diff --git a/Integrations/python/deephaven/doc/io/deephaven/engine/table/impl/by/IncrementalChunkedOperatorAggregationStateManager.json b/Integrations/python/deephaven/doc/io/deephaven/engine/table/impl/by/IncrementalChunkedOperatorAggregationStateManager.json index a474c384fb0..0af95dbe0d4 100644 --- a/Integrations/python/deephaven/doc/io/deephaven/engine/table/impl/by/IncrementalChunkedOperatorAggregationStateManager.json +++ b/Integrations/python/deephaven/doc/io/deephaven/engine/table/impl/by/IncrementalChunkedOperatorAggregationStateManager.json @@ -3,6 +3,7 @@ "methods": { "add": ":param bc: io.deephaven.util.SafeCloseable\n:param rowSequence: io.deephaven.engine.rowset.RowSequence\n:param sources: io.deephaven.engine.table.ColumnSource[]\n:param nextOutputPosition: org.apache.commons.lang3.mutable.MutableInt\n:param outputPositions: io.deephaven.chunk.WritableIntChunk", "addForUpdate": ":param bc: io.deephaven.util.SafeCloseable\n:param rowSequence: io.deephaven.engine.rowset.RowSequence\n:param sources: io.deephaven.engine.table.ColumnSource[]\n:param nextOutputPosition: org.apache.commons.lang3.mutable.MutableInt\n:param outputPositions: io.deephaven.chunk.WritableIntChunk\n:param reincarnatedPositions: io.deephaven.chunk.WritableIntChunk", + "beginUpdateCycle": "Allow our managers to do a little bit of work at the very start of the update cycle. We have this method so that\n even if nothing is to be done, we rehash a little bit on each cycle to avoid always rehashing when there is other\n work to be done.", "doRehash": ":param bc: io.deephaven.engine.table.impl.by.IncrementalChunkedOperatorAggregationStateManager.BuildContext", "findModifications": ":param pc: io.deephaven.util.SafeCloseable\n:param rowSequence: io.deephaven.engine.rowset.RowSequence\n:param sources: io.deephaven.engine.table.ColumnSource[]\n:param outputPositions: io.deephaven.chunk.WritableIntChunk", "findPositionForKey": ":param key: java.lang.Object\n:return: int", diff --git a/Integrations/python/deephaven/doc/io/deephaven/engine/table/impl/by/IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase.json b/Integrations/python/deephaven/doc/io/deephaven/engine/table/impl/by/IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase.json new file mode 100644 index 00000000000..0b063cd4178 --- /dev/null +++ b/Integrations/python/deephaven/doc/io/deephaven/engine/table/impl/by/IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase.json @@ -0,0 +1,16 @@ +{ + "className": "io.deephaven.engine.table.impl.by.IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase", + "methods": { + "add": ":param bc: io.deephaven.util.SafeCloseable\n:param rowSequence: io.deephaven.engine.rowset.RowSequence\n:param sources: io.deephaven.engine.table.ColumnSource[]\n:param nextOutputPosition: org.apache.commons.lang3.mutable.MutableInt\n:param outputPositions: io.deephaven.chunk.WritableIntChunk", + "addForUpdate": ":param bc: io.deephaven.util.SafeCloseable\n:param rowSequence: io.deephaven.engine.rowset.RowSequence\n:param sources: io.deephaven.engine.table.ColumnSource[]\n:param nextOutputPosition: org.apache.commons.lang3.mutable.MutableInt\n:param outputPositions: io.deephaven.chunk.WritableIntChunk\n:param reincarnatedPositions: io.deephaven.chunk.WritableIntChunk", + "beginUpdateCycle": "Allow our managers to do a little bit of work at the very start of the update cycle. We have this method so that\n even if nothing is to be done, we rehash a little bit on each cycle to avoid always rehashing when there is other\n work to be done.", + "findModifications": ":param pc: io.deephaven.util.SafeCloseable\n:param rowSequence: io.deephaven.engine.rowset.RowSequence\n:param sources: io.deephaven.engine.table.ColumnSource[]\n:param outputPositions: io.deephaven.chunk.WritableIntChunk", + "getKeyHashTableSources": ":return: io.deephaven.engine.table.ColumnSource[]", + "makeAggregationStateBuildContext": ":param buildSources: io.deephaven.engine.table.ColumnSource[]\n:param maxSize: long\n:return: io.deephaven.util.SafeCloseable", + "onNextChunk": ":param size: int", + "remove": ":param pc: io.deephaven.util.SafeCloseable\n:param rowSequence: io.deephaven.engine.rowset.RowSequence\n:param sources: io.deephaven.engine.table.ColumnSource[]\n:param outputPositions: io.deephaven.chunk.WritableIntChunk\n:param emptiedPositions: io.deephaven.chunk.WritableIntChunk", + "setRowSize": ":param outputPosition: int\n:param size: long" + }, + "path": "io.deephaven.engine.table.impl.by.IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase", + "typeName": "class" +} \ No newline at end of file diff --git a/Integrations/python/deephaven/doc/io/deephaven/engine/table/impl/by/IncrementalChunkedOperatorAggregationStateManagerTypedBase.json b/Integrations/python/deephaven/doc/io/deephaven/engine/table/impl/by/IncrementalChunkedOperatorAggregationStateManagerTypedBase.json index 89a497f2ca2..0385622293f 100644 --- a/Integrations/python/deephaven/doc/io/deephaven/engine/table/impl/by/IncrementalChunkedOperatorAggregationStateManagerTypedBase.json +++ b/Integrations/python/deephaven/doc/io/deephaven/engine/table/impl/by/IncrementalChunkedOperatorAggregationStateManagerTypedBase.json @@ -3,6 +3,7 @@ "methods": { "add": ":param bc: io.deephaven.util.SafeCloseable\n:param rowSequence: io.deephaven.engine.rowset.RowSequence\n:param sources: io.deephaven.engine.table.ColumnSource[]\n:param nextOutputPosition: org.apache.commons.lang3.mutable.MutableInt\n:param outputPositions: io.deephaven.chunk.WritableIntChunk", "addForUpdate": ":param bc: io.deephaven.util.SafeCloseable\n:param rowSequence: io.deephaven.engine.rowset.RowSequence\n:param sources: io.deephaven.engine.table.ColumnSource[]\n:param nextOutputPosition: org.apache.commons.lang3.mutable.MutableInt\n:param outputPositions: io.deephaven.chunk.WritableIntChunk\n:param reincarnatedPositions: io.deephaven.chunk.WritableIntChunk", + "beginUpdateCycle": "Allow our managers to do a little bit of work at the very start of the update cycle. We have this method so that\n even if nothing is to be done, we rehash a little bit on each cycle to avoid always rehashing when there is other\n work to be done.", "findModifications": ":param pc: io.deephaven.util.SafeCloseable\n:param rowSequence: io.deephaven.engine.rowset.RowSequence\n:param sources: io.deephaven.engine.table.ColumnSource[]\n:param outputPositions: io.deephaven.chunk.WritableIntChunk", "getKeyHashTableSources": ":return: io.deephaven.engine.table.ColumnSource[]", "makeAggregationStateBuildContext": ":param buildSources: io.deephaven.engine.table.ColumnSource[]\n:param maxSize: long\n:return: io.deephaven.util.SafeCloseable", diff --git a/Integrations/python/deephaven/doc/io/deephaven/engine/table/impl/by/IncrementalOperatorAggregationStateManager.json b/Integrations/python/deephaven/doc/io/deephaven/engine/table/impl/by/IncrementalOperatorAggregationStateManager.json index c7c30a2d549..b10f9cfa9dd 100644 --- a/Integrations/python/deephaven/doc/io/deephaven/engine/table/impl/by/IncrementalOperatorAggregationStateManager.json +++ b/Integrations/python/deephaven/doc/io/deephaven/engine/table/impl/by/IncrementalOperatorAggregationStateManager.json @@ -3,6 +3,7 @@ "methods": { "add": ":param bc: io.deephaven.util.SafeCloseable\n:param rowSequence: io.deephaven.engine.rowset.RowSequence\n:param sources: io.deephaven.engine.table.ColumnSource[]\n:param nextOutputPosition: org.apache.commons.lang3.mutable.MutableInt\n:param outputPositions: io.deephaven.chunk.WritableIntChunk", "addForUpdate": ":param bc: io.deephaven.util.SafeCloseable\n:param rowSequence: io.deephaven.engine.rowset.RowSequence\n:param sources: io.deephaven.engine.table.ColumnSource[]\n:param nextOutputPosition: org.apache.commons.lang3.mutable.MutableInt\n:param outputPositions: io.deephaven.chunk.WritableIntChunk\n:param reincarnatedPositions: io.deephaven.chunk.WritableIntChunk", + "beginUpdateCycle": "Allow our managers to do a little bit of work at the very start of the update cycle. We have this method so that\n even if nothing is to be done, we rehash a little bit on each cycle to avoid always rehashing when there is other\n work to be done.", "findModifications": ":param pc: io.deephaven.util.SafeCloseable\n:param rowSequence: io.deephaven.engine.rowset.RowSequence\n:param sources: io.deephaven.engine.table.ColumnSource[]\n:param outputPositions: io.deephaven.chunk.WritableIntChunk", "findPositionForKey": ":param key: java.lang.Object\n:return: int", "getKeyHashTableSources": ":return: io.deephaven.engine.table.ColumnSource[]", diff --git a/Integrations/python/deephaven/doc/io/deephaven/engine/table/impl/by/OperatorAggregationStateManagerOpenAddressedAlternateBase.json b/Integrations/python/deephaven/doc/io/deephaven/engine/table/impl/by/OperatorAggregationStateManagerOpenAddressedAlternateBase.json new file mode 100644 index 00000000000..f1c401b2999 --- /dev/null +++ b/Integrations/python/deephaven/doc/io/deephaven/engine/table/impl/by/OperatorAggregationStateManagerOpenAddressedAlternateBase.json @@ -0,0 +1,11 @@ +{ + "className": "io.deephaven.engine.table.impl.by.OperatorAggregationStateManagerOpenAddressedAlternateBase", + "methods": { + "doRehash": ":param fullRehash: (boolean) - should we rehash the entire table (if false, we rehash incrementally)\n:param rehashCredits: (org.apache.commons.lang3.mutable.MutableInt) - the number of entries this operation has rehashed (input/output)\n:param nextChunkSize: (int) - the size of the chunk we are processing\n:return: (boolean) true if a front migration is required", + "findPositionForKey": ":param key: java.lang.Object\n:return: int", + "makeProbeContext": ":param buildSources: io.deephaven.engine.table.ColumnSource[]\n:param maxSize: long\n:return: io.deephaven.engine.table.impl.by.OperatorAggregationStateManagerOpenAddressedAlternateBase.ProbeContext", + "rehashRequired": ":param nextChunkSize: int\n:return: boolean" + }, + "path": "io.deephaven.engine.table.impl.by.OperatorAggregationStateManagerOpenAddressedAlternateBase", + "typeName": "class" +} \ No newline at end of file diff --git a/Integrations/python/deephaven/doc/io/deephaven/engine/table/impl/by/OperatorAggregationStateManagerOpenAddressedAlternateBase/BuildContext.json b/Integrations/python/deephaven/doc/io/deephaven/engine/table/impl/by/OperatorAggregationStateManagerOpenAddressedAlternateBase/BuildContext.json new file mode 100644 index 00000000000..f809cd44058 --- /dev/null +++ b/Integrations/python/deephaven/doc/io/deephaven/engine/table/impl/by/OperatorAggregationStateManagerOpenAddressedAlternateBase/BuildContext.json @@ -0,0 +1,8 @@ +{ + "className": "io.deephaven.engine.table.impl.by.OperatorAggregationStateManagerOpenAddressedAlternateBase$BuildContext", + "methods": { + "close": "Release any resources associated with this context. The context should not be used afterwards." + }, + "path": "io.deephaven.engine.table.impl.by.OperatorAggregationStateManagerOpenAddressedAlternateBase.BuildContext", + "typeName": "class" +} \ No newline at end of file diff --git a/Integrations/python/deephaven/doc/io/deephaven/engine/table/impl/by/OperatorAggregationStateManagerOpenAddressedAlternateBase/BuildHandler.json b/Integrations/python/deephaven/doc/io/deephaven/engine/table/impl/by/OperatorAggregationStateManagerOpenAddressedAlternateBase/BuildHandler.json new file mode 100644 index 00000000000..d9fefb45334 --- /dev/null +++ b/Integrations/python/deephaven/doc/io/deephaven/engine/table/impl/by/OperatorAggregationStateManagerOpenAddressedAlternateBase/BuildHandler.json @@ -0,0 +1,8 @@ +{ + "className": "io.deephaven.engine.table.impl.by.OperatorAggregationStateManagerOpenAddressedAlternateBase$BuildHandler", + "methods": { + "doBuild": ":param chunkOk: io.deephaven.engine.rowset.RowSequence\n:param sourceKeyChunks: io.deephaven.chunk.Chunk[]" + }, + "path": "io.deephaven.engine.table.impl.by.OperatorAggregationStateManagerOpenAddressedAlternateBase.BuildHandler", + "typeName": "interface" +} \ No newline at end of file diff --git a/Integrations/python/deephaven/doc/io/deephaven/engine/table/impl/by/OperatorAggregationStateManagerOpenAddressedAlternateBase/ProbeContext.json b/Integrations/python/deephaven/doc/io/deephaven/engine/table/impl/by/OperatorAggregationStateManagerOpenAddressedAlternateBase/ProbeContext.json new file mode 100644 index 00000000000..4cc664be16a --- /dev/null +++ b/Integrations/python/deephaven/doc/io/deephaven/engine/table/impl/by/OperatorAggregationStateManagerOpenAddressedAlternateBase/ProbeContext.json @@ -0,0 +1,8 @@ +{ + "className": "io.deephaven.engine.table.impl.by.OperatorAggregationStateManagerOpenAddressedAlternateBase$ProbeContext", + "methods": { + "close": "Release any resources associated with this context. The context should not be used afterwards." + }, + "path": "io.deephaven.engine.table.impl.by.OperatorAggregationStateManagerOpenAddressedAlternateBase.ProbeContext", + "typeName": "class" +} \ No newline at end of file diff --git a/Integrations/python/deephaven/doc/io/deephaven/engine/table/impl/by/OperatorAggregationStateManagerOpenAddressedAlternateBase/ProbeHandler.json b/Integrations/python/deephaven/doc/io/deephaven/engine/table/impl/by/OperatorAggregationStateManagerOpenAddressedAlternateBase/ProbeHandler.json new file mode 100644 index 00000000000..52f6b3f1e09 --- /dev/null +++ b/Integrations/python/deephaven/doc/io/deephaven/engine/table/impl/by/OperatorAggregationStateManagerOpenAddressedAlternateBase/ProbeHandler.json @@ -0,0 +1,8 @@ +{ + "className": "io.deephaven.engine.table.impl.by.OperatorAggregationStateManagerOpenAddressedAlternateBase$ProbeHandler", + "methods": { + "doProbe": ":param chunkOk: io.deephaven.engine.rowset.RowSequence\n:param sourceKeyChunks: io.deephaven.chunk.Chunk[]" + }, + "path": "io.deephaven.engine.table.impl.by.OperatorAggregationStateManagerOpenAddressedAlternateBase.ProbeHandler", + "typeName": "interface" +} \ No newline at end of file diff --git a/Integrations/python/deephaven/doc/io/deephaven/engine/table/impl/by/alternatingcolumnsource/AlternatingColumnSource.json b/Integrations/python/deephaven/doc/io/deephaven/engine/table/impl/by/alternatingcolumnsource/AlternatingColumnSource.json new file mode 100644 index 00000000000..251db7d390c --- /dev/null +++ b/Integrations/python/deephaven/doc/io/deephaven/engine/table/impl/by/alternatingcolumnsource/AlternatingColumnSource.json @@ -0,0 +1,41 @@ +{ + "className": "io.deephaven.engine.table.impl.by.alternatingcolumnsource.AlternatingColumnSource", + "methods": { + "allowsReinterpret": "Test if a reinterpret call will succeed.\n\nNote: Java generics information - \n\n:param alternateDataType: (java.lang.Class) - The alternative type to consider\n:return: (boolean) If a reinterpret on this column source with the supplied alternateDataType will succeed.", + "fillChunk": "Populates the given destination chunk with data corresponding to the keys from the given RowSequence.\n\n:param context: (io.deephaven.engine.table.ChunkSource.FillContext) - A context containing all mutable/state related data used in retrieving the Chunk.\n:param destination: (io.deephaven.chunk.WritableChunk) - The chunk to be populated according to rowSequence. No assumptions shall be made about\n the size of the chunk shall be made. The chunk will be populated from position [0,rowSequence.size()).\n:param rowSequence: (io.deephaven.engine.rowset.RowSequence) - An RowSequence representing the keys to be fetched", + "fillChunkUnordered": "Populates a contiguous portion of the given destination chunk with data corresponding to the keys from the given\n LongChunk.\n\n:param context: (io.deephaven.engine.table.ChunkSource.FillContext) - A context containing all mutable/state related data used in retrieving the Chunk.\n:param dest: (io.deephaven.chunk.WritableChunk) - The chunk to be populated according to keys\n:param keys: (io.deephaven.chunk.LongChunk) - A chunk of individual, not assumed to be ordered keys to be fetched", + "fillPrevChunk": "Populates the given destination chunk with data corresponding to the keys from the given RowSequence.\n\n:param context: (io.deephaven.engine.table.ChunkSource.FillContext) - A context containing all mutable/state related data used in retrieving the Chunk.\n:param destination: (io.deephaven.chunk.WritableChunk) - The chunk to be populated according to rowSequence. No assumptions shall be made\n about the size of the chunk shall be made. The chunk will be populated from position\n [0,rowSequence.size()).\n:param rowSequence: (io.deephaven.engine.rowset.RowSequence) - An RowSequence representing the keys to be fetched", + "fillPrevChunkUnordered": "Populates a contiguous portion of the given destination chunk with prev data corresponding to the keys from the\n given LongChunk.\n\n:param context: (io.deephaven.engine.table.ChunkSource.FillContext) - A context containing all mutable/state related data used in retrieving the Chunk.\n:param dest: (io.deephaven.chunk.WritableChunk) - The chunk to be populated according to keys\n:param keys: (io.deephaven.chunk.LongChunk) - A chunk of individual, not assumed to be ordered keys to be fetched", + "get": ":param index: long\n:return: AlternatingColumnSource.DATA_TYPE", + "getBoolean": ":param index: long\n:return: java.lang.Boolean", + "getByte": ":param index: long\n:return: byte", + "getChar": ":param index: long\n:return: char", + "getChunk": "Returns a chunk of data corresponding to the keys from the given RowSequence.\n\n:param context: (io.deephaven.engine.table.ChunkSource.GetContext) - A context containing all mutable/state related data used in retrieving the Chunk. In particular,\n the Context may be used to provide a Chunk data pool\n:param rowSequence: (io.deephaven.engine.rowset.RowSequence) - An RowSequence representing the keys to be fetched\n:return: (io.deephaven.chunk.Chunk) A chunk of data corresponding to the keys from the given RowSequence", + "getDouble": ":param index: long\n:return: double", + "getFloat": ":param index: long\n:return: float", + "getInt": ":param index: long\n:return: int", + "getLong": ":param index: long\n:return: long", + "getPrev": ":param index: long\n:return: AlternatingColumnSource.DATA_TYPE", + "getPrevBoolean": ":param index: long\n:return: java.lang.Boolean", + "getPrevByte": ":param index: long\n:return: byte", + "getPrevChar": ":param index: long\n:return: char", + "getPrevChunk": "Returns a chunk of previous data corresponding to the keys from the given RowSequence.\n\n:param context: (io.deephaven.engine.table.ChunkSource.GetContext) - A context containing all mutable/state related data used in retrieving the Chunk. In\n particular, the Context may be used to provide a Chunk data pool\n:param rowSequence: (io.deephaven.engine.rowset.RowSequence) - An RowSequence representing the keys to be fetched\n:return: (io.deephaven.chunk.Chunk) A chunk of data corresponding to the keys from the given RowSequence", + "getPrevDouble": ":param index: long\n:return: double", + "getPrevFloat": ":param index: long\n:return: float", + "getPrevInt": ":param index: long\n:return: int", + "getPrevLong": ":param index: long\n:return: long", + "getPrevShort": ":param index: long\n:return: short", + "getShort": ":param index: long\n:return: short", + "innerLocation": ":param hashSlot: long\n:return: int", + "isAlternate": ":param index: long\n:return: boolean", + "isImmutable": "Determine if this column source is immutable, meaning that the values at a given row key never change.\n\n:return: (boolean) true if the values at a given row key of the column source never change, false otherwise", + "makeFillContext": "Allocate a new ChunkSource.FillContext for filling chunks from this FillContextMaker, typically a\n ChunkSource.\n\n:param chunkCapacity: (int) - The maximum size of any WritableChunk that will be filled with this context\n:param sharedContext: (io.deephaven.engine.table.SharedContext) - Shared store of intermediate results.\n:return: (io.deephaven.engine.table.ChunkSource.FillContext) A context for use with fill operations", + "makeGetContext": "Allocate a new ChunkSource.GetContext for retrieving chunks from this GetContextMaker, typically\n a ChunkSource.\n\n:param chunkCapacity: (int) - The maximum size required for any WritableChunk allocated as part of the result.\n:param sharedContext: (io.deephaven.engine.table.SharedContext) - Shared store of intermediate results.\n:return: (io.deephaven.engine.table.ChunkSource.GetContext) A context for use with get operations", + "providesFillUnordered": "Returns true if this column source can efficiently provide an unordered fill.\n\n If this method returns false, then fillChunkUnordered and fillPrevChunkUnordered may throw an\n UnsupportedOperationException.\n\n:return: (boolean) if this column source can provide an unordered fill", + "setSources": ":param mainSource: io.deephaven.engine.table.ColumnSource\n:param alternateSource: io.deephaven.engine.table.ColumnSource", + "startTrackingPrevValues": "ColumnSource implementations that track previous values have the option to not actually start tracking previous\n values until this method is called. This is an option, not an obligation: some simple ColumnSource\n implementations (like TSingleValueSource for various T) always track previous values; other implementations (like\n PrevColumnSource) never do; some (like TArrayColumnSource) only start tracking once this method is called.\n\n An immutable column source can not have distinct prev values; therefore it is implemented as a no-op." + }, + "path": "io.deephaven.engine.table.impl.by.alternatingcolumnsource.AlternatingColumnSource", + "text": "ColumnSource implementation that delegates to the main and alternate sources for our incremental open\n addressed hash table key columns that swap back and forth between a \"main\" and \"alternate\" source. Note that the main\n and alternate swap back and forth, from the perspective of this column source the main source is addressed by zero;\n and the alternate source is addressed starting at ALTERNATE_SWITCH_MASK. Neither source may have addresses\n greater than ALTERNATE_INNER_MASK.", + "typeName": "class" +} \ No newline at end of file diff --git a/Integrations/python/deephaven/doc/io/deephaven/engine/table/impl/by/alternatingcolumnsource/ByteAlternatingColumnSourceUnorderedMergeKernel.json b/Integrations/python/deephaven/doc/io/deephaven/engine/table/impl/by/alternatingcolumnsource/ByteAlternatingColumnSourceUnorderedMergeKernel.json new file mode 100644 index 00000000000..221c76cdaf6 --- /dev/null +++ b/Integrations/python/deephaven/doc/io/deephaven/engine/table/impl/by/alternatingcolumnsource/ByteAlternatingColumnSourceUnorderedMergeKernel.json @@ -0,0 +1,8 @@ +{ + "className": "io.deephaven.engine.table.impl.by.alternatingcolumnsource.ByteAlternatingColumnSourceUnorderedMergeKernel", + "methods": { + "mergeContext": ":param dest: io.deephaven.chunk.WritableChunk\n:param outerKeys: io.deephaven.chunk.LongChunk\n:param src: io.deephaven.chunk.Chunk\n:param alternatePosition: int" + }, + "path": "io.deephaven.engine.table.impl.by.alternatingcolumnsource.ByteAlternatingColumnSourceUnorderedMergeKernel", + "typeName": "class" +} \ No newline at end of file diff --git a/Integrations/python/deephaven/doc/io/deephaven/engine/table/impl/by/alternatingcolumnsource/CharAlternatingColumnSourceUnorderedMergeKernel.json b/Integrations/python/deephaven/doc/io/deephaven/engine/table/impl/by/alternatingcolumnsource/CharAlternatingColumnSourceUnorderedMergeKernel.json new file mode 100644 index 00000000000..6918298c18d --- /dev/null +++ b/Integrations/python/deephaven/doc/io/deephaven/engine/table/impl/by/alternatingcolumnsource/CharAlternatingColumnSourceUnorderedMergeKernel.json @@ -0,0 +1,8 @@ +{ + "className": "io.deephaven.engine.table.impl.by.alternatingcolumnsource.CharAlternatingColumnSourceUnorderedMergeKernel", + "methods": { + "mergeContext": ":param dest: io.deephaven.chunk.WritableChunk\n:param outerKeys: io.deephaven.chunk.LongChunk\n:param src: io.deephaven.chunk.Chunk\n:param alternatePosition: int" + }, + "path": "io.deephaven.engine.table.impl.by.alternatingcolumnsource.CharAlternatingColumnSourceUnorderedMergeKernel", + "typeName": "class" +} \ No newline at end of file diff --git a/Integrations/python/deephaven/doc/io/deephaven/engine/table/impl/by/alternatingcolumnsource/DoubleAlternatingColumnSourceUnorderedMergeKernel.json b/Integrations/python/deephaven/doc/io/deephaven/engine/table/impl/by/alternatingcolumnsource/DoubleAlternatingColumnSourceUnorderedMergeKernel.json new file mode 100644 index 00000000000..a4196d4e7da --- /dev/null +++ b/Integrations/python/deephaven/doc/io/deephaven/engine/table/impl/by/alternatingcolumnsource/DoubleAlternatingColumnSourceUnorderedMergeKernel.json @@ -0,0 +1,8 @@ +{ + "className": "io.deephaven.engine.table.impl.by.alternatingcolumnsource.DoubleAlternatingColumnSourceUnorderedMergeKernel", + "methods": { + "mergeContext": ":param dest: io.deephaven.chunk.WritableChunk\n:param outerKeys: io.deephaven.chunk.LongChunk\n:param src: io.deephaven.chunk.Chunk\n:param alternatePosition: int" + }, + "path": "io.deephaven.engine.table.impl.by.alternatingcolumnsource.DoubleAlternatingColumnSourceUnorderedMergeKernel", + "typeName": "class" +} \ No newline at end of file diff --git a/Integrations/python/deephaven/doc/io/deephaven/engine/table/impl/by/alternatingcolumnsource/FloatAlternatingColumnSourceUnorderedMergeKernel.json b/Integrations/python/deephaven/doc/io/deephaven/engine/table/impl/by/alternatingcolumnsource/FloatAlternatingColumnSourceUnorderedMergeKernel.json new file mode 100644 index 00000000000..4bd5739c5e1 --- /dev/null +++ b/Integrations/python/deephaven/doc/io/deephaven/engine/table/impl/by/alternatingcolumnsource/FloatAlternatingColumnSourceUnorderedMergeKernel.json @@ -0,0 +1,8 @@ +{ + "className": "io.deephaven.engine.table.impl.by.alternatingcolumnsource.FloatAlternatingColumnSourceUnorderedMergeKernel", + "methods": { + "mergeContext": ":param dest: io.deephaven.chunk.WritableChunk\n:param outerKeys: io.deephaven.chunk.LongChunk\n:param src: io.deephaven.chunk.Chunk\n:param alternatePosition: int" + }, + "path": "io.deephaven.engine.table.impl.by.alternatingcolumnsource.FloatAlternatingColumnSourceUnorderedMergeKernel", + "typeName": "class" +} \ No newline at end of file diff --git a/Integrations/python/deephaven/doc/io/deephaven/engine/table/impl/by/alternatingcolumnsource/IntAlternatingColumnSourceUnorderedMergeKernel.json b/Integrations/python/deephaven/doc/io/deephaven/engine/table/impl/by/alternatingcolumnsource/IntAlternatingColumnSourceUnorderedMergeKernel.json new file mode 100644 index 00000000000..fd3d2a2e789 --- /dev/null +++ b/Integrations/python/deephaven/doc/io/deephaven/engine/table/impl/by/alternatingcolumnsource/IntAlternatingColumnSourceUnorderedMergeKernel.json @@ -0,0 +1,8 @@ +{ + "className": "io.deephaven.engine.table.impl.by.alternatingcolumnsource.IntAlternatingColumnSourceUnorderedMergeKernel", + "methods": { + "mergeContext": ":param dest: io.deephaven.chunk.WritableChunk\n:param outerKeys: io.deephaven.chunk.LongChunk\n:param src: io.deephaven.chunk.Chunk\n:param alternatePosition: int" + }, + "path": "io.deephaven.engine.table.impl.by.alternatingcolumnsource.IntAlternatingColumnSourceUnorderedMergeKernel", + "typeName": "class" +} \ No newline at end of file diff --git a/Integrations/python/deephaven/doc/io/deephaven/engine/table/impl/by/alternatingcolumnsource/LongAlternatingColumnSourceUnorderedMergeKernel.json b/Integrations/python/deephaven/doc/io/deephaven/engine/table/impl/by/alternatingcolumnsource/LongAlternatingColumnSourceUnorderedMergeKernel.json new file mode 100644 index 00000000000..72759d08d4c --- /dev/null +++ b/Integrations/python/deephaven/doc/io/deephaven/engine/table/impl/by/alternatingcolumnsource/LongAlternatingColumnSourceUnorderedMergeKernel.json @@ -0,0 +1,8 @@ +{ + "className": "io.deephaven.engine.table.impl.by.alternatingcolumnsource.LongAlternatingColumnSourceUnorderedMergeKernel", + "methods": { + "mergeContext": ":param dest: io.deephaven.chunk.WritableChunk\n:param outerKeys: io.deephaven.chunk.LongChunk\n:param src: io.deephaven.chunk.Chunk\n:param alternatePosition: int" + }, + "path": "io.deephaven.engine.table.impl.by.alternatingcolumnsource.LongAlternatingColumnSourceUnorderedMergeKernel", + "typeName": "class" +} \ No newline at end of file diff --git a/Integrations/python/deephaven/doc/io/deephaven/engine/table/impl/by/alternatingcolumnsource/ObjectAlternatingColumnSourceUnorderedMergeKernel.json b/Integrations/python/deephaven/doc/io/deephaven/engine/table/impl/by/alternatingcolumnsource/ObjectAlternatingColumnSourceUnorderedMergeKernel.json new file mode 100644 index 00000000000..570e2f2a887 --- /dev/null +++ b/Integrations/python/deephaven/doc/io/deephaven/engine/table/impl/by/alternatingcolumnsource/ObjectAlternatingColumnSourceUnorderedMergeKernel.json @@ -0,0 +1,8 @@ +{ + "className": "io.deephaven.engine.table.impl.by.alternatingcolumnsource.ObjectAlternatingColumnSourceUnorderedMergeKernel", + "methods": { + "mergeContext": ":param dest: io.deephaven.chunk.WritableChunk\n:param outerKeys: io.deephaven.chunk.LongChunk\n:param src: io.deephaven.chunk.Chunk\n:param alternatePosition: int" + }, + "path": "io.deephaven.engine.table.impl.by.alternatingcolumnsource.ObjectAlternatingColumnSourceUnorderedMergeKernel", + "typeName": "class" +} \ No newline at end of file diff --git a/Integrations/python/deephaven/doc/io/deephaven/engine/table/impl/by/alternatingcolumnsource/ShortAlternatingColumnSourceUnorderedMergeKernel.json b/Integrations/python/deephaven/doc/io/deephaven/engine/table/impl/by/alternatingcolumnsource/ShortAlternatingColumnSourceUnorderedMergeKernel.json new file mode 100644 index 00000000000..233bfdf93f5 --- /dev/null +++ b/Integrations/python/deephaven/doc/io/deephaven/engine/table/impl/by/alternatingcolumnsource/ShortAlternatingColumnSourceUnorderedMergeKernel.json @@ -0,0 +1,8 @@ +{ + "className": "io.deephaven.engine.table.impl.by.alternatingcolumnsource.ShortAlternatingColumnSourceUnorderedMergeKernel", + "methods": { + "mergeContext": ":param dest: io.deephaven.chunk.WritableChunk\n:param outerKeys: io.deephaven.chunk.LongChunk\n:param src: io.deephaven.chunk.Chunk\n:param alternatePosition: int" + }, + "path": "io.deephaven.engine.table.impl.by.alternatingcolumnsource.ShortAlternatingColumnSourceUnorderedMergeKernel", + "typeName": "class" +} \ No newline at end of file diff --git a/Integrations/python/deephaven/doc/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/TypedHashDispatcher.json b/Integrations/python/deephaven/doc/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/TypedHashDispatcher.json new file mode 100644 index 00000000000..6fa90011244 --- /dev/null +++ b/Integrations/python/deephaven/doc/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/TypedHashDispatcher.json @@ -0,0 +1,9 @@ +{ + "className": "io.deephaven.engine.table.impl.by.typed.incopenagg.gen.TypedHashDispatcher", + "methods": { + "dispatch": ":param tableKeySources: io.deephaven.engine.table.ColumnSource[]\n:param tableSize: int\n:param maximumLoadFactor: double\n:param targetLoadFactor: double\n:return: io.deephaven.engine.table.impl.by.IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase" + }, + "path": "io.deephaven.engine.table.impl.by.typed.incopenagg.gen.TypedHashDispatcher", + "text": "The TypedHashDispatcher returns a pre-generated and precompiled hasher instance suitable for the provided column sources, or null if there is not a precompiled hasher suitable for the specified sources.", + "typeName": "class" +} \ No newline at end of file diff --git a/Integrations/python/deephaven/doc/io/deephaven/engine/table/impl/sources/AbstractLongArraySource.json b/Integrations/python/deephaven/doc/io/deephaven/engine/table/impl/sources/AbstractLongArraySource.json index 0c5ae567503..6c5882c7452 100644 --- a/Integrations/python/deephaven/doc/io/deephaven/engine/table/impl/sources/AbstractLongArraySource.json +++ b/Integrations/python/deephaven/doc/io/deephaven/engine/table/impl/sources/AbstractLongArraySource.json @@ -6,6 +6,7 @@ "fillFromChunk": "Our default, inefficient, implementation. Inheritors who care should provide a better implementation.\n\n:param context: (io.deephaven.engine.table.ChunkSink.FillFromContext) - A context containing all mutable/state related data used in writing the Chunk.\n:param src: (io.deephaven.chunk.Chunk) - The source of the data rowSequence\n:param rowSequence: (io.deephaven.engine.rowset.RowSequence) - An RowSequence representing the keys to be written", "fillFromChunkUnordered": "Fills the ChunkSink with data from the source, with data corresponding to the keys from the given key chunk.\n\n:param context: (io.deephaven.engine.table.ChunkSink.FillFromContext) - A context containing all mutable/state related data used in writing the Chunk.\n:param src: (io.deephaven.chunk.Chunk) - The source of the data RowSequence\n:param keys: (io.deephaven.chunk.LongChunk) - A LongChunk representing the keys to be written", "fillPrevChunk": "Populates the given destination chunk with data corresponding to the keys from the given RowSequence.\n\n:param context: (io.deephaven.engine.table.ChunkSource.FillContext) - A context containing all mutable/state related data used in retrieving the Chunk.\n:param destination: (io.deephaven.chunk.WritableChunk) - The chunk to be populated according to rowSequence. No assumptions shall be made\n about the size of the chunk shall be made. The chunk will be populated from position\n [0,rowSequence.size()).\n:param rowSequence: (io.deephaven.engine.rowset.RowSequence) - An RowSequence representing the keys to be fetched", + "getAndAddUnsafe": ":param index: long\n:param addend: long\n:return: long", "getAndSetUnsafe": ":param index: long\n:param newValue: long\n:return: long", "getCapacity": "Get the capacity of this column source. This number is one higher than the highest key that may be accessed (read\n or written).\n\n:return: (long) The capacity of this column source", "getLong": ":param index: long\n:return: long", diff --git a/engine/api/src/main/java/io/deephaven/engine/table/SharedContext.java b/engine/api/src/main/java/io/deephaven/engine/table/SharedContext.java index 9658d9c6ac3..b5b8fb1484e 100644 --- a/engine/api/src/main/java/io/deephaven/engine/table/SharedContext.java +++ b/engine/api/src/main/java/io/deephaven/engine/table/SharedContext.java @@ -31,11 +31,9 @@ public class SharedContext implements ResettableContext { /** * The entries in this shared context. */ - private final Map entries; + private Map entries; - protected SharedContext() { - entries = new HashMap<>(); - } + protected SharedContext() {} /** * Key marker interface. @@ -59,6 +57,9 @@ public interface Key { */ public final > V getOrCreate(final K key, @NotNull final Supplier valueFactory) { + if (entries == null) { + entries = new HashMap<>(); + } // noinspection unchecked return (V) entries.computeIfAbsent(key, k -> valueFactory.get()); } @@ -74,6 +75,9 @@ public final > V getOrCreate(final @Override @OverridingMethodsMustInvokeSuper public void reset() { + if (entries == null) { + return; + } entries.values().forEach(ResettableContext::reset); } @@ -88,6 +92,9 @@ public void reset() { @Override @OverridingMethodsMustInvokeSuper public void close() { + if (entries == null) { + return; + } entries.values().forEach(SafeCloseable::close); entries.clear(); } diff --git a/engine/table/build.gradle b/engine/table/build.gradle index 8a159167e0d..444c7c793fc 100644 --- a/engine/table/build.gradle +++ b/engine/table/build.gradle @@ -84,6 +84,7 @@ spotless { '**/*Object*.java', '**/*StateManager.java', '**/incagg/gen/*.java', + '**/incopenagg/gen/*.java', '**/staticagg/gen/*.java', '**/staticopenagg/gen/*.java', 'src/main/java/io/deephaven/engine/table/impl/SymbolTableCombiner.java', diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/ChunkedOperatorAggregationHelper.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/ChunkedOperatorAggregationHelper.java index 0516b15ed94..1b1cff466eb 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/ChunkedOperatorAggregationHelper.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/ChunkedOperatorAggregationHelper.java @@ -62,6 +62,10 @@ public class ChunkedOperatorAggregationHelper { Configuration.getInstance().getBooleanWithDefault( "ChunkedOperatorAggregationHelper.useOpenAddressedStateManager", true); + static boolean USE_BITMAP_MODIFIED_STATES_BUILDER = + Configuration.getInstance().getBooleanWithDefault( + "ChunkedOperatorAggregationHelper.useBitmapModifiedStatesBuilder", + true); public static QueryTable aggregation(AggregationContextFactory aggregationContextFactory, QueryTable queryTable, SelectColumn[] groupByColumns) { @@ -128,7 +132,13 @@ private static QueryTable aggregation(AggregationControl control, SwapListener s final OperatorAggregationStateManager stateManager; final IncrementalOperatorAggregationStateManager incrementalStateManager; if (withView.isRefreshing()) { - if (USE_TYPED_STATE_MANAGER) { + if (USE_OPEN_ADDRESSED_STATE_MANAGER) { + stateManager = incrementalStateManager = TypedHasherFactory.make( + IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase.class, + reinterpretedKeySources, + control.initialHashTableSize(withView), control.getMaximumLoadFactor(), + control.getTargetLoadFactor()); + } else if (USE_TYPED_STATE_MANAGER) { stateManager = incrementalStateManager = TypedHasherFactory.make( IncrementalChunkedOperatorAggregationStateManagerTypedBase.class, reinterpretedKeySources, control.initialHashTableSize(withView), control.getMaximumLoadFactor(), @@ -225,6 +235,8 @@ private static QueryTable aggregation(AggregationControl control, SwapListener s @Override public void onUpdate(@NotNull final TableUpdate upstream) { + incrementalStateManager.beginUpdateCycle(); + final TableUpdate upstreamToUse = isStream ? adjustForStreaming(upstream) : upstream; if (upstreamToUse.empty()) { return; @@ -413,7 +425,11 @@ private KeyedUpdateContext(@NotNull final AggregationContext ac, final int chunkSize = Math.max(buildChunkSize, probeChunkSize); emptiedStatesBuilder = RowSetFactory.builderRandom(); - modifiedStatesBuilder = RowSetFactory.builderRandom(); + if (USE_BITMAP_MODIFIED_STATES_BUILDER) { + modifiedStatesBuilder = new BitmapRandomBuilder(outputPosition.intValue()); + } else { + modifiedStatesBuilder = RowSetFactory.builderRandom(); + } reincarnatedStatesBuilder = RowSetFactory.builderRandom(); modifiedOperators = new boolean[ac.size()]; @@ -2213,4 +2229,76 @@ private static Chunk fetchValues(boolean usePrev, RowSequence public static int chunkSize(long size) { return (int) Math.min(size, CHUNK_SIZE); } + + /** + * The output RowSet of an aggregation is fairly special. It is always from zero to the number of output rows, and + * while modifying states we randomly add rows to it, potentially touching the same state many times. The normal + * index random builder does not guarantee those values are de-duplicated and requires O(lg n) operations for each + * insertion and building the RowSet. + * + * This version is O(1) for updating a modified slot, then linear in the number of output positions (not the number + * of result values) to build the RowSet. The memory usage is 1 bit per output position, vs. the standard builder is + * 128 bits per used value (though with the possibility of collapsing adjacent ranges when they are modified + * back-to-back). For random access patterns, this version will be more efficient; for friendly patterns the default + * random builder is likely more efficient. + * + * We also know that we will only modify the rows that existed when we start, so that we can clamp the maximum key + * for the builder to the maximum output position without loss of fidelity. + */ + private static class BitmapRandomBuilder implements RowSetBuilderRandom { + final int maxKey; + int firstUsed = Integer.MAX_VALUE; + int lastUsed = -1; + long[] bitset; + + private BitmapRandomBuilder(int maxKey) { + this.maxKey = maxKey; + } + + private static int rowKeyToArrayIndex(long rowKey) { + return (int) (rowKey / 64); + } + + @Override + public WritableRowSet build() { + final RowSetBuilderSequential seqBuilder = RowSetFactory.builderSequential(); + for (int ii = firstUsed; ii <= lastUsed; ++ii) { + long word = bitset[ii]; + long rowKey = ii * 64L; + + while (word != 0) { + if ((word & 1) != 0) { + seqBuilder.appendKey(rowKey); + } + rowKey++; + word >>>= 1; + } + } + return seqBuilder.build(); + } + + @Override + public void addKey(long rowKey) { + if (rowKey >= maxKey) { + return; + } + int index = rowKeyToArrayIndex(rowKey); + if (bitset == null) { + final int maxSize = (maxKey + 63) / 64; + bitset = new long[Math.min(maxSize, (index + 1) * 2)]; + } else if (index >= bitset.length) { + final int maxSize = (maxKey + 63) / 64; + bitset = Arrays.copyOf(bitset, Math.min(maxSize, Math.max(bitset.length * 2, index + 1))); + } + bitset[index] |= 1L << rowKey; + firstUsed = Math.min(index, firstUsed); + lastUsed = Math.max(index, lastUsed); + } + + @Override + public void addRange(long firstRowKey, long lastRowKey) { + throw new UnsupportedOperationException(); + } + } } + diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/CountAggregationOperator.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/CountAggregationOperator.java index 7eedb5b494d..9264b2a2340 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/CountAggregationOperator.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/CountAggregationOperator.java @@ -30,8 +30,7 @@ public void addChunk(BucketedContext context, Chunk values, final int startPosition = startPositions.get(ii); final long destination = destinations.get(startPosition); final long newCount = length.get(ii); - final long oldCount = countColumnSource.getUnsafe(destination); - countColumnSource.set(destination, NullSafeAddition.plusLong(oldCount, newCount)); + countColumnSource.getAndAddUnsafe(destination, newCount); } stateModified.fillWithValue(0, startPositions.size(), true); } @@ -45,8 +44,7 @@ public void removeChunk(BucketedContext context, Chunk values, final int startPosition = startPositions.get(ii); final long destination = destinations.get(startPosition); final long newCount = length.get(ii); - final long oldCount = countColumnSource.getUnsafe(destination); - countColumnSource.set(destination, NullSafeAddition.minusLong(oldCount, newCount)); + countColumnSource.getAndAddUnsafe(destination, -newCount); } stateModified.fillWithValue(0, startPositions.size(), true); } @@ -54,16 +52,14 @@ public void removeChunk(BucketedContext context, Chunk values, @Override public boolean addChunk(SingletonContext context, int chunkSize, Chunk values, LongChunk inputRowKeys, long destination) { - final long oldCount = countColumnSource.getUnsafe(destination); - countColumnSource.set(destination, NullSafeAddition.plusLong(oldCount, chunkSize)); + countColumnSource.getAndAddUnsafe(destination, chunkSize); return true; } @Override public boolean removeChunk(SingletonContext context, int chunkSize, Chunk values, LongChunk inputRowKeys, long destination) { - final long oldCount = countColumnSource.getUnsafe(destination); - countColumnSource.set(destination, NullSafeAddition.minusLong(oldCount, chunkSize)); + countColumnSource.getAndAddUnsafe(destination, -chunkSize); return true; } @@ -83,7 +79,7 @@ public boolean modifyChunk(SingletonContext context, int chunkSize, Chunk chunkPositi } // region build wrappers + @Override + public void beginUpdateCycle() { + } + @Override public void add(final SafeCloseable bc, RowSequence rowSequence, ColumnSource[] sources, MutableInt nextOutputPosition, WritableIntChunk outputPositions) { if (rowSequence.isEmpty()) { diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase.java new file mode 100644 index 00000000000..b89022922fd --- /dev/null +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase.java @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2016-2021 Deephaven Data Labs and Patent Pending + */ +package io.deephaven.engine.table.impl.by; + +import io.deephaven.base.verify.Assert; +import io.deephaven.chunk.Chunk; +import io.deephaven.chunk.WritableIntChunk; +import io.deephaven.engine.rowset.RowSequence; +import io.deephaven.engine.rowset.chunkattributes.RowKeys; +import io.deephaven.engine.table.ColumnSource; +import io.deephaven.engine.table.impl.by.alternatingcolumnsource.AlternatingColumnSource; +import io.deephaven.engine.table.impl.sources.IntegerArraySource; +import io.deephaven.engine.table.impl.sources.LongArraySource; +import io.deephaven.engine.table.impl.sources.RedirectedColumnSource; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableIntArraySource; +import io.deephaven.engine.table.impl.util.IntColumnSourceWritableRowRedirection; +import io.deephaven.engine.table.impl.util.RowRedirection; +import io.deephaven.util.QueryConstants; +import io.deephaven.util.SafeCloseable; +import org.apache.commons.lang3.mutable.MutableInt; + +public abstract class IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase + extends OperatorAggregationStateManagerOpenAddressedAlternateBase + implements IncrementalOperatorAggregationStateManager { + // our state value used when nothing is there + protected static final int EMPTY_OUTPUT_POSITION = QueryConstants.NULL_INT; + + // the state value for the bucket, parallel to mainKeySources (the state is an output row key for the aggregation) + protected ImmutableIntArraySource mainOutputPosition = new ImmutableIntArraySource(); + + // the state value for the bucket, parallel to alternateKeySources (the state is an output row key for the + // aggregation) + protected ImmutableIntArraySource alternateOutputPosition; + + // used as a row redirection for the output key sources, updated using the mainInsertMask to identify the main vs. + // alternate values + protected final IntegerArraySource outputPositionToHashSlot = new IntegerArraySource(); + + // how many values are in each state, addressed by output row key + protected final LongArraySource rowCountSource = new LongArraySource(); + + // state variables that exist as part of the update + protected MutableInt nextOutputPosition; + protected WritableIntChunk outputPositions; + + // output alternating column sources + protected AlternatingColumnSource[] alternatingColumnSources; + + // the mask for insertion into the main table (this tells our alternating column sources which of the two sources + // to access for a given key) + protected int mainInsertMask = 0; + + protected IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase(ColumnSource[] tableKeySources, + int tableSize, + double maximumLoadFactor) { + super(tableKeySources, tableSize, maximumLoadFactor); + mainOutputPosition.ensureCapacity(tableSize); + } + + @Override + protected void newAlternate() { + alternateOutputPosition = mainOutputPosition; + mainOutputPosition = new ImmutableIntArraySource(); + mainOutputPosition.ensureCapacity(tableSize); + if (mainInsertMask == 0) { + if (alternatingColumnSources != null) { + for (int ai = 0; ai < alternatingColumnSources.length; ++ai) { + alternatingColumnSources[ai].setSources(alternateKeySources[ai], mainKeySources[ai]); + } + } + mainInsertMask = (int) AlternatingColumnSource.ALTERNATE_SWITCH_MASK; + } else { + if (alternatingColumnSources != null) { + for (int ai = 0; ai < alternatingColumnSources.length; ++ai) { + alternatingColumnSources[ai].setSources(mainKeySources[ai], alternateKeySources[ai]); + } + } + mainInsertMask = 0; + } + } + + @Override + protected void clearAlternate() { + super.clearAlternate(); + this.alternateOutputPosition = null; + } + + @Override + public SafeCloseable makeAggregationStateBuildContext(ColumnSource[] buildSources, long maxSize) { + return makeBuildContext(buildSources, maxSize); + } + + @Override + public void add(final SafeCloseable bc, RowSequence rowSequence, ColumnSource[] sources, + MutableInt nextOutputPosition, WritableIntChunk outputPositions) { + outputPositions.setSize(rowSequence.intSize()); + if (rowSequence.isEmpty()) { + return; + } + this.nextOutputPosition = nextOutputPosition; + this.outputPositions = outputPositions; + buildTable((BuildContext) bc, rowSequence, sources, true, this::build); + this.outputPositions = null; + this.nextOutputPosition = null; + } + + @Override + public void onNextChunk(int size) { + outputPositionToHashSlot.ensureCapacity(nextOutputPosition.intValue() + size, false); + rowCountSource.ensureCapacity(nextOutputPosition.intValue() + size, false); + } + + @Override + public ColumnSource[] getKeyHashTableSources() { + final RowRedirection resultIndexToHashSlot = + new IntColumnSourceWritableRowRedirection(outputPositionToHashSlot); + final ColumnSource[] keyHashTableSources = new ColumnSource[mainKeySources.length]; + Assert.eqNull(alternatingColumnSources, "alternatingColumnSources"); + alternatingColumnSources = new AlternatingColumnSource[mainKeySources.length]; + for (int kci = 0; kci < mainKeySources.length; ++kci) { + final Class dataType = mainKeySources[kci].getType(); + final Class componentType = mainKeySources[kci].getComponentType(); + if (mainInsertMask == 0) { + alternatingColumnSources[kci] = new AlternatingColumnSource<>(dataType, componentType, + mainKeySources[kci], alternateKeySources[kci]); + } else { + alternatingColumnSources[kci] = new AlternatingColumnSource<>(dataType, componentType, + alternateKeySources[kci], mainKeySources[kci]); + } + // noinspection unchecked + keyHashTableSources[kci] = new RedirectedColumnSource(resultIndexToHashSlot, alternatingColumnSources[kci]); + } + + return keyHashTableSources; + } + + @Override + public void beginUpdateCycle() { + // at the beginning of the update cycle, we always want to do some rehash work so that we can eventually ditch + // the alternate table + if (rehashPointer > 0) { + rehashInternalPartial(CHUNK_SIZE); + } + } + + @Override + public void addForUpdate(final SafeCloseable bc, RowSequence rowSequence, ColumnSource[] sources, + MutableInt nextOutputPosition, WritableIntChunk outputPositions, + final WritableIntChunk reincarnatedPositions) { + outputPositions.setSize(rowSequence.intSize()); + reincarnatedPositions.setSize(0); + if (rowSequence.isEmpty()) { + return; + } + this.nextOutputPosition = nextOutputPosition; + this.outputPositions = outputPositions; + buildTable((BuildContext) bc, rowSequence, sources, false, + ((chunkOk, sourceKeyChunks) -> buildForUpdate(chunkOk, sourceKeyChunks, reincarnatedPositions))); + this.outputPositions = null; + this.nextOutputPosition = null; + } + + protected abstract void buildForUpdate(RowSequence chunkOk, Chunk[] sourceKeyChunks, + WritableIntChunk reincarnatedPositions); + + @Override + public void remove(final SafeCloseable pc, RowSequence rowSequence, ColumnSource[] sources, + WritableIntChunk outputPositions, final WritableIntChunk emptiedPositions) { + outputPositions.setSize(rowSequence.intSize()); + emptiedPositions.setSize(0); + if (rowSequence.isEmpty()) { + return; + } + this.outputPositions = outputPositions; + probeTable((ProbeContext) pc, rowSequence, true, sources, + (chunkOk, sourceKeyChunks) -> IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase.this + .doRemoveProbe(chunkOk, sourceKeyChunks, emptiedPositions)); + this.outputPositions = null; + } + + protected abstract void doRemoveProbe(RowSequence chunkOk, Chunk[] sourceKeyChunks, + WritableIntChunk emptiedPositions); + + @Override + public void findModifications(final SafeCloseable pc, RowSequence rowSequence, ColumnSource[] sources, + WritableIntChunk outputPositions) { + outputPositions.setSize(rowSequence.intSize()); + if (rowSequence.isEmpty()) { + return; + } + this.outputPositions = outputPositions; + probeTable((ProbeContext) pc, rowSequence, false, sources, + IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase.this::doModifyProbe); + this.outputPositions = null; + } + + protected abstract void doModifyProbe(RowSequence chunkOk, Chunk[] sourceKeyChunks); + + @Override + public void startTrackingPrevValues() {} + + @Override + public void setRowSize(int outputPosition, long size) { + rowCountSource.set(outputPosition, size); + } +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/IncrementalChunkedOperatorAggregationStateManagerTypedBase.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/IncrementalChunkedOperatorAggregationStateManagerTypedBase.java index 4fdc1c12900..64ab9a3390b 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/IncrementalChunkedOperatorAggregationStateManagerTypedBase.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/IncrementalChunkedOperatorAggregationStateManagerTypedBase.java @@ -84,6 +84,9 @@ public ColumnSource[] getKeyHashTableSources() { @Override public void startTrackingPrevValues() {} + @Override + public void beginUpdateCycle() {} + @Override public void setRowSize(int outputPosition, long size) { rowCountSource.set(outputPosition, size); diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/IncrementalOperatorAggregationStateManager.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/IncrementalOperatorAggregationStateManager.java index d8674273b25..6ceefaad03b 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/IncrementalOperatorAggregationStateManager.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/IncrementalOperatorAggregationStateManager.java @@ -13,6 +13,13 @@ public interface IncrementalOperatorAggregationStateManager extends OperatorAggregationStateManager { SafeCloseable makeProbeContext(ColumnSource[] probeSources, long maxSize); + /** + * Allow our managers to do a little bit of work at the very start of the update cycle. We have this method so that + * even if nothing is to be done, we rehash a little bit on each cycle to avoid always rehashing when there is other + * work to be done. + */ + void beginUpdateCycle(); + void startTrackingPrevValues(); void setRowSize(int outputPosition, long size); diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/OperatorAggregationStateManagerOpenAddressedAlternateBase.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/OperatorAggregationStateManagerOpenAddressedAlternateBase.java new file mode 100644 index 00000000000..cc19c68488f --- /dev/null +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/OperatorAggregationStateManagerOpenAddressedAlternateBase.java @@ -0,0 +1,314 @@ +/* + * Copyright (c) 2016-2021 Deephaven Data Labs and Patent Pending + */ +package io.deephaven.engine.table.impl.by; + +import io.deephaven.base.verify.Assert; +import io.deephaven.base.verify.Require; +import io.deephaven.chunk.Chunk; +import io.deephaven.chunk.attributes.Values; +import io.deephaven.engine.rowset.RowSequence; +import io.deephaven.engine.table.*; +import io.deephaven.engine.table.impl.sources.InMemoryColumnSource; +import org.apache.commons.lang3.mutable.MutableInt; + +import static io.deephaven.util.SafeCloseable.closeArray; + +public abstract class OperatorAggregationStateManagerOpenAddressedAlternateBase + implements OperatorAggregationStateManager { + public static final int CHUNK_SIZE = ChunkedOperatorAggregationHelper.CHUNK_SIZE; + private static final long MAX_TABLE_SIZE = 1 << 30; // maximum array size + + // the number of slots in our table + protected int tableSize; + // the number of slots in our alternate table, to start with "1" is a lie, but rehashPointer is zero; so our + // location value is positive and can be compared against rehashPointer safely + protected int alternateTableSize = 1; + + // how much of the alternate sources are necessary to rehash? + protected int rehashPointer = 0; + + protected long numEntries = 0; + + // the table will be rehashed to a load factor of targetLoadFactor if our loadFactor exceeds maximumLoadFactor + // or if it falls below minimum load factor we will instead contract the table + private final double maximumLoadFactor; + + // the keys for our hash entries + protected final WritableColumnSource[] mainKeySources; + + // the keys for our hash entries, for the old alternative smaller table + protected final ColumnSource[] alternateKeySources; + + protected OperatorAggregationStateManagerOpenAddressedAlternateBase(ColumnSource[] tableKeySources, + int tableSize, + double maximumLoadFactor) { + this.tableSize = tableSize; + Require.inRange(tableSize, "tableSize", MAX_TABLE_SIZE + 1, "MAX_TABLE_SIZE + 1"); + Require.eq(Integer.bitCount(tableSize), "Integer.bitCount(tableSize)", 1); + Require.inRange(maximumLoadFactor, 0.0, 0.95, "maximumLoadFactor"); + + mainKeySources = new WritableColumnSource[tableKeySources.length]; + alternateKeySources = new ColumnSource[tableKeySources.length]; + + for (int ii = 0; ii < tableKeySources.length; ++ii) { + mainKeySources[ii] = InMemoryColumnSource.getImmutableMemoryColumnSource(tableSize, + tableKeySources[ii].getType(), tableKeySources[ii].getComponentType()); + } + + this.maximumLoadFactor = maximumLoadFactor; + } + + protected abstract void build(RowSequence rowSequence, Chunk[] sourceKeyChunks); + + public static class BuildContext extends BuildOrProbeContext { + private BuildContext(ColumnSource[] buildSources, int chunkSize) { + super(buildSources, chunkSize); + } + + final MutableInt rehashCredits = new MutableInt(0); + } + public static class ProbeContext extends BuildOrProbeContext { + private ProbeContext(ColumnSource[] buildSources, int chunkSize) { + super(buildSources, chunkSize); + } + } + + private static class BuildOrProbeContext implements Context { + final int chunkSize; + final SharedContext sharedContext; + final ChunkSource.GetContext[] getContexts; + + private BuildOrProbeContext(ColumnSource[] buildSources, int chunkSize) { + Assert.gtZero(chunkSize, "chunkSize"); + this.chunkSize = chunkSize; + if (buildSources.length > 1) { + sharedContext = SharedContext.makeSharedContext(); + } else { + sharedContext = null; + } + getContexts = makeGetContexts(buildSources, sharedContext, chunkSize); + } + + void resetSharedContexts() { + if (sharedContext != null) { + sharedContext.reset(); + } + } + + void closeSharedContexts() { + if (sharedContext != null) { + sharedContext.close(); + } + } + + @Override + public void close() { + closeArray(getContexts); + closeSharedContexts(); + } + } + + BuildContext makeBuildContext(ColumnSource[] buildSources, long maxSize) { + return new BuildContext(buildSources, (int) Math.min(CHUNK_SIZE, maxSize)); + } + + public ProbeContext makeProbeContext(ColumnSource[] buildSources, long maxSize) { + return new ProbeContext(buildSources, (int) Math.min(CHUNK_SIZE, maxSize)); + } + + protected abstract void onNextChunk(int nextChunkSize); + + protected void buildTable( + final BuildContext bc, + final RowSequence buildRows, + final ColumnSource[] buildSources, + final boolean fullRehash, + final BuildHandler buildHandler) { + try (final RowSequence.Iterator rsIt = buildRows.getRowSequenceIterator()) { + // noinspection unchecked + final Chunk[] sourceKeyChunks = new Chunk[buildSources.length]; + + while (rsIt.hasMore()) { + final RowSequence chunkOk = rsIt.getNextRowSequenceWithLength(bc.chunkSize); + final int nextChunkSize = chunkOk.intSize(); + onNextChunk(nextChunkSize); + while (doRehash(fullRehash, bc.rehashCredits, nextChunkSize)) { + migrateFront(); + } + + getKeyChunks(buildSources, bc.getContexts, sourceKeyChunks, chunkOk); + + final long oldEntries = numEntries; + buildHandler.doBuild(chunkOk, sourceKeyChunks); + final long entriesAdded = numEntries - oldEntries; + // if we actually added anything, then take away from the "equity" we've built up rehashing, otherwise + // don't penalize this build call with additional rehashing + bc.rehashCredits.subtract(entriesAdded); + + bc.resetSharedContexts(); + } + } + } + + abstract protected void migrateFront(); + + protected void probeTable( + final ProbeContext pc, + final RowSequence probeRows, + final boolean usePrev, + final ColumnSource[] probeSources, + final ProbeHandler handler) { + try (final RowSequence.Iterator rsIt = probeRows.getRowSequenceIterator()) { + // noinspection unchecked + final Chunk[] sourceKeyChunks = new Chunk[probeSources.length]; + + while (rsIt.hasMore()) { + final RowSequence chunkOk = rsIt.getNextRowSequenceWithLength(pc.chunkSize); + + if (usePrev) { + getPrevKeyChunks(probeSources, pc.getContexts, sourceKeyChunks, chunkOk); + } else { + getKeyChunks(probeSources, pc.getContexts, sourceKeyChunks, chunkOk); + } + + handler.doProbe(chunkOk, sourceKeyChunks); + + pc.resetSharedContexts(); + } + } + } + + @FunctionalInterface + public interface ProbeHandler { + void doProbe(RowSequence chunkOk, Chunk[] sourceKeyChunks); + } + + @FunctionalInterface + public interface BuildHandler { + void doBuild(RowSequence chunkOk, Chunk[] sourceKeyChunks); + } + + /** + * @param fullRehash should we rehash the entire table (if false, we rehash incrementally) + * @param rehashCredits the number of entries this operation has rehashed (input/output) + * @param nextChunkSize the size of the chunk we are processing + * @return true if a front migration is required + */ + public boolean doRehash(boolean fullRehash, MutableInt rehashCredits, int nextChunkSize) { + if (rehashPointer > 0) { + final int requiredRehash = nextChunkSize - rehashCredits.intValue(); + if (requiredRehash <= 0) { + return false; + } + + // before building, we need to do at least as much rehash work as we would do build work + rehashCredits.add(rehashInternalPartial(requiredRehash)); + if (rehashPointer == 0) { + clearAlternate(); + } + } + + int oldTableSize = tableSize; + while (rehashRequired(nextChunkSize)) { + tableSize *= 2; + + if (tableSize < 0 || tableSize > MAX_TABLE_SIZE) { + throw new UnsupportedOperationException("Hash table exceeds maximum size!"); + } + } + + if (oldTableSize == tableSize) { + return false; + } + + // we can't give the caller credit for rehashes with the old table, we need to begin migrating things again + if (rehashCredits.intValue() > 0) { + rehashCredits.setValue(0); + } + + if (fullRehash) { + // if we are doing a full rehash, we need to ditch the alternate + if (rehashPointer > 0) { + rehashInternalPartial((int) numEntries); + clearAlternate(); + } + + rehashInternalFull(oldTableSize); + + return false; + } + + Assert.eqZero(rehashPointer, "rehashPointer"); + + for (int ii = 0; ii < mainKeySources.length; ++ii) { + alternateKeySources[ii] = mainKeySources[ii]; + mainKeySources[ii] = InMemoryColumnSource.getImmutableMemoryColumnSource(tableSize, + alternateKeySources[ii].getType(), alternateKeySources[ii].getComponentType()); + mainKeySources[ii].ensureCapacity(tableSize); + } + alternateTableSize = oldTableSize; + if (numEntries > 0) { + rehashPointer = alternateTableSize; + } + + newAlternate(); + + return true; + } + + protected abstract void newAlternate(); + + protected void clearAlternate() { + for (int ii = 0; ii < mainKeySources.length; ++ii) { + alternateKeySources[ii] = null; + } + } + + /** + * @param numEntriesToRehash number of entries to rehash into main table + * @return actual number of entries rehashed + */ + protected abstract int rehashInternalPartial(int numEntriesToRehash); + + // full rehashInternal + protected abstract void rehashInternalFull(int oldSize); + + public boolean rehashRequired(int nextChunkSize) { + return (numEntries + nextChunkSize) > (tableSize * maximumLoadFactor); + } + + private static void getKeyChunks(ColumnSource[] sources, ColumnSource.GetContext[] contexts, + Chunk[] chunks, RowSequence rowSequence) { + for (int ii = 0; ii < chunks.length; ++ii) { + chunks[ii] = sources[ii].getChunk(contexts[ii], rowSequence); + } + } + + private static void getPrevKeyChunks(ColumnSource[] sources, ColumnSource.GetContext[] contexts, + Chunk[] chunks, RowSequence rowSequence) { + for (int ii = 0; ii < chunks.length; ++ii) { + chunks[ii] = sources[ii].getPrevChunk(contexts[ii], rowSequence); + } + } + + protected int hashToTableLocation(int hash) { + return hash & (tableSize - 1); + } + + protected int hashToTableLocationAlternate(int hash) { + return hash & (alternateTableSize - 1); + } + + @Override + abstract public int findPositionForKey(Object key); + + private static ColumnSource.GetContext[] makeGetContexts(ColumnSource[] sources, final SharedContext sharedState, + int chunkSize) { + final ColumnSource.GetContext[] contexts = new ColumnSource.GetContext[sources.length]; + for (int ii = 0; ii < sources.length; ++ii) { + contexts[ii] = sources[ii].makeGetContext(chunkSize, sharedState); + } + return contexts; + } +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/OperatorAggregationStateManagerOpenAddressedBase.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/OperatorAggregationStateManagerOpenAddressedBase.java index e1a62f7f4aa..add62d08c9d 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/OperatorAggregationStateManagerOpenAddressedBase.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/OperatorAggregationStateManagerOpenAddressedBase.java @@ -131,44 +131,20 @@ protected void buildTable( } } - // protected void probeTable( - // final HashHandler handler, - // final ProbeContext pc, - // final RowSequence probeRows, - // final boolean usePrev, - // final ColumnSource[] probeSources) { - // try (final RowSequence.Iterator rsIt = probeRows.getRowSequenceIterator()) { - // // noinspection unchecked - // final Chunk[] sourceKeyChunks = new Chunk[probeSources.length]; - // - // while (rsIt.hasMore()) { - // final RowSequence chunkOk = rsIt.getNextRowSequenceWithLength(pc.chunkSize); - // handler.onNextChunk(chunkOk.intSize()); - // - // if (usePrev) { - // getPrevKeyChunks(probeSources, pc.getContexts, sourceKeyChunks, chunkOk); - // } else { - // getKeyChunks(probeSources, pc.getContexts, sourceKeyChunks, chunkOk); - // } - // - // probe(handler, chunkOk, sourceKeyChunks); - // - // pc.resetSharedContexts(); - // } - // } - // } - public void doRehash(int nextChunkSize) { + final int oldSize = tableSize; while (rehashRequired(nextChunkSize)) { tableSize *= 2; if (tableSize < 0 || tableSize > MAX_TABLE_SIZE) { throw new UnsupportedOperationException("Hash table exceeds maximum size!"); } - rehashInternal(); + } + if (tableSize > oldSize) { + rehashInternalFull(oldSize); } } - protected abstract void rehashInternal(); + protected abstract void rehashInternalFull(int oldSize); public boolean rehashRequired(int nextChunkSize) { return (numEntries + nextChunkSize) > (tableSize * maximumLoadFactor); diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/OperatorAggregationStateManagerTypedBase.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/OperatorAggregationStateManagerTypedBase.java index 77e10b4650b..31d8bdc46fd 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/OperatorAggregationStateManagerTypedBase.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/OperatorAggregationStateManagerTypedBase.java @@ -14,7 +14,6 @@ import io.deephaven.engine.table.SharedContext; import io.deephaven.engine.table.impl.sources.ArrayBackedColumnSource; import io.deephaven.engine.table.impl.sources.IntegerArraySource; -import io.deephaven.util.QueryConstants; import static io.deephaven.util.SafeCloseable.closeArray; diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/StaticChunkedOperatorAggregationStateManagerOpenAddressedBase.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/StaticChunkedOperatorAggregationStateManagerOpenAddressedBase.java index f043cd0dd71..a610e9cefc5 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/StaticChunkedOperatorAggregationStateManagerOpenAddressedBase.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/StaticChunkedOperatorAggregationStateManagerOpenAddressedBase.java @@ -57,7 +57,7 @@ public void add(final SafeCloseable bc, RowSequence rowSequence, ColumnSource @Override public void onNextChunk(int size) { - outputPositionToHashSlot.ensureCapacity(nextOutputPosition.intValue() + size); + outputPositionToHashSlot.ensureCapacity(nextOutputPosition.intValue() + size, false); } @Override diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/alternatingcolumnsource/AlternatingColumnSource.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/alternatingcolumnsource/AlternatingColumnSource.java new file mode 100644 index 00000000000..1e0141850f0 --- /dev/null +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/alternatingcolumnsource/AlternatingColumnSource.java @@ -0,0 +1,478 @@ +package io.deephaven.engine.table.impl.by.alternatingcolumnsource; + +import io.deephaven.base.WeakReferenceManager; +import io.deephaven.chunk.*; +import io.deephaven.chunk.attributes.Values; +import io.deephaven.engine.rowset.RowSequence; +import io.deephaven.engine.rowset.chunkattributes.RowKeys; +import io.deephaven.engine.table.ColumnSource; +import io.deephaven.engine.table.SharedContext; +import io.deephaven.engine.table.impl.AbstractColumnSource; +import io.deephaven.engine.table.impl.sources.FillUnordered; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.function.BiConsumer; + +/** + * {@link ColumnSource} implementation that delegates to the main and alternate sources for our incremental open + * addressed hash table key columns that swap back and forth between a "main" and "alternate" source. Note that the main + * and alternate swap back and forth, from the perspective of this column source the main source is addressed by zero; + * and the alternate source is addressed starting at {@link #ALTERNATE_SWITCH_MASK}. Neither source may have addresses + * greater than {@link #ALTERNATE_INNER_MASK}. + */ +public class AlternatingColumnSource extends AbstractColumnSource + implements ColumnSource, FillUnordered { + public static final long ALTERNATE_SWITCH_MASK = 0x4000_0000; + public static final long ALTERNATE_INNER_MASK = 0x3fff_ffff; + + private ColumnSource mainSource; + private ColumnSource alternateSource; + + private final WeakReferenceManager, ColumnSource>> sourceHolderListeners = + new WeakReferenceManager<>(); + + public AlternatingColumnSource(@NotNull final Class dataType, + @Nullable final Class componentType, + final ColumnSource mainSource, + final ColumnSource alternateSource) { + super(dataType, componentType); + this.mainSource = mainSource; + this.alternateSource = alternateSource; + } + + public AlternatingColumnSource(@NotNull final ColumnSource mainSource, + final ColumnSource alternateSource) { + this(mainSource.getType(), mainSource.getComponentType(), mainSource, alternateSource); + } + + public void setSources(ColumnSource mainSource, ColumnSource alternateSource) { + this.mainSource = mainSource; + this.alternateSource = alternateSource; + sourceHolderListeners.forEachValidReference(x -> x.accept(mainSource, alternateSource)); + } + + @Override + public final FillContext makeFillContext(final int chunkCapacity, final SharedContext sharedContext) { + return new AlternatingFillContextWithUnordered(mainSource, alternateSource, + chunkCapacity, + sharedContext); + } + + @Override + public final GetContext makeGetContext(final int chunkCapacity, final SharedContext sharedContext) { + return new AlternatingGetContext(mainSource, alternateSource, chunkCapacity, + sharedContext); + } + + @Override + public final void fillChunk(@NotNull final FillContext context, + @NotNull final WritableChunk destination, @NotNull final RowSequence rowSequence) { + final AlternatingFillContextWithUnordered typedContext = (AlternatingFillContextWithUnordered) context; + if (!isAlternate(rowSequence.lastRowKey())) { + // Alternate locations are always after main locations, so there are no responsive alternate locations + mainSource.fillChunk(typedContext.mainFillContext, destination, rowSequence); + return; + } + if (isAlternate(rowSequence.firstRowKey())) { + // Main locations are always before alternate locations, so there are no responsive main locations + typedContext.alternateShiftedRowSequence.reset(rowSequence, -ALTERNATE_SWITCH_MASK); + alternateSource.fillChunk(typedContext.alternateFillContext, destination, + typedContext.alternateShiftedRowSequence); + typedContext.alternateShiftedRowSequence.clear(); + return; + } + // We're going to have to mix main and alternate locations in a single destination chunk, so delegate to fill + mergedFillChunk(typedContext, destination, rowSequence); + } + + private void mergedFillChunk(@NotNull final BaseAlternatingFillContext typedContext, + @NotNull final WritableChunk destination, @NotNull final RowSequence rowSequence) { + final int totalSize = rowSequence.intSize(); + final int firstAlternateChunkPosition; + try (final RowSequence mainRowSequenceSlice = + rowSequence.getRowSequenceByKeyRange(0, ALTERNATE_SWITCH_MASK - 1)) { + firstAlternateChunkPosition = mainRowSequenceSlice.intSize(); + mainSource.fillChunk(typedContext.mainFillContext, destination, mainRowSequenceSlice); + } + final int sizeFromAlternate = totalSize - firstAlternateChunkPosition; + + // Set destination size ahead of time, so that resetting our alternate destination slice doesn't run into bounds + // issues. + destination.setSize(totalSize); + + try (final RowSequence alternateRowSequenceSlice = + rowSequence.getRowSequenceByPosition(firstAlternateChunkPosition, sizeFromAlternate)) { + typedContext.alternateShiftedRowSequence.reset(alternateRowSequenceSlice, -ALTERNATE_SWITCH_MASK); + alternateSource.fillChunk(typedContext.alternateFillContext, + typedContext.alternateDestinationSlice.resetFromChunk(destination, firstAlternateChunkPosition, + sizeFromAlternate), + typedContext.alternateShiftedRowSequence); + } + typedContext.alternateDestinationSlice.clear(); + typedContext.alternateShiftedRowSequence.clear(); + } + + @Override + public final void fillPrevChunk(@NotNull final FillContext context, + @NotNull final WritableChunk destination, @NotNull final RowSequence rowSequence) { + final AlternatingFillContextWithUnordered typedContext = (AlternatingFillContextWithUnordered) context; + if (!isAlternate(rowSequence.lastRowKey())) { + // Alternate locations are always after main locations, so there are no responsive alternate locations + mainSource.fillPrevChunk(typedContext.mainFillContext, destination, rowSequence); + return; + } + if (isAlternate(rowSequence.firstRowKey())) { + // Main locations are always before alternate locations, so there are no responsive main locations + typedContext.alternateShiftedRowSequence.reset(rowSequence, -ALTERNATE_SWITCH_MASK); + alternateSource.fillPrevChunk(typedContext.alternateFillContext, destination, + typedContext.alternateShiftedRowSequence); + typedContext.alternateShiftedRowSequence.clear(); + return; + } + // We're going to have to mix main and alternate locations in a single destination chunk, so delegate to fill + mergedFillPrevChunk(typedContext, destination, rowSequence); + } + + private void mergedFillPrevChunk(@NotNull final BaseAlternatingFillContext typedContext, + @NotNull final WritableChunk destination, @NotNull final RowSequence rowSequence) { + final int totalSize = rowSequence.intSize(); + final int firstAlternateChunkPosition; + try (final RowSequence mainRowSequenceSlice = + rowSequence.getRowSequenceByKeyRange(0, ALTERNATE_SWITCH_MASK - 1)) { + firstAlternateChunkPosition = mainRowSequenceSlice.intSize(); + mainSource.fillPrevChunk(typedContext.mainFillContext, destination, mainRowSequenceSlice); + } + final int sizeFromAlternate = totalSize - firstAlternateChunkPosition; + + // Set destination size ahead of time, so that resetting our alternate destination slice doesn't run into bounds + // issues. + destination.setSize(totalSize); + + try (final RowSequence alternateRowSequenceSlice = + rowSequence.getRowSequenceByPosition(firstAlternateChunkPosition, sizeFromAlternate)) { + typedContext.alternateShiftedRowSequence.reset(alternateRowSequenceSlice, -ALTERNATE_SWITCH_MASK); + alternateSource.fillPrevChunk(typedContext.alternateFillContext, + typedContext.alternateDestinationSlice.resetFromChunk(destination, firstAlternateChunkPosition, + sizeFromAlternate), + typedContext.alternateShiftedRowSequence); + typedContext.alternateDestinationSlice.clear(); + typedContext.alternateShiftedRowSequence.clear(); + } + } + + @Override + public final Chunk getChunk(@NotNull final GetContext context, + @NotNull final RowSequence rowSequence) { + final AlternatingGetContext typedContext = (AlternatingGetContext) context; + if (!isAlternate(rowSequence.lastRowKey())) { + // Alternate locations are always after main locations, so there are no responsive alternate locations + return mainSource.getChunk(typedContext.mainGetContext, rowSequence); + } + if (isAlternate(rowSequence.firstRowKey())) { + // Main locations are always before alternate locations, so there are no responsive main locations + typedContext.alternateShiftedRowSequence.reset(rowSequence, -ALTERNATE_SWITCH_MASK); + return alternateSource.getChunk(typedContext.alternateGetContext, + typedContext.alternateShiftedRowSequence); + } + // We're going to have to mix main and alternate locations in a single destination chunk, so delegate to fill + mergedFillChunk(typedContext, typedContext.mergeChunk, rowSequence); + return typedContext.mergeChunk; + } + + @Override + public final Chunk getPrevChunk(@NotNull final GetContext context, + @NotNull final RowSequence rowSequence) { + final AlternatingGetContext typedContext = (AlternatingGetContext) context; + if (!isAlternate(rowSequence.lastRowKey())) { + // Alternate locations are always after main locations, so there are no responsive alternate locations + return mainSource.getPrevChunk(typedContext.mainGetContext, rowSequence); + } + if (isAlternate(rowSequence.firstRowKey())) { + // Main locations are always before alternate locations, so there are no responsive main locations + typedContext.alternateShiftedRowSequence.reset(rowSequence, -ALTERNATE_SWITCH_MASK); + return alternateSource.getPrevChunk(typedContext.alternateGetContext, + typedContext.alternateShiftedRowSequence); + } + // We're going to have to mix main and alternate locations in a single destination chunk, so delegate to fill + mergedFillPrevChunk(typedContext, typedContext.mergeChunk, rowSequence); + return typedContext.mergeChunk; + } + + @Override + public final DATA_TYPE get(final long index) { + return isAlternate(index) ? alternateSource.get(innerLocation(index)) + : mainSource.get(index); + } + + @Override + public final Boolean getBoolean(final long index) { + return isAlternate(index) ? alternateSource.getBoolean(innerLocation(index)) + : mainSource.getBoolean(index); + } + + @Override + public final byte getByte(final long index) { + return isAlternate(index) ? alternateSource.getByte(innerLocation(index)) + : mainSource.getByte(index); + } + + @Override + public final char getChar(final long index) { + return isAlternate(index) ? alternateSource.getChar(innerLocation(index)) + : mainSource.getChar(index); + } + + @Override + public final double getDouble(final long index) { + return isAlternate(index) ? alternateSource.getDouble(innerLocation(index)) + : mainSource.getDouble(index); + } + + @Override + public final float getFloat(final long index) { + return isAlternate(index) ? alternateSource.getFloat(innerLocation(index)) + : mainSource.getFloat(index); + } + + @Override + public final int getInt(final long index) { + return isAlternate(index) ? alternateSource.getInt(innerLocation(index)) + : mainSource.getInt(index); + } + + @Override + public final long getLong(final long index) { + return isAlternate(index) ? alternateSource.getLong(innerLocation(index)) + : mainSource.getLong(index); + } + + @Override + public final short getShort(final long index) { + return isAlternate(index) ? alternateSource.getShort(innerLocation(index)) + : mainSource.getShort(index); + } + + @Override + public final DATA_TYPE getPrev(final long index) { + return isAlternate(index) ? alternateSource.getPrev(innerLocation(index)) + : mainSource.getPrev(index); + } + + @Override + public final Boolean getPrevBoolean(final long index) { + return isAlternate(index) ? alternateSource.getPrevBoolean(innerLocation(index)) + : mainSource.getPrevBoolean(index); + } + + @Override + public final byte getPrevByte(final long index) { + return isAlternate(index) ? alternateSource.getPrevByte(innerLocation(index)) + : mainSource.getPrevByte(index); + } + + @Override + public final char getPrevChar(final long index) { + return isAlternate(index) ? alternateSource.getPrevChar(innerLocation(index)) + : mainSource.getPrevChar(index); + } + + @Override + public final double getPrevDouble(final long index) { + return isAlternate(index) ? alternateSource.getPrevDouble(innerLocation(index)) + : mainSource.getPrevDouble(index); + } + + @Override + public final float getPrevFloat(final long index) { + return isAlternate(index) ? alternateSource.getPrevFloat(innerLocation(index)) + : mainSource.getPrevFloat(index); + } + + @Override + public final int getPrevInt(final long index) { + return isAlternate(index) ? alternateSource.getPrevInt(innerLocation(index)) + : mainSource.getPrevInt(index); + } + + @Override + public final long getPrevLong(final long index) { + return isAlternate(index) ? alternateSource.getPrevLong(innerLocation(index)) + : mainSource.getPrevLong(index); + } + + @Override + public final short getPrevShort(final long index) { + return isAlternate(index) ? alternateSource.getPrevShort(innerLocation(index)) + : mainSource.getPrevShort(index); + } + + @Override + public final void startTrackingPrevValues() { + mainSource.startTrackingPrevValues(); + alternateSource.startTrackingPrevValues(); + } + + @Override + public final boolean isImmutable() { + return mainSource.isImmutable() && alternateSource.isImmutable(); + } + + @Override + public boolean allowsReinterpret( + @NotNull final Class alternateDataType) { + if (alternateSource == null) { + return mainSource.allowsReinterpret(alternateDataType); + } + if (mainSource == null) { + return alternateSource.allowsReinterpret(alternateDataType); + } + return mainSource.allowsReinterpret(alternateDataType) + && alternateSource.allowsReinterpret(alternateDataType); + } + + private static final class Reinterpreted extends AlternatingColumnSource + implements BiConsumer, ColumnSource> { + private Reinterpreted(@NotNull final Class dataType, + @NotNull final AlternatingColumnSource original, + final ColumnSource main, + final ColumnSource alternate) { + super(dataType, null, main, alternate); + original.sourceHolderListeners.add(this); + } + + @Override + public void accept(ColumnSource main, ColumnSource alternateSource) { + setSources(reinterpretInner(main, getType()), reinterpretInner(alternateSource, getType())); + } + } + + private static ColumnSource reinterpretInner( + ColumnSource source, Class alternateDataType) { + return source == null ? null : source.reinterpret(alternateDataType); + } + + @Override + protected ColumnSource doReinterpret( + @NotNull final Class alternateDataType) { + return new Reinterpreted<>(alternateDataType, this, reinterpretInner(mainSource, alternateDataType), + reinterpretInner(alternateSource, alternateDataType)); + } + + public static boolean isAlternate(final long index) { + return (index & ALTERNATE_SWITCH_MASK) != 0; + } + + public static int innerLocation(final long hashSlot) { + return (int) (hashSlot & ALTERNATE_INNER_MASK); + } + + + @Override + public void fillChunkUnordered(@NotNull FillContext context, @NotNull WritableChunk dest, + @NotNull LongChunk keys) { + final AlternatingFillContextWithUnordered typedContext = (AlternatingFillContextWithUnordered) context; + if (alternateSource == null) { + ((FillUnordered) mainSource).fillChunkUnordered(typedContext.mainFillContext, dest, keys); + } else if (mainSource == null) { + doFillAlternateUnorderedDirect(dest, keys, typedContext, false); + } else { + final int mainSize = populateInnerKeysMain(keys, typedContext); + if (mainSize == keys.size()) { + ((FillUnordered) mainSource).fillChunkUnordered(typedContext.mainFillContext, dest, keys); + } else if (mainSize == 0) { + doFillAlternateUnorderedDirect(dest, keys, typedContext, false); + } else { + typedContext.innerValues.setSize(keys.size()); + ((FillUnordered) mainSource).fillChunkUnordered(typedContext.mainFillContext, + typedContext.innerValues, typedContext.innerKeys); + populateInnerKeysAlternate(keys, typedContext); + + ((FillUnordered) alternateSource).fillChunkUnordered(typedContext.alternateFillContext, + typedContext.innerSlice, typedContext.innerKeys); + + typedContext.mergeKernel.mergeContext(dest, keys, typedContext.innerValues, mainSize); + } + } + } + + @Override + public void fillPrevChunkUnordered(@NotNull FillContext context, @NotNull WritableChunk dest, + @NotNull LongChunk keys) { + final AlternatingFillContextWithUnordered typedContext = (AlternatingFillContextWithUnordered) context; + if (alternateSource == null) { + ((FillUnordered) mainSource).fillPrevChunkUnordered(typedContext.mainFillContext, dest, keys); + } else if (mainSource == null) { + doFillAlternateUnorderedDirect(dest, keys, typedContext, true); + } else { + final int mainSize = populateInnerKeysMain(keys, typedContext); + if (mainSize == keys.size()) { + ((FillUnordered) mainSource).fillPrevChunkUnordered(typedContext.mainFillContext, dest, + keys); + } else if (mainSize == 0) { + doFillAlternateUnorderedDirect(dest, keys, typedContext, true); + } else { + typedContext.innerValues.setSize(keys.size()); + ((FillUnordered) mainSource).fillPrevChunkUnordered(typedContext.mainFillContext, + typedContext.innerValues, typedContext.innerKeys); + // fill the alternate into the back half of the chunk + populateInnerKeysAlternate(keys, typedContext); + ((FillUnordered) alternateSource).fillPrevChunkUnordered(typedContext.alternateFillContext, + typedContext.innerSlice, typedContext.innerKeys); + + typedContext.mergeKernel.mergeContext(dest, keys, typedContext.innerValues, mainSize); + } + } + } + + private int populateInnerKeysMain(@NotNull LongChunk keys, + AlternatingFillContextWithUnordered typedContext) { + typedContext.innerKeys.setSize(0); + for (int ii = 0; ii < keys.size(); ++ii) { + final long outerKey = keys.get(ii); + if ((outerKey & ALTERNATE_SWITCH_MASK) == 0) { + typedContext.innerKeys.add(keys.get(ii)); + } + } + return typedContext.innerKeys.size(); + } + + private void populateInnerKeysAlternate(@NotNull LongChunk keys, + AlternatingFillContextWithUnordered typedContext) { + // fill the alternate into the back half of the chunk + typedContext.innerValues.setSize(keys.size()); + typedContext.innerSlice.resetFromChunk((WritableChunk) typedContext.innerValues, typedContext.innerKeys.size(), + keys.size() - typedContext.innerKeys.size()); + typedContext.innerKeys.setSize(0); + for (int ii = 0; ii < keys.size(); ++ii) { + final long outerKey = keys.get(ii); + if ((outerKey & ALTERNATE_SWITCH_MASK) != 0) { + typedContext.innerKeys.add(keys.get(ii) & ALTERNATE_INNER_MASK); + } + } + } + + private void doFillAlternateUnorderedDirect(@NotNull WritableChunk dest, + @NotNull LongChunk keys, AlternatingFillContextWithUnordered typedContext, + boolean usePrev) { + typedContext.innerKeys.setSize(keys.size()); + for (int ii = 0; ii < keys.size(); ++ii) { + typedContext.innerKeys.set(ii, keys.get(ii) & ALTERNATE_INNER_MASK); + } + if (usePrev) { + ((FillUnordered) alternateSource).fillPrevChunkUnordered(typedContext.alternateFillContext, + dest, typedContext.innerKeys); + } else { + ((FillUnordered) alternateSource).fillChunkUnordered(typedContext.alternateFillContext, dest, + typedContext.innerKeys); + } + } + + + @Override + public boolean providesFillUnordered() { + return (mainSource == null || FillUnordered.providesFillUnordered(mainSource)) && + (alternateSource == null + || FillUnordered.providesFillUnordered(alternateSource)); + } +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/alternatingcolumnsource/AlternatingColumnSourceUnorderedMergeKernel.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/alternatingcolumnsource/AlternatingColumnSourceUnorderedMergeKernel.java new file mode 100644 index 00000000000..caea52f654f --- /dev/null +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/alternatingcolumnsource/AlternatingColumnSourceUnorderedMergeKernel.java @@ -0,0 +1,37 @@ +package io.deephaven.engine.table.impl.by.alternatingcolumnsource; + +import io.deephaven.chunk.Chunk; +import io.deephaven.chunk.ChunkType; +import io.deephaven.chunk.LongChunk; +import io.deephaven.chunk.WritableChunk; +import io.deephaven.chunk.attributes.Values; +import io.deephaven.engine.rowset.chunkattributes.RowKeys; + +interface AlternatingColumnSourceUnorderedMergeKernel { + static AlternatingColumnSourceUnorderedMergeKernel getInstance(ChunkType chunkType) { + switch (chunkType) { + case Boolean: + break; + case Char: + return CharAlternatingColumnSourceUnorderedMergeKernel.INSTANCE; + case Byte: + return ByteAlternatingColumnSourceUnorderedMergeKernel.INSTANCE; + case Short: + return ShortAlternatingColumnSourceUnorderedMergeKernel.INSTANCE; + case Int: + return IntAlternatingColumnSourceUnorderedMergeKernel.INSTANCE; + case Long: + return LongAlternatingColumnSourceUnorderedMergeKernel.INSTANCE; + case Float: + return FloatAlternatingColumnSourceUnorderedMergeKernel.INSTANCE; + case Double: + return DoubleAlternatingColumnSourceUnorderedMergeKernel.INSTANCE; + case Object: + return ObjectAlternatingColumnSourceUnorderedMergeKernel.INSTANCE; + } + throw new IllegalStateException(); + } + + void mergeContext(WritableChunk dest, LongChunk outerKeys, + Chunk src, int alternatePosition); +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/alternatingcolumnsource/AlternatingFillContextWithUnordered.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/alternatingcolumnsource/AlternatingFillContextWithUnordered.java new file mode 100644 index 00000000000..dc227caf2c4 --- /dev/null +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/alternatingcolumnsource/AlternatingFillContextWithUnordered.java @@ -0,0 +1,55 @@ +package io.deephaven.engine.table.impl.by.alternatingcolumnsource; + +import io.deephaven.chunk.ResettableWritableChunk; +import io.deephaven.chunk.WritableChunk; +import io.deephaven.chunk.WritableLongChunk; +import io.deephaven.chunk.attributes.Values; +import io.deephaven.engine.rowset.chunkattributes.RowKeys; +import io.deephaven.engine.table.ColumnSource; +import io.deephaven.engine.table.SharedContext; +import io.deephaven.engine.table.impl.sources.FillUnordered; +import org.jetbrains.annotations.Nullable; + +class AlternatingFillContextWithUnordered extends BaseAlternatingFillContext { + final WritableLongChunk innerKeys; + final WritableChunk innerValues; + final ResettableWritableChunk innerSlice; + final AlternatingColumnSourceUnorderedMergeKernel mergeKernel; + + AlternatingFillContextWithUnordered(@Nullable final ColumnSource mainSource, + @Nullable final ColumnSource alternateSource, + final int chunkCapacity, + final SharedContext sharedContext) { + super(mainSource, alternateSource, chunkCapacity, sharedContext); + if ((mainSource == null || FillUnordered.providesFillUnordered(mainSource)) + && (alternateSource == null || FillUnordered.providesFillUnordered(alternateSource))) { + innerKeys = alternateSource != null ? WritableLongChunk.makeWritableChunk(chunkCapacity) : null; + if (mainSource != null && alternateSource != null) { + innerSlice = mainSource.getChunkType().makeResettableWritableChunk(); + innerValues = mainSource.getChunkType().makeWritableChunk(chunkCapacity); + mergeKernel = AlternatingColumnSourceUnorderedMergeKernel.getInstance(mainSource.getChunkType()); + } else { + innerSlice = null; + innerValues = null; + mergeKernel = null; + } + } else { + innerKeys = null; + innerSlice = null; + innerValues = null; + mergeKernel = null; + } + } + + @Override + public void close() { + super.close(); + if (innerKeys != null) { + innerKeys.close(); + } + if (innerSlice != null) { + innerSlice.close(); + innerValues.close(); + } + } +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/alternatingcolumnsource/AlternatingGetContext.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/alternatingcolumnsource/AlternatingGetContext.java new file mode 100644 index 00000000000..fa57e2eaa39 --- /dev/null +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/alternatingcolumnsource/AlternatingGetContext.java @@ -0,0 +1,51 @@ +package io.deephaven.engine.table.impl.by.alternatingcolumnsource; + +import io.deephaven.chunk.WritableChunk; +import io.deephaven.chunk.attributes.Values; +import io.deephaven.engine.table.ChunkSource; +import io.deephaven.engine.table.ColumnSource; +import io.deephaven.engine.table.SharedContext; +import org.jetbrains.annotations.Nullable; + +final class AlternatingGetContext extends BaseAlternatingFillContext implements ChunkSource.GetContext { + + final ChunkSource.GetContext mainGetContext; + final ChunkSource.GetContext alternateGetContext; + final WritableChunk mergeChunk; + + AlternatingGetContext(@Nullable final ColumnSource mainSource, + @Nullable final ColumnSource alternateSource, + final int chunkCapacity, + final SharedContext sharedContext) { + super(mainSource, alternateSource, chunkCapacity, sharedContext); + if (mainSource != null) { + mainGetContext = mainSource.makeGetContext(chunkCapacity, sharedContext); + } else { + mainGetContext = null; + } + if (alternateSource != null) { + alternateGetContext = alternateSource.makeGetContext(chunkCapacity, sharedContext); + } else { + alternateGetContext = null; + } + if (mainGetContext != null && alternateGetContext != null) { + mergeChunk = mainSource.getChunkType().makeWritableChunk(chunkCapacity); + } else { + mergeChunk = null; + } + } + + @Override + public void close() { + super.close(); + if (mainGetContext != null) { + mainGetContext.close(); + } + if (alternateGetContext != null) { + alternateGetContext.close(); + } + if (mergeChunk != null) { + mergeChunk.close(); + } + } +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/alternatingcolumnsource/BaseAlternatingFillContext.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/alternatingcolumnsource/BaseAlternatingFillContext.java new file mode 100644 index 00000000000..01b0d533592 --- /dev/null +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/alternatingcolumnsource/BaseAlternatingFillContext.java @@ -0,0 +1,54 @@ +package io.deephaven.engine.table.impl.by.alternatingcolumnsource; + +import io.deephaven.chunk.ResettableWritableChunk; +import io.deephaven.chunk.WritableChunk; +import io.deephaven.chunk.WritableLongChunk; +import io.deephaven.chunk.attributes.Any; +import io.deephaven.chunk.attributes.Values; +import io.deephaven.engine.rowset.chunkattributes.RowKeys; +import io.deephaven.engine.rowset.impl.ShiftedRowSequence; +import io.deephaven.engine.table.ChunkSource; +import io.deephaven.engine.table.ColumnSource; +import io.deephaven.engine.table.SharedContext; +import io.deephaven.engine.table.impl.sources.FillUnordered; +import org.jetbrains.annotations.Nullable; + +abstract class BaseAlternatingFillContext implements ChunkSource.FillContext { + + final ChunkSource.FillContext mainFillContext; + final ChunkSource.FillContext alternateFillContext; + final ShiftedRowSequence alternateShiftedRowSequence; + final ResettableWritableChunk alternateDestinationSlice; + + BaseAlternatingFillContext(@Nullable final ColumnSource mainSource, + @Nullable final ColumnSource alternateSource, + final int chunkCapacity, + final SharedContext sharedContext) { + if (mainSource != null) { + mainFillContext = mainSource.makeFillContext(chunkCapacity, sharedContext); + } else { + mainFillContext = null; + } + if (alternateSource != null) { + alternateFillContext = alternateSource.makeFillContext(chunkCapacity, sharedContext); + alternateShiftedRowSequence = new ShiftedRowSequence(); + alternateDestinationSlice = alternateSource.getChunkType().makeResettableWritableChunk(); + } else { + alternateFillContext = null; + alternateShiftedRowSequence = null; + alternateDestinationSlice = null; + } + } + + @Override + public void close() { + if (mainFillContext != null) { + mainFillContext.close(); + } + if (alternateFillContext != null) { + alternateFillContext.close(); + alternateShiftedRowSequence.close(); + alternateDestinationSlice.close(); + } + } +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/alternatingcolumnsource/ByteAlternatingColumnSourceUnorderedMergeKernel.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/alternatingcolumnsource/ByteAlternatingColumnSourceUnorderedMergeKernel.java new file mode 100644 index 00000000000..c08fa1c4806 --- /dev/null +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/alternatingcolumnsource/ByteAlternatingColumnSourceUnorderedMergeKernel.java @@ -0,0 +1,37 @@ +/* + * --------------------------------------------------------------------------------------------------------------------- + * AUTO-GENERATED CLASS - DO NOT EDIT MANUALLY - for any changes edit CharAlternatingColumnSourceUnorderedMergeKernel and regenerate + * --------------------------------------------------------------------------------------------------------------------- + */ +package io.deephaven.engine.table.impl.by.alternatingcolumnsource; + +import io.deephaven.chunk.*; +import io.deephaven.chunk.attributes.Values; +import io.deephaven.engine.rowset.chunkattributes.RowKeys; + +import static io.deephaven.engine.table.impl.by.alternatingcolumnsource.AlternatingColumnSource.ALTERNATE_SWITCH_MASK; + +public class ByteAlternatingColumnSourceUnorderedMergeKernel implements AlternatingColumnSourceUnorderedMergeKernel { + public static ByteAlternatingColumnSourceUnorderedMergeKernel INSTANCE = new ByteAlternatingColumnSourceUnorderedMergeKernel(); + + // static use only + private ByteAlternatingColumnSourceUnorderedMergeKernel() {} + + @Override + public void mergeContext(WritableChunk dest, LongChunk outerKeys, Chunk src, int alternatePosition) { + final WritableByteChunk destAsByte = dest.asWritableByteChunk(); + final ByteChunk srcAsByte = src.asByteChunk(); + + // now merge them together + int mainPosition = 0; + destAsByte.setSize(outerKeys.size()); + for (int ii = 0; ii < outerKeys.size(); ++ii) { + final long outerKey = outerKeys.get(ii); + if ((outerKey & ALTERNATE_SWITCH_MASK) == 0) { + destAsByte.set(ii, srcAsByte.get(mainPosition++)); + } else { + destAsByte.set(ii, srcAsByte.get(alternatePosition++)); + } + } + } +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/alternatingcolumnsource/CharAlternatingColumnSourceUnorderedMergeKernel.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/alternatingcolumnsource/CharAlternatingColumnSourceUnorderedMergeKernel.java new file mode 100644 index 00000000000..1ecc7dea5a7 --- /dev/null +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/alternatingcolumnsource/CharAlternatingColumnSourceUnorderedMergeKernel.java @@ -0,0 +1,32 @@ +package io.deephaven.engine.table.impl.by.alternatingcolumnsource; + +import io.deephaven.chunk.*; +import io.deephaven.chunk.attributes.Values; +import io.deephaven.engine.rowset.chunkattributes.RowKeys; + +import static io.deephaven.engine.table.impl.by.alternatingcolumnsource.AlternatingColumnSource.ALTERNATE_SWITCH_MASK; + +public class CharAlternatingColumnSourceUnorderedMergeKernel implements AlternatingColumnSourceUnorderedMergeKernel { + public static CharAlternatingColumnSourceUnorderedMergeKernel INSTANCE = new CharAlternatingColumnSourceUnorderedMergeKernel(); + + // static use only + private CharAlternatingColumnSourceUnorderedMergeKernel() {} + + @Override + public void mergeContext(WritableChunk dest, LongChunk outerKeys, Chunk src, int alternatePosition) { + final WritableCharChunk destAsChar = dest.asWritableCharChunk(); + final CharChunk srcAsChar = src.asCharChunk(); + + // now merge them together + int mainPosition = 0; + destAsChar.setSize(outerKeys.size()); + for (int ii = 0; ii < outerKeys.size(); ++ii) { + final long outerKey = outerKeys.get(ii); + if ((outerKey & ALTERNATE_SWITCH_MASK) == 0) { + destAsChar.set(ii, srcAsChar.get(mainPosition++)); + } else { + destAsChar.set(ii, srcAsChar.get(alternatePosition++)); + } + } + } +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/alternatingcolumnsource/DoubleAlternatingColumnSourceUnorderedMergeKernel.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/alternatingcolumnsource/DoubleAlternatingColumnSourceUnorderedMergeKernel.java new file mode 100644 index 00000000000..28b39ad0c8a --- /dev/null +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/alternatingcolumnsource/DoubleAlternatingColumnSourceUnorderedMergeKernel.java @@ -0,0 +1,37 @@ +/* + * --------------------------------------------------------------------------------------------------------------------- + * AUTO-GENERATED CLASS - DO NOT EDIT MANUALLY - for any changes edit CharAlternatingColumnSourceUnorderedMergeKernel and regenerate + * --------------------------------------------------------------------------------------------------------------------- + */ +package io.deephaven.engine.table.impl.by.alternatingcolumnsource; + +import io.deephaven.chunk.*; +import io.deephaven.chunk.attributes.Values; +import io.deephaven.engine.rowset.chunkattributes.RowKeys; + +import static io.deephaven.engine.table.impl.by.alternatingcolumnsource.AlternatingColumnSource.ALTERNATE_SWITCH_MASK; + +public class DoubleAlternatingColumnSourceUnorderedMergeKernel implements AlternatingColumnSourceUnorderedMergeKernel { + public static DoubleAlternatingColumnSourceUnorderedMergeKernel INSTANCE = new DoubleAlternatingColumnSourceUnorderedMergeKernel(); + + // static use only + private DoubleAlternatingColumnSourceUnorderedMergeKernel() {} + + @Override + public void mergeContext(WritableChunk dest, LongChunk outerKeys, Chunk src, int alternatePosition) { + final WritableDoubleChunk destAsDouble = dest.asWritableDoubleChunk(); + final DoubleChunk srcAsDouble = src.asDoubleChunk(); + + // now merge them together + int mainPosition = 0; + destAsDouble.setSize(outerKeys.size()); + for (int ii = 0; ii < outerKeys.size(); ++ii) { + final long outerKey = outerKeys.get(ii); + if ((outerKey & ALTERNATE_SWITCH_MASK) == 0) { + destAsDouble.set(ii, srcAsDouble.get(mainPosition++)); + } else { + destAsDouble.set(ii, srcAsDouble.get(alternatePosition++)); + } + } + } +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/alternatingcolumnsource/FloatAlternatingColumnSourceUnorderedMergeKernel.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/alternatingcolumnsource/FloatAlternatingColumnSourceUnorderedMergeKernel.java new file mode 100644 index 00000000000..62ad43a8f5d --- /dev/null +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/alternatingcolumnsource/FloatAlternatingColumnSourceUnorderedMergeKernel.java @@ -0,0 +1,37 @@ +/* + * --------------------------------------------------------------------------------------------------------------------- + * AUTO-GENERATED CLASS - DO NOT EDIT MANUALLY - for any changes edit CharAlternatingColumnSourceUnorderedMergeKernel and regenerate + * --------------------------------------------------------------------------------------------------------------------- + */ +package io.deephaven.engine.table.impl.by.alternatingcolumnsource; + +import io.deephaven.chunk.*; +import io.deephaven.chunk.attributes.Values; +import io.deephaven.engine.rowset.chunkattributes.RowKeys; + +import static io.deephaven.engine.table.impl.by.alternatingcolumnsource.AlternatingColumnSource.ALTERNATE_SWITCH_MASK; + +public class FloatAlternatingColumnSourceUnorderedMergeKernel implements AlternatingColumnSourceUnorderedMergeKernel { + public static FloatAlternatingColumnSourceUnorderedMergeKernel INSTANCE = new FloatAlternatingColumnSourceUnorderedMergeKernel(); + + // static use only + private FloatAlternatingColumnSourceUnorderedMergeKernel() {} + + @Override + public void mergeContext(WritableChunk dest, LongChunk outerKeys, Chunk src, int alternatePosition) { + final WritableFloatChunk destAsFloat = dest.asWritableFloatChunk(); + final FloatChunk srcAsFloat = src.asFloatChunk(); + + // now merge them together + int mainPosition = 0; + destAsFloat.setSize(outerKeys.size()); + for (int ii = 0; ii < outerKeys.size(); ++ii) { + final long outerKey = outerKeys.get(ii); + if ((outerKey & ALTERNATE_SWITCH_MASK) == 0) { + destAsFloat.set(ii, srcAsFloat.get(mainPosition++)); + } else { + destAsFloat.set(ii, srcAsFloat.get(alternatePosition++)); + } + } + } +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/alternatingcolumnsource/IntAlternatingColumnSourceUnorderedMergeKernel.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/alternatingcolumnsource/IntAlternatingColumnSourceUnorderedMergeKernel.java new file mode 100644 index 00000000000..1d96135d675 --- /dev/null +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/alternatingcolumnsource/IntAlternatingColumnSourceUnorderedMergeKernel.java @@ -0,0 +1,37 @@ +/* + * --------------------------------------------------------------------------------------------------------------------- + * AUTO-GENERATED CLASS - DO NOT EDIT MANUALLY - for any changes edit CharAlternatingColumnSourceUnorderedMergeKernel and regenerate + * --------------------------------------------------------------------------------------------------------------------- + */ +package io.deephaven.engine.table.impl.by.alternatingcolumnsource; + +import io.deephaven.chunk.*; +import io.deephaven.chunk.attributes.Values; +import io.deephaven.engine.rowset.chunkattributes.RowKeys; + +import static io.deephaven.engine.table.impl.by.alternatingcolumnsource.AlternatingColumnSource.ALTERNATE_SWITCH_MASK; + +public class IntAlternatingColumnSourceUnorderedMergeKernel implements AlternatingColumnSourceUnorderedMergeKernel { + public static IntAlternatingColumnSourceUnorderedMergeKernel INSTANCE = new IntAlternatingColumnSourceUnorderedMergeKernel(); + + // static use only + private IntAlternatingColumnSourceUnorderedMergeKernel() {} + + @Override + public void mergeContext(WritableChunk dest, LongChunk outerKeys, Chunk src, int alternatePosition) { + final WritableIntChunk destAsInt = dest.asWritableIntChunk(); + final IntChunk srcAsInt = src.asIntChunk(); + + // now merge them together + int mainPosition = 0; + destAsInt.setSize(outerKeys.size()); + for (int ii = 0; ii < outerKeys.size(); ++ii) { + final long outerKey = outerKeys.get(ii); + if ((outerKey & ALTERNATE_SWITCH_MASK) == 0) { + destAsInt.set(ii, srcAsInt.get(mainPosition++)); + } else { + destAsInt.set(ii, srcAsInt.get(alternatePosition++)); + } + } + } +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/alternatingcolumnsource/LongAlternatingColumnSourceUnorderedMergeKernel.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/alternatingcolumnsource/LongAlternatingColumnSourceUnorderedMergeKernel.java new file mode 100644 index 00000000000..69a613dc728 --- /dev/null +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/alternatingcolumnsource/LongAlternatingColumnSourceUnorderedMergeKernel.java @@ -0,0 +1,37 @@ +/* + * --------------------------------------------------------------------------------------------------------------------- + * AUTO-GENERATED CLASS - DO NOT EDIT MANUALLY - for any changes edit CharAlternatingColumnSourceUnorderedMergeKernel and regenerate + * --------------------------------------------------------------------------------------------------------------------- + */ +package io.deephaven.engine.table.impl.by.alternatingcolumnsource; + +import io.deephaven.chunk.*; +import io.deephaven.chunk.attributes.Values; +import io.deephaven.engine.rowset.chunkattributes.RowKeys; + +import static io.deephaven.engine.table.impl.by.alternatingcolumnsource.AlternatingColumnSource.ALTERNATE_SWITCH_MASK; + +public class LongAlternatingColumnSourceUnorderedMergeKernel implements AlternatingColumnSourceUnorderedMergeKernel { + public static LongAlternatingColumnSourceUnorderedMergeKernel INSTANCE = new LongAlternatingColumnSourceUnorderedMergeKernel(); + + // static use only + private LongAlternatingColumnSourceUnorderedMergeKernel() {} + + @Override + public void mergeContext(WritableChunk dest, LongChunk outerKeys, Chunk src, int alternatePosition) { + final WritableLongChunk destAsLong = dest.asWritableLongChunk(); + final LongChunk srcAsLong = src.asLongChunk(); + + // now merge them together + int mainPosition = 0; + destAsLong.setSize(outerKeys.size()); + for (int ii = 0; ii < outerKeys.size(); ++ii) { + final long outerKey = outerKeys.get(ii); + if ((outerKey & ALTERNATE_SWITCH_MASK) == 0) { + destAsLong.set(ii, srcAsLong.get(mainPosition++)); + } else { + destAsLong.set(ii, srcAsLong.get(alternatePosition++)); + } + } + } +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/alternatingcolumnsource/ObjectAlternatingColumnSourceUnorderedMergeKernel.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/alternatingcolumnsource/ObjectAlternatingColumnSourceUnorderedMergeKernel.java new file mode 100644 index 00000000000..257ab92a01a --- /dev/null +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/alternatingcolumnsource/ObjectAlternatingColumnSourceUnorderedMergeKernel.java @@ -0,0 +1,37 @@ +/* + * --------------------------------------------------------------------------------------------------------------------- + * AUTO-GENERATED CLASS - DO NOT EDIT MANUALLY - for any changes edit CharAlternatingColumnSourceUnorderedMergeKernel and regenerate + * --------------------------------------------------------------------------------------------------------------------- + */ +package io.deephaven.engine.table.impl.by.alternatingcolumnsource; + +import io.deephaven.chunk.*; +import io.deephaven.chunk.attributes.Values; +import io.deephaven.engine.rowset.chunkattributes.RowKeys; + +import static io.deephaven.engine.table.impl.by.alternatingcolumnsource.AlternatingColumnSource.ALTERNATE_SWITCH_MASK; + +public class ObjectAlternatingColumnSourceUnorderedMergeKernel implements AlternatingColumnSourceUnorderedMergeKernel { + public static ObjectAlternatingColumnSourceUnorderedMergeKernel INSTANCE = new ObjectAlternatingColumnSourceUnorderedMergeKernel(); + + // static use only + private ObjectAlternatingColumnSourceUnorderedMergeKernel() {} + + @Override + public void mergeContext(WritableChunk dest, LongChunk outerKeys, Chunk src, int alternatePosition) { + final WritableObjectChunk destAsObject = dest.asWritableObjectChunk(); + final ObjectChunk srcAsObject = src.asObjectChunk(); + + // now merge them together + int mainPosition = 0; + destAsObject.setSize(outerKeys.size()); + for (int ii = 0; ii < outerKeys.size(); ++ii) { + final long outerKey = outerKeys.get(ii); + if ((outerKey & ALTERNATE_SWITCH_MASK) == 0) { + destAsObject.set(ii, srcAsObject.get(mainPosition++)); + } else { + destAsObject.set(ii, srcAsObject.get(alternatePosition++)); + } + } + } +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/alternatingcolumnsource/ShortAlternatingColumnSourceUnorderedMergeKernel.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/alternatingcolumnsource/ShortAlternatingColumnSourceUnorderedMergeKernel.java new file mode 100644 index 00000000000..f9bd3b1dcd7 --- /dev/null +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/alternatingcolumnsource/ShortAlternatingColumnSourceUnorderedMergeKernel.java @@ -0,0 +1,37 @@ +/* + * --------------------------------------------------------------------------------------------------------------------- + * AUTO-GENERATED CLASS - DO NOT EDIT MANUALLY - for any changes edit CharAlternatingColumnSourceUnorderedMergeKernel and regenerate + * --------------------------------------------------------------------------------------------------------------------- + */ +package io.deephaven.engine.table.impl.by.alternatingcolumnsource; + +import io.deephaven.chunk.*; +import io.deephaven.chunk.attributes.Values; +import io.deephaven.engine.rowset.chunkattributes.RowKeys; + +import static io.deephaven.engine.table.impl.by.alternatingcolumnsource.AlternatingColumnSource.ALTERNATE_SWITCH_MASK; + +public class ShortAlternatingColumnSourceUnorderedMergeKernel implements AlternatingColumnSourceUnorderedMergeKernel { + public static ShortAlternatingColumnSourceUnorderedMergeKernel INSTANCE = new ShortAlternatingColumnSourceUnorderedMergeKernel(); + + // static use only + private ShortAlternatingColumnSourceUnorderedMergeKernel() {} + + @Override + public void mergeContext(WritableChunk dest, LongChunk outerKeys, Chunk src, int alternatePosition) { + final WritableShortChunk destAsShort = dest.asWritableShortChunk(); + final ShortChunk srcAsShort = src.asShortChunk(); + + // now merge them together + int mainPosition = 0; + destAsShort.setSize(outerKeys.size()); + for (int ii = 0; ii < outerKeys.size(); ++ii) { + final long outerKey = outerKeys.get(ii); + if ((outerKey & ALTERNATE_SWITCH_MASK) == 0) { + destAsShort.set(ii, srcAsShort.get(mainPosition++)); + } else { + destAsShort.set(ii, srcAsShort.get(alternatePosition++)); + } + } + } +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/TypedHasherFactory.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/TypedHasherFactory.java index 0e10543fb2c..ceb76182a3b 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/TypedHasherFactory.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/TypedHasherFactory.java @@ -10,22 +10,23 @@ import io.deephaven.compilertools.CompilerTools; import io.deephaven.configuration.Configuration; import io.deephaven.engine.rowset.RowSequence; +import io.deephaven.engine.rowset.chunkattributes.RowKeys; import io.deephaven.engine.table.ColumnSource; -import io.deephaven.engine.table.impl.by.HashHandler; -import io.deephaven.engine.table.impl.by.IncrementalChunkedOperatorAggregationStateManagerTypedBase; -import io.deephaven.engine.table.impl.by.StaticChunkedOperatorAggregationStateManagerOpenAddressedBase; -import io.deephaven.engine.table.impl.by.StaticChunkedOperatorAggregationStateManagerTypedBase; +import io.deephaven.engine.table.impl.by.*; import io.deephaven.engine.table.impl.sources.*; import io.deephaven.engine.table.impl.sources.immutable.*; import io.deephaven.util.QueryConstants; import io.deephaven.util.compare.CharComparisons; import io.deephaven.util.type.TypeUtils; +import org.apache.commons.lang3.StringUtils; import org.jetbrains.annotations.NotNull; import javax.lang.model.element.Modifier; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.util.*; +import java.util.function.BiConsumer; +import java.util.function.Consumer; import java.util.stream.Collectors; import java.util.stream.IntStream; @@ -54,43 +55,188 @@ public static T make(Class baseClass, ColumnSource[] tableKeySources, return make(hasherConfigForBase(baseClass), tableKeySources, tableSize, maximumLoadFactor, targetLoadFactor); } + private static class ProbeSpec { + final String name; + final String stateValueName; + final Consumer found; + final Consumer missing; + final ParameterSpec[] params; + + private ProbeSpec(String name, String stateValueName, Consumer found, + Consumer missing, ParameterSpec... params) { + this.name = name; + this.stateValueName = stateValueName; + this.found = found; + this.missing = missing; + this.params = params; + } + } + + private static class BuildSpec { + final String name; + final String stateValueName; + final BiConsumer, CodeBlock.Builder> found; + final BiConsumer, CodeBlock.Builder> insert; + final ParameterSpec[] params; + + private BuildSpec(String name, String stateValueName, BiConsumer, CodeBlock.Builder> found, + BiConsumer, CodeBlock.Builder> insert, ParameterSpec... params) { + this.name = name; + this.stateValueName = stateValueName; + this.found = found; + this.insert = insert; + this.params = params; + } + } + @NotNull public static HasherConfig hasherConfigForBase(Class baseClass) { final String classPrefix; final String packageMiddle; final String mainStateName; - final String overflowStateName; + final String overflowOrAlternateStateName; final String emptyStateName; final boolean openAddressed; + final boolean openAddressedAlternate; + final Consumer moveMain; + final List builds = new ArrayList<>(); + final List probes = new ArrayList<>(); + final boolean alwaysMoveMain; if (baseClass.equals(StaticChunkedOperatorAggregationStateManagerTypedBase.class)) { classPrefix = "StaticAggHasher"; packageMiddle = "staticagg"; openAddressed = false; + openAddressedAlternate = false; mainStateName = "mainOutputPosition"; - overflowStateName = "overflowOutputPosition"; + overflowOrAlternateStateName = "overflowOutputPosition"; emptyStateName = "EMPTY_OUTPUT_POSITION"; + moveMain = null; + alwaysMoveMain = false; } else if (baseClass.equals(StaticChunkedOperatorAggregationStateManagerOpenAddressedBase.class)) { classPrefix = "StaticAggOpenHasher"; packageMiddle = "staticopenagg"; openAddressed = true; + openAddressedAlternate = false; mainStateName = "mainOutputPosition"; - overflowStateName = null; + overflowOrAlternateStateName = null; emptyStateName = "EMPTY_OUTPUT_POSITION"; + moveMain = TypedHasherFactory::staticAggMoveMain; + builds.add(new BuildSpec("build", "outputPosition", TypedHasherFactory::buildFound, + TypedHasherFactory::buildInsert)); + alwaysMoveMain = false; } else if (baseClass.equals(IncrementalChunkedOperatorAggregationStateManagerTypedBase.class)) { classPrefix = "IncrementalAggHasher"; packageMiddle = "incagg"; openAddressed = false; + openAddressedAlternate = false; mainStateName = "mainOutputPosition"; - overflowStateName = "overflowOutputPosition"; + overflowOrAlternateStateName = "overflowOutputPosition"; emptyStateName = "EMPTY_OUTPUT_POSITION"; + moveMain = null; + alwaysMoveMain = false; + } else if (baseClass.equals(IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase.class)) { + classPrefix = "IncrementalAggOpenHasher"; + packageMiddle = "incopenagg"; + openAddressed = true; + openAddressedAlternate = true; + mainStateName = "mainOutputPosition"; + overflowOrAlternateStateName = "alternateOutputPosition"; + emptyStateName = "EMPTY_OUTPUT_POSITION"; + moveMain = TypedHasherFactory::incAggMoveMain; + alwaysMoveMain = true; + + final ClassName rowKeyType = ClassName.get(RowKeys.class); + final ParameterizedTypeName emptiedChunkType = + ParameterizedTypeName.get(ClassName.get(WritableIntChunk.class), rowKeyType); + final ParameterSpec emptiedPositions = ParameterSpec.builder(emptiedChunkType, "emptiedPositions").build();; + + probes.add(new ProbeSpec("doRemoveProbe", "outputPosition", TypedHasherFactory::removeProbeFound, + TypedHasherFactory::probeMissing, emptiedPositions)); + probes.add(new ProbeSpec("doModifyProbe", "outputPosition", TypedHasherFactory::probeFound, + TypedHasherFactory::probeMissing)); + + builds.add(new BuildSpec("build", "outputPosition", TypedHasherFactory::buildFoundIncrementalInitial, + TypedHasherFactory::buildInsertIncremental)); + + final ParameterSpec reincarnatedPositions = + ParameterSpec.builder(emptiedChunkType, "reincarnatedPositions").build();; + builds.add( + new BuildSpec("buildForUpdate", "outputPosition", TypedHasherFactory::buildFoundIncrementalUpdate, + TypedHasherFactory::buildInsertIncremental, reincarnatedPositions)); } else { throw new UnsupportedOperationException("Unknown class to make: " + baseClass); } - final HasherConfig hasherConfig = - new HasherConfig<>(baseClass, classPrefix, packageMiddle, openAddressed, mainStateName, - overflowStateName, - emptyStateName, int.class); - return hasherConfig; + + return new HasherConfig<>(baseClass, classPrefix, packageMiddle, openAddressed, openAddressedAlternate, + alwaysMoveMain, + mainStateName, + overflowOrAlternateStateName, + emptyStateName, int.class, moveMain, probes, builds); + } + + private static void staticAggMoveMain(CodeBlock.Builder builder) { + builder.addStatement("outputPositionToHashSlot.set(currentStateValue, destinationTableLocation)"); + } + + private static void incAggMoveMain(CodeBlock.Builder builder) { + builder.addStatement( + "outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation)"); + } + + private static void buildFound(HasherConfig hasherConfig, CodeBlock.Builder builder) { + builder.addStatement("outputPositions.set(chunkPosition, outputPosition)"); + } + + private static void buildFoundIncremental(HasherConfig hasherConfig, CodeBlock.Builder builder) { + buildFound(hasherConfig, builder); + builder.addStatement("final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1)"); + } + + private static void buildFoundIncrementalInitial(HasherConfig hasherConfig, CodeBlock.Builder builder) { + buildFoundIncremental(hasherConfig, builder); + builder.addStatement("Assert.gtZero(oldRowCount, \"oldRowCount\")"); + } + + private static void buildFoundIncrementalUpdate(HasherConfig hasherConfig, CodeBlock.Builder builder) { + buildFoundIncremental(hasherConfig, builder); + builder.beginControlFlow("if (oldRowCount == 0)"); + builder.addStatement("reincarnatedPositions.add(outputPosition)"); + builder.endControlFlow(); + } + + private static void buildInsertCommon(HasherConfig hasherConfig, CodeBlock.Builder builder) { + builder.addStatement("outputPosition = nextOutputPosition.getAndIncrement()"); + builder.addStatement("outputPositions.set(chunkPosition, outputPosition)"); + builder.addStatement("$L.set(tableLocation, outputPosition)", hasherConfig.mainStateName); + } + + private static void buildInsert(HasherConfig hasherConfig, CodeBlock.Builder builder) { + buildInsertCommon(hasherConfig, builder); + builder.addStatement("outputPositionToHashSlot.set(outputPosition, tableLocation)"); + } + + private static void buildInsertIncremental(HasherConfig hasherConfig, CodeBlock.Builder builder) { + buildInsertCommon(hasherConfig, builder); + builder.addStatement("outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation)"); + builder.addStatement("rowCountSource.set(outputPosition, 1L)"); + } + + private static void probeFound(CodeBlock.Builder builder) { + builder.addStatement("outputPositions.set(chunkPosition, outputPosition)"); + } + + private static void removeProbeFound(CodeBlock.Builder builder) { + probeFound(builder); + + builder.addStatement("final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1)"); + builder.addStatement("Assert.gtZero(oldRowCount, \"oldRowCount\")"); + builder.beginControlFlow("if (oldRowCount == 1)"); + builder.addStatement("emptiedPositions.add(outputPosition)"); + builder.endControlFlow(); + } + + private static void probeMissing(CodeBlock.Builder builder) { + builder.addStatement("throw new IllegalStateException($S)", "Missing value in probe"); } public static class HasherConfig { @@ -98,23 +244,34 @@ public static class HasherConfig { public final String classPrefix; public final String packageMiddle; final boolean openAddressed; + final boolean openAddressedAlternate; + final boolean alwaysMoveMain; final String mainStateName; - final String overflowStateName; + final String overflowOrAlternateStateName; final String emptyStateName; final Class stateType; + final Consumer moveMain; + private final List probes; + private final List builds; HasherConfig(Class baseClass, String classPrefix, String packageMiddle, boolean openAddressed, - String mainStateName, - String overflowStateName, - String emptyStateName, Class stateType) { + boolean openAddressedAlternate, boolean alwaysMoveMain, String mainStateName, + String overflowOrAlternateStateName, + String emptyStateName, Class stateType, Consumer moveMain, List probes, + List builds) { this.baseClass = baseClass; this.classPrefix = classPrefix; this.packageMiddle = packageMiddle; this.openAddressed = openAddressed; + this.openAddressedAlternate = openAddressedAlternate; + this.alwaysMoveMain = alwaysMoveMain; this.mainStateName = mainStateName; - this.overflowStateName = overflowStateName; + this.overflowOrAlternateStateName = overflowOrAlternateStateName; this.emptyStateName = emptyStateName; this.stateType = stateType; + this.moveMain = moveMain; + this.probes = probes; + this.builds = builds; } } @@ -155,6 +312,14 @@ public static T make(HasherConfig hasherConfig, ColumnSource[] tableKe if (pregeneratedHasher != null) { return pregeneratedHasher; } + } else if (hasherConfig.baseClass + .equals(IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase.class)) { + // noinspection unchecked + T pregeneratedHasher = (T) io.deephaven.engine.table.impl.by.typed.incopenagg.gen.TypedHashDispatcher + .dispatch(tableKeySources, tableSize, maximumLoadFactor, targetLoadFactor); + if (pregeneratedHasher != null) { + return pregeneratedHasher; + } } } @@ -211,7 +376,14 @@ public static JavaFile generateHasher(final HasherConfig hasherConfig, hasherBuilder.addMethod(createConstructor(hasherConfig, chunkTypes, hasherBuilder)); if (hasherConfig.openAddressed) { - hasherBuilder.addMethod(createBuildMethodForOpenAddressed(hasherConfig, chunkTypes)); + hasherBuilder.addMethod(createNextTableLocationMethod(false)); + if (hasherConfig.openAddressedAlternate) { + hasherBuilder.addMethod(createNextTableLocationMethod(true)); + } + hasherConfig.builds.forEach( + bs -> hasherBuilder.addMethod(createBuildMethodForOpenAddressed(hasherConfig, bs, chunkTypes))); + hasherConfig.probes.forEach( + ps -> hasherBuilder.addMethod(createProbeMethodForOpenAddressed(hasherConfig, ps, chunkTypes))); } else { hasherBuilder.addMethod(createBuildMethodForOverflow(hasherConfig, chunkTypes)); hasherBuilder.addMethod(createProbeMethodForOverflow(hasherConfig, chunkTypes)); @@ -219,7 +391,14 @@ public static JavaFile generateHasher(final HasherConfig hasherConfig, hasherBuilder.addMethod(createHashMethod(chunkTypes)); if (hasherConfig.openAddressed) { - hasherBuilder.addMethod(createRehashInternalMethod(hasherConfig, chunkTypes)); + if (hasherConfig.openAddressedAlternate) { + hasherBuilder.addMethod(createMigrateLocationMethod(hasherConfig, chunkTypes)); + hasherBuilder.addMethod(createRehashInternalPartialMethod(hasherConfig, chunkTypes)); + hasherBuilder.addMethod(createNewAlternateMethod(hasherConfig, chunkTypes)); + hasherBuilder.addMethod(createClearAlternateMethod(hasherConfig, chunkTypes)); + hasherBuilder.addMethod(createMigrateFront()); + } + hasherBuilder.addMethod(createRehashInternalFullMethod(hasherConfig, chunkTypes)); } else { hasherBuilder.addMethod(createRehashBucketMethod(hasherConfig, chunkTypes)); hasherBuilder.addMethod(createMaybeMoveMainBucket(hasherConfig, chunkTypes)); @@ -244,6 +423,23 @@ public static JavaFile generateHasher(final HasherConfig hasherConfig, return fileBuilder.build(); } + private static MethodSpec createNextTableLocationMethod(boolean alternate) { + final MethodSpec.Builder builder = + MethodSpec.methodBuilder(nextTableLocationName(alternate)).addParameter(int.class, "tableLocation") + .returns(int.class).addModifiers(Modifier.PRIVATE); + if (alternate) { + builder.addStatement("return (tableLocation + 1) & (alternateTableSize - 1)"); + } else { + builder.addStatement("return (tableLocation + 1) & (tableSize - 1)"); + } + return builder.build(); + } + + @NotNull + private static String nextTableLocationName(boolean alternate) { + return alternate ? "alternateNextTableLocation" : "nextTableLocation"; + } + @NotNull private static MethodSpec createConstructor(HasherConfig hasherConfig, ChunkType[] chunkTypes, TypeSpec.Builder hasherBuilder) { @@ -263,22 +459,29 @@ private static MethodSpec createConstructor(HasherConfig hasherConfig, Ch .build(); } - private static void addKeySourceFields(HasherConfig hasherConfig, ChunkType[] chunkTypes, + private static void addKeySourceFields(HasherConfig hasherConfig, ChunkType[] chunkTypes, TypeSpec.Builder hasherBuilder, CodeBlock.Builder constructorCodeBuilder) { + final Modifier[] modifiers = hasherConfig.openAddressedAlternate ? new Modifier[] {Modifier.PRIVATE} + : new Modifier[] {Modifier.PRIVATE, Modifier.FINAL}; + final List keySources = new ArrayList<>(); for (int ii = 0; ii < chunkTypes.length; ++ii) { final Class type = hasherConfig.openAddressed ? flatSourceType(chunkTypes[ii]) : arraySourceType(chunkTypes[ii]); keySources.add( - FieldSpec.builder(type, "mainKeySource" + ii).addModifiers(Modifier.PRIVATE, Modifier.FINAL) + FieldSpec.builder(type, "mainKeySource" + ii).addModifiers(modifiers) .build()); constructorCodeBuilder.addStatement("this.mainKeySource$L = ($T) super.mainKeySources[$L]", ii, type, ii); if (hasherConfig.openAddressed) { constructorCodeBuilder.addStatement("this.mainKeySource$L.ensureCapacity(tableSize)", ii); + if (hasherConfig.openAddressedAlternate) { + keySources.add(FieldSpec.builder(type, "alternateKeySource" + ii) + .addModifiers(modifiers).build()); + } } else { keySources.add(FieldSpec.builder(type, "overflowKeySource" + ii) - .addModifiers(Modifier.PRIVATE, Modifier.FINAL).build()); + .addModifiers(modifiers).build()); constructorCodeBuilder.addStatement("this.overflowKeySource$L = ($T) super.overflowKeySources[$L]", ii, type, ii); } @@ -326,7 +529,7 @@ private static MethodSpec createFindPositionForKey(HasherConfig hasherConfig, + IntStream.range(0, chunkTypes.length).mapToObj(x -> "k" + x).collect(Collectors.joining(", ")) + ")"); if (hasherConfig.openAddressed) { - findPositionForKeyOpenAddressed(hasherConfig, chunkTypes, builder); + findPositionForKeyOpenAddressed(hasherConfig, chunkTypes, builder, false); } else { findPositionForKeyOverflow(hasherConfig, chunkTypes, builder); } @@ -334,24 +537,46 @@ private static MethodSpec createFindPositionForKey(HasherConfig hasherConfig, } private static void findPositionForKeyOpenAddressed(HasherConfig hasherConfig, ChunkType[] chunkTypes, - MethodSpec.Builder builder) { - builder.addStatement("int tableLocation = hashToTableLocation(hash)"); - builder.addStatement("final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1)"); + MethodSpec.Builder builder, boolean alternate) { + + final String tableLocationName = alternate ? "alternateTableLocation" : "tableLocation"; + final String firstLocationName = "first" + StringUtils.capitalize(tableLocationName); + if (alternate) { + builder.addStatement("int $L = hashToTableLocationAlternate(hash)", tableLocationName); + builder.beginControlFlow("if ($L >= rehashPointer)", tableLocationName); + builder.addStatement("return -1"); + builder.endControlFlow(); + } else { + builder.addStatement("int $L = hashToTableLocation(hash)", tableLocationName); + } + builder.addStatement("final int $L = $L", firstLocationName, tableLocationName); builder.beginControlFlow("while (true)"); - builder.addStatement("final int positionValue = $L.getUnsafe(tableLocation)", hasherConfig.mainStateName); - builder.beginControlFlow("if (positionValue == $L)", hasherConfig.emptyStateName); - builder.addStatement("return -1"); + final String positionValueName = alternate ? "alternatePositionValue" : "positionValue"; + + builder.addStatement("final int $L = $L.getUnsafe($L)", positionValueName, + alternate ? hasherConfig.overflowOrAlternateStateName : hasherConfig.mainStateName, + tableLocationName); + builder.beginControlFlow("if ($L == $L)", positionValueName, hasherConfig.emptyStateName); + + if (hasherConfig.openAddressedAlternate && !alternate) { + findPositionForKeyOpenAddressed(hasherConfig, chunkTypes, builder, true); + } else { + builder.addStatement("return -1"); + } + builder.endControlFlow(); - builder.beginControlFlow("if (" + getEqualsStatement(chunkTypes) + ")"); - builder.addStatement("return positionValue"); + builder.beginControlFlow( + "if (" + (alternate ? getEqualsStatementAlternate(chunkTypes) : getEqualsStatement(chunkTypes)) + ")"); + builder.addStatement("return $L", positionValueName); builder.endControlFlow(); - builder.addStatement("$T.neq(tableLocation, $S, lastTableLocation, $S)", Assert.class, "tableLocation", - "lastTableLocation"); - builder.addStatement("tableLocation = (tableLocation + 1) & (tableSize - 1)"); + final String nextLocationName = alternate ? "alternateNextTableLocation" : "nextTableLocation"; + builder.addStatement("$L = $L($L)", tableLocationName, nextLocationName, tableLocationName); + builder.addStatement("$T.neq($L, $S, $L, $S)", Assert.class, tableLocationName, tableLocationName, + firstLocationName, firstLocationName); builder.endControlFlow(); } @@ -372,7 +597,7 @@ private static void findPositionForKeyOverflow(HasherConfig hasherConfig, Chu builder.beginControlFlow("while (overflowLocation != QueryConstants.NULL_INT)"); builder.beginControlFlow("if (" + getEqualsStatementOverflow(chunkTypes) + ")"); - builder.addStatement("return $L.getUnsafe(overflowLocation)", hasherConfig.overflowStateName); + builder.addStatement("return $L.getUnsafe(overflowLocation)", hasherConfig.overflowOrAlternateStateName); builder.endControlFlow(); builder.addStatement("overflowLocation = overflowOverflowLocationSource.getUnsafe(overflowLocation)"); @@ -464,9 +689,10 @@ private static MethodSpec createRehashBucketMethod(HasherConfig hasherConfig, builder.addStatement("mainKeySource$L.set(mainInsertLocation, overflowKey$L)", ii, ii); } builder.addStatement("$L.set(mainInsertLocation, $L.getUnsafe(overflowLocation))", hasherConfig.mainStateName, - hasherConfig.overflowStateName); + hasherConfig.overflowOrAlternateStateName); builder.addStatement("handler.doPromoteOverflow(overflowLocation, mainInsertLocation)"); - builder.addStatement("$L.set(overflowLocation, QueryConstants.NULL_INT)", hasherConfig.overflowStateName); + builder.addStatement("$L.set(overflowLocation, QueryConstants.NULL_INT)", + hasherConfig.overflowOrAlternateStateName); // key source loop for (int ii = 0; ii < chunkTypes.length; ++ii) { @@ -495,11 +721,9 @@ private static MethodSpec createRehashBucketMethod(HasherConfig hasherConfig, // we are also using the old arrays as temporary space, so any moving of objects must be done inline (but the // single inheritor we have does not do that, so we are not adding that complexity at this instant) @NotNull - private static MethodSpec createRehashInternalMethod(HasherConfig hasherConfig, ChunkType[] chunkTypes) { + private static MethodSpec createRehashInternalFullMethod(HasherConfig hasherConfig, ChunkType[] chunkTypes) { final CodeBlock.Builder builder = CodeBlock.builder(); - builder.addStatement("final int oldSize = tableSize >> 1"); - for (int ii = 0; ii < chunkTypes.length; ++ii) { builder.addStatement("final $T[] destKeyArray$L = new $T[tableSize]", elementType(chunkTypes[ii]), ii, elementType(chunkTypes[ii])); @@ -518,7 +742,8 @@ private static MethodSpec createRehashInternalMethod(HasherConfig hasherConfi builder.addStatement("$L.setArray(destState)", hasherConfig.mainStateName); builder.beginControlFlow("for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket)"); - builder.beginControlFlow("if (originalStateArray[sourceBucket] == $L)", hasherConfig.emptyStateName); + builder.addStatement("final $T currentStateValue = originalStateArray[sourceBucket]", hasherConfig.stateType); + builder.beginControlFlow("if (currentStateValue == $L)", hasherConfig.emptyStateName); builder.addStatement("continue"); builder.endControlFlow(); @@ -528,33 +753,155 @@ private static MethodSpec createRehashInternalMethod(HasherConfig hasherConfi } builder.addStatement("final int hash = hash(" + IntStream.range(0, chunkTypes.length).mapToObj(x -> "k" + x).collect(Collectors.joining(", ")) + ")"); - builder.addStatement("int tableLocation = hashToTableLocation(hash)"); - builder.addStatement("final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1)"); + builder.addStatement("final int firstDestinationTableLocation = hashToTableLocation(hash)"); + builder.addStatement("int destinationTableLocation = firstDestinationTableLocation"); builder.beginControlFlow("while (true)"); - builder.beginControlFlow("if (destState[tableLocation] == $L)", hasherConfig.emptyStateName); + builder.beginControlFlow("if (destState[destinationTableLocation] == $L)", hasherConfig.emptyStateName); for (int ii = 0; ii < chunkTypes.length; ++ii) { - builder.addStatement("destKeyArray$L[tableLocation] = k$L", ii, ii); + builder.addStatement("destKeyArray$L[destinationTableLocation] = k$L", ii, ii); + } + builder.addStatement("destState[destinationTableLocation] = originalStateArray[sourceBucket]", + hasherConfig.mainStateName); + if (!hasherConfig.alwaysMoveMain) { + builder.beginControlFlow("if (sourceBucket != destinationTableLocation)"); + } + hasherConfig.moveMain.accept(builder); + if (!hasherConfig.alwaysMoveMain) { + builder.endControlFlow(); } - builder.addStatement("destState[tableLocation] = originalStateArray[sourceBucket]", hasherConfig.mainStateName); - builder.beginControlFlow("if (sourceBucket != tableLocation)"); - builder.addStatement("outputPositionToHashSlot.set(destState[tableLocation], tableLocation)"); - builder.endControlFlow(); builder.addStatement("break"); - builder.nextControlFlow("else"); - builder.addStatement("$T.neq(tableLocation, $S, lastTableLocation, $S)", Assert.class, "tableLocation", - "lastTableLocation"); - builder.addStatement("tableLocation = (tableLocation + 1) & (tableSize - 1)"); builder.endControlFlow(); + builder.addStatement("destinationTableLocation = nextTableLocation(destinationTableLocation)"); + builder.addStatement("$T.neq($L, $S, $L, $S)", Assert.class, "destinationTableLocation", + "destinationTableLocation", + "firstDestinationTableLocation", "firstDestinationTableLocation"); + builder.endControlFlow(); + builder.endControlFlow(); + return MethodSpec.methodBuilder("rehashInternalFull") + .returns(void.class) + .addParameter(int.class, "oldSize", Modifier.FINAL) + .addModifiers(Modifier.PROTECTED) + .addCode(builder.build()) + .addAnnotation(Override.class).build(); + } + + @NotNull + private static MethodSpec createRehashInternalPartialMethod(HasherConfig hasherConfig, ChunkType[] chunkTypes) { + final CodeBlock.Builder builder = CodeBlock.builder(); + + // ensure the capacity for everything + builder.addStatement("int rehashedEntries = 0"); + builder.beginControlFlow("while (rehashPointer > 0 && rehashedEntries < entriesToRehash)"); + builder.beginControlFlow("if (migrateOneLocation(--rehashPointer))"); + builder.addStatement("rehashedEntries++"); + builder.endControlFlow(); builder.endControlFlow(); + builder.addStatement("return rehashedEntries"); + + return MethodSpec.methodBuilder("rehashInternalPartial") + .returns(int.class).addModifiers(Modifier.PROTECTED).addParameter(int.class, "entriesToRehash") + .addCode(builder.build()) + .addAnnotation(Override.class).build(); + } + + @NotNull + private static MethodSpec createNewAlternateMethod(HasherConfig hasherConfig, ChunkType[] chunkTypes) { + final CodeBlock.Builder builder = CodeBlock.builder(); + + builder.addStatement("super.newAlternate()"); + + for (int ii = 0; ii < chunkTypes.length; ++ii) { + final Class sourceType = flatSourceType(chunkTypes[ii]); + builder.addStatement("this.mainKeySource$L = ($T)super.mainKeySources[$L]", ii, sourceType, ii); + builder.addStatement("this.alternateKeySource$L = ($T)super.alternateKeySources[$L]", ii, sourceType, ii); + } - return MethodSpec.methodBuilder("rehashInternal") + return MethodSpec.methodBuilder("newAlternate") .returns(void.class).addModifiers(Modifier.PROTECTED) .addCode(builder.build()) .addAnnotation(Override.class).build(); } + @NotNull + private static MethodSpec createClearAlternateMethod(HasherConfig hasherConfig, ChunkType[] chunkTypes) { + final CodeBlock.Builder builder = CodeBlock.builder(); + + builder.addStatement("super.clearAlternate()"); + + for (int ii = 0; ii < chunkTypes.length; ++ii) { + builder.addStatement("this.alternateKeySource$L = null", ii); + } + + return MethodSpec.methodBuilder("clearAlternate") + .returns(void.class).addModifiers(Modifier.PROTECTED) + .addCode(builder.build()) + .addAnnotation(Override.class) + .build(); + } + + @NotNull + private static MethodSpec createMigrateLocationMethod(HasherConfig hasherConfig, ChunkType[] chunkTypes) { + final CodeBlock.Builder builder = CodeBlock.builder(); + + builder.addStatement("final $T currentStateValue = $L.getUnsafe(locationToMigrate)", hasherConfig.stateType, + hasherConfig.overflowOrAlternateStateName); + builder.beginControlFlow("if (currentStateValue == $L)", hasherConfig.emptyStateName); + builder.addStatement("return false"); + builder.endControlFlow(); + + for (int ii = 0; ii < chunkTypes.length; ++ii) { + final Class element = elementType(chunkTypes[ii]); + builder.addStatement("final $T k$L = alternateKeySource$L.getUnsafe(locationToMigrate)", element, ii, ii); + } + builder.addStatement("final int hash = hash(" + + IntStream.range(0, chunkTypes.length).mapToObj(x -> "k" + x).collect(Collectors.joining(", ")) + ")"); + + builder.addStatement("int destinationTableLocation = hashToTableLocation(hash)"); + + builder.beginControlFlow("while ($L.getUnsafe(destinationTableLocation) != $L)", hasherConfig.mainStateName, + hasherConfig.emptyStateName); + builder.addStatement("destinationTableLocation = nextTableLocation(destinationTableLocation)"); + builder.endControlFlow(); + + doRehashMoveAlternateToMain(hasherConfig, chunkTypes, builder, "locationToMigrate", "destinationTableLocation"); + + builder.addStatement("return true"); + + return MethodSpec.methodBuilder("migrateOneLocation") + .returns(boolean.class).addModifiers(Modifier.PRIVATE).addParameter(int.class, "locationToMigrate") + .addCode(builder.build()).build(); + } + + @NotNull + private static MethodSpec createMigrateFront() { + final CodeBlock.Builder builder = CodeBlock.builder(); + + builder.addStatement("int location = 0"); + builder.addStatement("while (migrateOneLocation(location++))"); + + return MethodSpec.methodBuilder("migrateFront") + .addModifiers(Modifier.PROTECTED) + .addAnnotation(Override.class) + .addCode(builder.build()).build(); + } + + private static void doRehashMoveAlternateToMain(HasherConfig hasherConfig, ChunkType[] chunkTypes, + CodeBlock.Builder builder, final String sourceLocation, final String destinationLocation) { + // we need to move the keys, states, and call the move main + for (int ii = 0; ii < chunkTypes.length; ++ii) { + builder.addStatement("mainKeySource$L.set($L, k$L)", ii, destinationLocation, ii); + if (chunkTypes[ii] == ChunkType.Object) { + builder.addStatement("alternateKeySource$L.set($L, null)", ii, sourceLocation); + } + } + builder.addStatement("$L.set($L, currentStateValue)", hasherConfig.mainStateName, destinationLocation); + hasherConfig.moveMain.accept(builder); + builder.addStatement("$L.set($L, $L)", hasherConfig.overflowOrAlternateStateName, sourceLocation, + hasherConfig.emptyStateName); + } + @NotNull private static MethodSpec createBuildMethodForOverflow(HasherConfig hasherConfig, ChunkType[] chunkTypes) { final CodeBlock.Builder builder = CodeBlock.builder(); @@ -613,7 +960,8 @@ private static MethodSpec createBuildMethodForOverflow(HasherConfig hasherCon } @NotNull - private static MethodSpec createBuildMethodForOpenAddressed(HasherConfig hasherConfig, ChunkType[] chunkTypes) { + private static MethodSpec createBuildMethodForOpenAddressed(HasherConfig hasherConfig, BuildSpec buildSpec, + ChunkType[] chunkTypes) { final CodeBlock.Builder builder = CodeBlock.builder(); for (int ii = 0; ii < chunkTypes.length; ++ii) { final ClassName chunkName = @@ -633,40 +981,159 @@ private static MethodSpec createBuildMethodForOpenAddressed(HasherConfig hash } builder.addStatement("final int hash = hash(" + IntStream.range(0, chunkTypes.length).mapToObj(x -> "k" + x).collect(Collectors.joining(", ")) + ")"); - builder.addStatement("int tableLocation = hashToTableLocation(hash)"); - builder.addStatement("final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1)"); - builder.beginControlFlow("while (true)"); - builder.addStatement("$T tableState = $L.getUnsafe(tableLocation)", hasherConfig.stateType, - hasherConfig.mainStateName); - builder.beginControlFlow("if (tableState == $L)", hasherConfig.emptyStateName); - builder.addStatement("numEntries++"); - for (int ii = 0; ii < chunkTypes.length; ++ii) { - builder.addStatement("mainKeySource$L.set(tableLocation, k$L)", ii, ii); + doBuildSearch(hasherConfig, buildSpec, chunkTypes, builder, false); + + builder.endControlFlow(); + + MethodSpec.Builder methodBuilder = MethodSpec.methodBuilder(buildSpec.name) + .addParameter(RowSequence.class, "rowSequence") + .addParameter(Chunk[].class, "sourceKeyChunks"); + for (final ParameterSpec param : buildSpec.params) { + methodBuilder.addParameter(param); } + return methodBuilder + .returns(void.class).addModifiers(Modifier.PROTECTED).addCode(builder.build()) + // .addAnnotation(Override.class) + .build(); + } - builder.addStatement("final int outputPosition = nextOutputPosition.getAndIncrement()"); - builder.addStatement("outputPositions.set(chunkPosition, outputPosition)"); - builder.addStatement("$L.set(tableLocation, outputPosition)", hasherConfig.mainStateName); - builder.addStatement("outputPositionToHashSlot.set(outputPosition, tableLocation)"); - // builder.addStatement("handler.doMainInsert(tableLocation, chunkPosition)"); - builder.addStatement("break"); - builder.nextControlFlow("else if (" + getEqualsStatement(chunkTypes) + ")"); - builder.addStatement("outputPositions.set(chunkPosition, tableState)"); - // builder.addStatement("handler.doMainFound(tableLocation, chunkPosition)"); + private static void doBuildSearch(HasherConfig hasherConfig, BuildSpec buildSpec, ChunkType[] chunkTypes, + CodeBlock.Builder builder, boolean alternate) { + final String tableLocationName = alternate ? "alternateTableLocation" : "tableLocation"; + final String firstTableLocationName = alternate ? "firstAlternateTableLocation" : "firstTableLocation"; + final String tableLocationMethod = alternate ? "hashToTableLocationAlternate" : "hashToTableLocation"; + + builder.addStatement("final int $L = $L(hash)", firstTableLocationName, tableLocationMethod); + builder.addStatement("int $L = $L", tableLocationName, firstTableLocationName); + if (alternate) { + builder.beginControlFlow("while ($L < rehashPointer)", tableLocationName); + builder.addStatement("$L = $L.getUnsafe($L)", buildSpec.stateValueName, + hasherConfig.overflowOrAlternateStateName, tableLocationName); + } else { + builder.beginControlFlow((hasherConfig.openAddressedAlternate ? "MAIN_SEARCH: " : "") + "while (true)"); + builder.addStatement("$T $L = $L.getUnsafe($L)", hasherConfig.stateType, buildSpec.stateValueName, + hasherConfig.mainStateName, tableLocationName); + } + builder.beginControlFlow("if ($L == $L)", buildSpec.stateValueName, hasherConfig.emptyStateName); + + if (hasherConfig.openAddressedAlternate && !alternate) { + // we might need to do an alternative build here + doBuildSearch(hasherConfig, buildSpec, chunkTypes, builder, true); + } + + if (!alternate) { + builder.addStatement("numEntries++"); + for (int ii = 0; ii < chunkTypes.length; ++ii) { + builder.addStatement("mainKeySource$L.set($L, k$L)", ii, tableLocationName, ii); + } + buildSpec.insert.accept(hasherConfig, builder); + } builder.addStatement("break"); + builder.nextControlFlow("else if (" + + (alternate ? getEqualsStatementAlternate(chunkTypes) : getEqualsStatement(chunkTypes)) + ")"); + buildSpec.found.accept(hasherConfig, builder); + if (alternate) { + builder.addStatement("break MAIN_SEARCH"); + } else { + builder.addStatement("break"); + } builder.nextControlFlow("else"); - builder.addStatement("$T.neq(tableLocation, $S, lastTableLocation, $S)", Assert.class, "tableLocation", - "lastTableLocation"); - builder.addStatement("tableLocation = (tableLocation + 1) & (tableSize - 1)"); + if (alternate) { + builder.addStatement("$L = alternateNextTableLocation($L)", tableLocationName, tableLocationName); + } else { + builder.addStatement("$L = nextTableLocation($L)", tableLocationName, tableLocationName); + } + builder.addStatement("$T.neq($L, $S, $L, $S)", Assert.class, tableLocationName, tableLocationName, + firstTableLocationName, firstTableLocationName); builder.endControlFlow(); builder.endControlFlow(); + } + + private static MethodSpec createProbeMethodForOpenAddressed(HasherConfig hasherConfig, ProbeSpec ps, + ChunkType[] chunkTypes) { + final CodeBlock.Builder builder = CodeBlock.builder(); + for (int ii = 0; ii < chunkTypes.length; ++ii) { + final ClassName chunkName = + ClassName.get(CharChunk.class.getPackageName(), chunkTypes[ii].name() + "Chunk"); + final ClassName valuesName = ClassName.get(Values.class); + final ParameterizedTypeName chunkTypeName = chunkTypes[ii] == ChunkType.Object + ? ParameterizedTypeName.get(chunkName, ClassName.get(Object.class), valuesName) + : ParameterizedTypeName.get(chunkName, valuesName); + builder.addStatement("final $T keyChunk$L = sourceKeyChunks[$L].as$LChunk()", chunkTypeName, ii, ii, + chunkTypes[ii].name()); + } + + builder.addStatement("final int chunkSize = keyChunk0.size()"); + builder.beginControlFlow("for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition)"); + for (int ii = 0; ii < chunkTypes.length; ++ii) { + final Class element = elementType(chunkTypes[ii]); + builder.addStatement("final $T k$L = keyChunk$L.get(chunkPosition)", element, ii, ii); + } + builder.addStatement("final int hash = hash(" + + IntStream.range(0, chunkTypes.length).mapToObj(x -> "k" + x).collect(Collectors.joining(", ")) + ")"); + doProbeSearch(hasherConfig, ps, chunkTypes, builder, false); + builder.endControlFlow(); - return MethodSpec.methodBuilder("build") + final MethodSpec.Builder methodBuilder = MethodSpec.methodBuilder(ps.name) .addParameter(RowSequence.class, "rowSequence") - .addParameter(Chunk[].class, "sourceKeyChunks") - .returns(void.class).addModifiers(Modifier.PROTECTED).addCode(builder.build()) - .addAnnotation(Override.class).build(); + .addParameter(Chunk[].class, "sourceKeyChunks"); + + for (final ParameterSpec param : ps.params) { + methodBuilder.addParameter(param); + } + + methodBuilder.returns(void.class).addModifiers(Modifier.PROTECTED).addCode(builder.build()); + // .addAnnotation(Override.class) + + return methodBuilder.build(); + } + + private static void doProbeSearch(HasherConfig hasherConfig, ProbeSpec ps, ChunkType[] chunkTypes, + CodeBlock.Builder builder, boolean alternate) { + final String tableLocationName = alternate ? "alternateTableLocation" : "tableLocation"; + final String firstTableLocationName = alternate ? "firstAlternateTableLocation" : "firstTableLocation"; + final String tableLocationMethod = alternate ? "hashToTableLocationAlternate" : "hashToTableLocation"; + final String foundName = alternate ? "alternateFound" : "found"; + + builder.addStatement("final int $L = $L(hash)", firstTableLocationName, tableLocationMethod); + builder.addStatement("boolean $L = false", foundName); + + if (alternate) { + builder.beginControlFlow("if ($L < rehashPointer)", firstTableLocationName); + } + builder.addStatement("int $L = $L", tableLocationName, firstTableLocationName); + + + if (!alternate) { + builder.addStatement("$T $L", hasherConfig.stateType, ps.stateValueName); + } + + builder.beginControlFlow("while (($L = $L.getUnsafe($L)) != $L)", ps.stateValueName, + alternate ? hasherConfig.overflowOrAlternateStateName : hasherConfig.mainStateName, tableLocationName, + hasherConfig.emptyStateName); + + builder.beginControlFlow( + "if (" + (alternate ? getEqualsStatementAlternate(chunkTypes) : getEqualsStatement(chunkTypes)) + ")"); + ps.found.accept(builder); + builder.addStatement("$L = true", foundName); + builder.addStatement("break"); + builder.endControlFlow(); + builder.addStatement("$L = $L($L)", tableLocationName, nextTableLocationName(alternate), tableLocationName); + builder.addStatement("$T.neq($L, $S, $L, $S)", Assert.class, tableLocationName, tableLocationName, + firstTableLocationName, firstTableLocationName); + builder.endControlFlow(); + if (alternate) { + builder.endControlFlow(); + } + + builder.beginControlFlow("if (!$L)", foundName); + if (hasherConfig.openAddressedAlternate && !alternate) { + doProbeSearch(hasherConfig, ps, chunkTypes, builder, true); + } else { + ps.missing.accept(builder); + } + builder.endControlFlow(); } @NotNull @@ -714,6 +1181,8 @@ private static MethodSpec createProbeMethodForOverflow(HasherConfig hasherCon .addAnnotation(Override.class).build(); } + + @NotNull private static MethodSpec createHashMethod(ChunkType[] chunkTypes) { final MethodSpec.Builder builder = @@ -740,6 +1209,13 @@ private static String getEqualsStatement(ChunkType[] chunkTypes) { .collect(Collectors.joining(" && ")); } + @NotNull + private static String getEqualsStatementAlternate(ChunkType[] chunkTypes) { + return IntStream.range(0, chunkTypes.length) + .mapToObj(x -> "eq(alternateKeySource" + x + ".getUnsafe(alternateTableLocation), k" + x + ")") + .collect(Collectors.joining(" && ")); + } + @NotNull private static String getEqualsStatementOverflow(ChunkType[] chunkTypes) { return IntStream.range(0, chunkTypes.length) diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherByte.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherByte.java new file mode 100644 index 00000000000..edd2e046002 --- /dev/null +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherByte.java @@ -0,0 +1,356 @@ +// DO NOT EDIT THIS CLASS, AUTOMATICALLY GENERATED BY io.deephaven.engine.table.impl.by.typed.TypedHasherFactory +// Copyright (c) 2016-2022 Deephaven Data Labs and Patent Pending +// +package io.deephaven.engine.table.impl.by.typed.incopenagg.gen; + +import static io.deephaven.util.compare.ByteComparisons.eq; + +import io.deephaven.base.verify.Assert; +import io.deephaven.chunk.ByteChunk; +import io.deephaven.chunk.Chunk; +import io.deephaven.chunk.WritableIntChunk; +import io.deephaven.chunk.attributes.Values; +import io.deephaven.chunk.util.hashing.ByteChunkHasher; +import io.deephaven.engine.rowset.RowSequence; +import io.deephaven.engine.rowset.chunkattributes.RowKeys; +import io.deephaven.engine.table.ColumnSource; +import io.deephaven.engine.table.impl.by.IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableByteArraySource; +import io.deephaven.util.type.TypeUtils; +import java.lang.Byte; +import java.lang.Object; +import java.lang.Override; +import java.util.Arrays; + +final class IncrementalAggOpenHasherByte extends IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase { + private ImmutableByteArraySource mainKeySource0; + + private ImmutableByteArraySource alternateKeySource0; + + public IncrementalAggOpenHasherByte(ColumnSource[] tableKeySources, int tableSize, + double maximumLoadFactor, double targetLoadFactor) { + super(tableKeySources, tableSize, maximumLoadFactor); + this.mainKeySource0 = (ImmutableByteArraySource) super.mainKeySources[0]; + this.mainKeySource0.ensureCapacity(tableSize); + } + + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + + private int alternateNextTableLocation(int tableLocation) { + return (tableLocation + 1) & (alternateTableSize - 1); + } + + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final ByteChunk keyChunk0 = sourceKeyChunks[0].asByteChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final byte k0 = keyChunk0.get(chunkPosition); + final int hash = hash(k0); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void buildForUpdate(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk reincarnatedPositions) { + final ByteChunk keyChunk0 = sourceKeyChunks[0].asByteChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final byte k0 = keyChunk0.get(chunkPosition); + final int hash = hash(k0); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void doRemoveProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk emptiedPositions) { + final ByteChunk keyChunk0 = sourceKeyChunks[0].asByteChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final byte k0 = keyChunk0.get(chunkPosition); + final int hash = hash(k0); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + protected void doModifyProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final ByteChunk keyChunk0 = sourceKeyChunks[0].asByteChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final byte k0 = keyChunk0.get(chunkPosition); + final int hash = hash(k0); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0)) { + outputPositions.set(chunkPosition, outputPosition); + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0)) { + outputPositions.set(chunkPosition, outputPosition); + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + private static int hash(byte k0) { + int hash = ByteChunkHasher.hashInitialSingle(k0); + return hash; + } + + private boolean migrateOneLocation(int locationToMigrate) { + final int currentStateValue = alternateOutputPosition.getUnsafe(locationToMigrate); + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + return false; + } + final byte k0 = alternateKeySource0.getUnsafe(locationToMigrate); + final int hash = hash(k0); + int destinationTableLocation = hashToTableLocation(hash); + while (mainOutputPosition.getUnsafe(destinationTableLocation) != EMPTY_OUTPUT_POSITION) { + destinationTableLocation = nextTableLocation(destinationTableLocation); + } + mainKeySource0.set(destinationTableLocation, k0); + mainOutputPosition.set(destinationTableLocation, currentStateValue); + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + alternateOutputPosition.set(locationToMigrate, EMPTY_OUTPUT_POSITION); + return true; + } + + @Override + protected int rehashInternalPartial(int entriesToRehash) { + int rehashedEntries = 0; + while (rehashPointer > 0 && rehashedEntries < entriesToRehash) { + if (migrateOneLocation(--rehashPointer)) { + rehashedEntries++; + } + } + return rehashedEntries; + } + + @Override + protected void newAlternate() { + super.newAlternate(); + this.mainKeySource0 = (ImmutableByteArraySource)super.mainKeySources[0]; + this.alternateKeySource0 = (ImmutableByteArraySource)super.alternateKeySources[0]; + } + + @Override + protected void clearAlternate() { + super.clearAlternate(); + this.alternateKeySource0 = null; + } + + @Override + protected void migrateFront() { + int location = 0; + while (migrateOneLocation(location++)); + } + + @Override + protected void rehashInternalFull(final int oldSize) { + final byte[] destKeyArray0 = new byte[tableSize]; + final int[] destState = new int[tableSize]; + Arrays.fill(destState, EMPTY_OUTPUT_POSITION); + final byte [] originalKeyArray0 = mainKeySource0.getArray(); + mainKeySource0.setArray(destKeyArray0); + final int [] originalStateArray = mainOutputPosition.getArray(); + mainOutputPosition.setArray(destState); + for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + continue; + } + final byte k0 = originalKeyArray0[sourceBucket]; + final int hash = hash(k0); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; + while (true) { + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + break; + } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); + } + } + } + + @Override + public int findPositionForKey(Object key) { + final byte k0 = TypeUtils.unbox((Byte)key); + int hash = hash(k0); + int tableLocation = hashToTableLocation(hash); + final int firstTableLocation = tableLocation; + while (true) { + final int positionValue = mainOutputPosition.getUnsafe(tableLocation); + if (positionValue == EMPTY_OUTPUT_POSITION) { + int alternateTableLocation = hashToTableLocationAlternate(hash); + if (alternateTableLocation >= rehashPointer) { + return -1; + } + final int firstAlternateTableLocation = alternateTableLocation; + while (true) { + final int alternatePositionValue = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (alternatePositionValue == EMPTY_OUTPUT_POSITION) { + return -1; + } + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0)) { + return alternatePositionValue; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (eq(mainKeySource0.getUnsafe(tableLocation), k0)) { + return positionValue; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherByteByte.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherByteByte.java new file mode 100644 index 00000000000..5c711945305 --- /dev/null +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherByteByte.java @@ -0,0 +1,385 @@ +// DO NOT EDIT THIS CLASS, AUTOMATICALLY GENERATED BY io.deephaven.engine.table.impl.by.typed.TypedHasherFactory +// Copyright (c) 2016-2022 Deephaven Data Labs and Patent Pending +// +package io.deephaven.engine.table.impl.by.typed.incopenagg.gen; + +import static io.deephaven.util.compare.ByteComparisons.eq; + +import io.deephaven.base.verify.Assert; +import io.deephaven.chunk.ByteChunk; +import io.deephaven.chunk.Chunk; +import io.deephaven.chunk.WritableIntChunk; +import io.deephaven.chunk.attributes.Values; +import io.deephaven.chunk.util.hashing.ByteChunkHasher; +import io.deephaven.engine.rowset.RowSequence; +import io.deephaven.engine.rowset.chunkattributes.RowKeys; +import io.deephaven.engine.table.ColumnSource; +import io.deephaven.engine.table.impl.by.IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableByteArraySource; +import io.deephaven.util.type.TypeUtils; +import java.lang.Byte; +import java.lang.Object; +import java.lang.Override; +import java.util.Arrays; + +final class IncrementalAggOpenHasherByteByte extends IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase { + private ImmutableByteArraySource mainKeySource0; + + private ImmutableByteArraySource alternateKeySource0; + + private ImmutableByteArraySource mainKeySource1; + + private ImmutableByteArraySource alternateKeySource1; + + public IncrementalAggOpenHasherByteByte(ColumnSource[] tableKeySources, int tableSize, + double maximumLoadFactor, double targetLoadFactor) { + super(tableKeySources, tableSize, maximumLoadFactor); + this.mainKeySource0 = (ImmutableByteArraySource) super.mainKeySources[0]; + this.mainKeySource0.ensureCapacity(tableSize); + this.mainKeySource1 = (ImmutableByteArraySource) super.mainKeySources[1]; + this.mainKeySource1.ensureCapacity(tableSize); + } + + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + + private int alternateNextTableLocation(int tableLocation) { + return (tableLocation + 1) & (alternateTableSize - 1); + } + + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final ByteChunk keyChunk0 = sourceKeyChunks[0].asByteChunk(); + final ByteChunk keyChunk1 = sourceKeyChunks[1].asByteChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final byte k0 = keyChunk0.get(chunkPosition); + final byte k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void buildForUpdate(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk reincarnatedPositions) { + final ByteChunk keyChunk0 = sourceKeyChunks[0].asByteChunk(); + final ByteChunk keyChunk1 = sourceKeyChunks[1].asByteChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final byte k0 = keyChunk0.get(chunkPosition); + final byte k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void doRemoveProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk emptiedPositions) { + final ByteChunk keyChunk0 = sourceKeyChunks[0].asByteChunk(); + final ByteChunk keyChunk1 = sourceKeyChunks[1].asByteChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final byte k0 = keyChunk0.get(chunkPosition); + final byte k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + protected void doModifyProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final ByteChunk keyChunk0 = sourceKeyChunks[0].asByteChunk(); + final ByteChunk keyChunk1 = sourceKeyChunks[1].asByteChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final byte k0 = keyChunk0.get(chunkPosition); + final byte k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + private static int hash(byte k0, byte k1) { + int hash = ByteChunkHasher.hashInitialSingle(k0); + hash = ByteChunkHasher.hashUpdateSingle(hash, k1); + return hash; + } + + private boolean migrateOneLocation(int locationToMigrate) { + final int currentStateValue = alternateOutputPosition.getUnsafe(locationToMigrate); + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + return false; + } + final byte k0 = alternateKeySource0.getUnsafe(locationToMigrate); + final byte k1 = alternateKeySource1.getUnsafe(locationToMigrate); + final int hash = hash(k0, k1); + int destinationTableLocation = hashToTableLocation(hash); + while (mainOutputPosition.getUnsafe(destinationTableLocation) != EMPTY_OUTPUT_POSITION) { + destinationTableLocation = nextTableLocation(destinationTableLocation); + } + mainKeySource0.set(destinationTableLocation, k0); + mainKeySource1.set(destinationTableLocation, k1); + mainOutputPosition.set(destinationTableLocation, currentStateValue); + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + alternateOutputPosition.set(locationToMigrate, EMPTY_OUTPUT_POSITION); + return true; + } + + @Override + protected int rehashInternalPartial(int entriesToRehash) { + int rehashedEntries = 0; + while (rehashPointer > 0 && rehashedEntries < entriesToRehash) { + if (migrateOneLocation(--rehashPointer)) { + rehashedEntries++; + } + } + return rehashedEntries; + } + + @Override + protected void newAlternate() { + super.newAlternate(); + this.mainKeySource0 = (ImmutableByteArraySource)super.mainKeySources[0]; + this.alternateKeySource0 = (ImmutableByteArraySource)super.alternateKeySources[0]; + this.mainKeySource1 = (ImmutableByteArraySource)super.mainKeySources[1]; + this.alternateKeySource1 = (ImmutableByteArraySource)super.alternateKeySources[1]; + } + + @Override + protected void clearAlternate() { + super.clearAlternate(); + this.alternateKeySource0 = null; + this.alternateKeySource1 = null; + } + + @Override + protected void migrateFront() { + int location = 0; + while (migrateOneLocation(location++)); + } + + @Override + protected void rehashInternalFull(final int oldSize) { + final byte[] destKeyArray0 = new byte[tableSize]; + final byte[] destKeyArray1 = new byte[tableSize]; + final int[] destState = new int[tableSize]; + Arrays.fill(destState, EMPTY_OUTPUT_POSITION); + final byte [] originalKeyArray0 = mainKeySource0.getArray(); + mainKeySource0.setArray(destKeyArray0); + final byte [] originalKeyArray1 = mainKeySource1.getArray(); + mainKeySource1.setArray(destKeyArray1); + final int [] originalStateArray = mainOutputPosition.getArray(); + mainOutputPosition.setArray(destState); + for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + continue; + } + final byte k0 = originalKeyArray0[sourceBucket]; + final byte k1 = originalKeyArray1[sourceBucket]; + final int hash = hash(k0, k1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; + while (true) { + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + break; + } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); + } + } + } + + @Override + public int findPositionForKey(Object key) { + final Object [] ka = (Object[])key; + final byte k0 = TypeUtils.unbox((Byte)ka[0]); + final byte k1 = TypeUtils.unbox((Byte)ka[1]); + int hash = hash(k0, k1); + int tableLocation = hashToTableLocation(hash); + final int firstTableLocation = tableLocation; + while (true) { + final int positionValue = mainOutputPosition.getUnsafe(tableLocation); + if (positionValue == EMPTY_OUTPUT_POSITION) { + int alternateTableLocation = hashToTableLocationAlternate(hash); + if (alternateTableLocation >= rehashPointer) { + return -1; + } + final int firstAlternateTableLocation = alternateTableLocation; + while (true) { + final int alternatePositionValue = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (alternatePositionValue == EMPTY_OUTPUT_POSITION) { + return -1; + } + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + return alternatePositionValue; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + return positionValue; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherByteChar.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherByteChar.java new file mode 100644 index 00000000000..a5f885a7ac4 --- /dev/null +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherByteChar.java @@ -0,0 +1,390 @@ +// DO NOT EDIT THIS CLASS, AUTOMATICALLY GENERATED BY io.deephaven.engine.table.impl.by.typed.TypedHasherFactory +// Copyright (c) 2016-2022 Deephaven Data Labs and Patent Pending +// +package io.deephaven.engine.table.impl.by.typed.incopenagg.gen; + +import static io.deephaven.util.compare.ByteComparisons.eq; +import static io.deephaven.util.compare.CharComparisons.eq; + +import io.deephaven.base.verify.Assert; +import io.deephaven.chunk.ByteChunk; +import io.deephaven.chunk.CharChunk; +import io.deephaven.chunk.Chunk; +import io.deephaven.chunk.WritableIntChunk; +import io.deephaven.chunk.attributes.Values; +import io.deephaven.chunk.util.hashing.ByteChunkHasher; +import io.deephaven.chunk.util.hashing.CharChunkHasher; +import io.deephaven.engine.rowset.RowSequence; +import io.deephaven.engine.rowset.chunkattributes.RowKeys; +import io.deephaven.engine.table.ColumnSource; +import io.deephaven.engine.table.impl.by.IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableByteArraySource; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableCharArraySource; +import io.deephaven.util.type.TypeUtils; +import java.lang.Byte; +import java.lang.Character; +import java.lang.Object; +import java.lang.Override; +import java.util.Arrays; + +final class IncrementalAggOpenHasherByteChar extends IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase { + private ImmutableByteArraySource mainKeySource0; + + private ImmutableByteArraySource alternateKeySource0; + + private ImmutableCharArraySource mainKeySource1; + + private ImmutableCharArraySource alternateKeySource1; + + public IncrementalAggOpenHasherByteChar(ColumnSource[] tableKeySources, int tableSize, + double maximumLoadFactor, double targetLoadFactor) { + super(tableKeySources, tableSize, maximumLoadFactor); + this.mainKeySource0 = (ImmutableByteArraySource) super.mainKeySources[0]; + this.mainKeySource0.ensureCapacity(tableSize); + this.mainKeySource1 = (ImmutableCharArraySource) super.mainKeySources[1]; + this.mainKeySource1.ensureCapacity(tableSize); + } + + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + + private int alternateNextTableLocation(int tableLocation) { + return (tableLocation + 1) & (alternateTableSize - 1); + } + + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final ByteChunk keyChunk0 = sourceKeyChunks[0].asByteChunk(); + final CharChunk keyChunk1 = sourceKeyChunks[1].asCharChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final byte k0 = keyChunk0.get(chunkPosition); + final char k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void buildForUpdate(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk reincarnatedPositions) { + final ByteChunk keyChunk0 = sourceKeyChunks[0].asByteChunk(); + final CharChunk keyChunk1 = sourceKeyChunks[1].asCharChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final byte k0 = keyChunk0.get(chunkPosition); + final char k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void doRemoveProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk emptiedPositions) { + final ByteChunk keyChunk0 = sourceKeyChunks[0].asByteChunk(); + final CharChunk keyChunk1 = sourceKeyChunks[1].asCharChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final byte k0 = keyChunk0.get(chunkPosition); + final char k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + protected void doModifyProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final ByteChunk keyChunk0 = sourceKeyChunks[0].asByteChunk(); + final CharChunk keyChunk1 = sourceKeyChunks[1].asCharChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final byte k0 = keyChunk0.get(chunkPosition); + final char k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + private static int hash(byte k0, char k1) { + int hash = ByteChunkHasher.hashInitialSingle(k0); + hash = CharChunkHasher.hashUpdateSingle(hash, k1); + return hash; + } + + private boolean migrateOneLocation(int locationToMigrate) { + final int currentStateValue = alternateOutputPosition.getUnsafe(locationToMigrate); + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + return false; + } + final byte k0 = alternateKeySource0.getUnsafe(locationToMigrate); + final char k1 = alternateKeySource1.getUnsafe(locationToMigrate); + final int hash = hash(k0, k1); + int destinationTableLocation = hashToTableLocation(hash); + while (mainOutputPosition.getUnsafe(destinationTableLocation) != EMPTY_OUTPUT_POSITION) { + destinationTableLocation = nextTableLocation(destinationTableLocation); + } + mainKeySource0.set(destinationTableLocation, k0); + mainKeySource1.set(destinationTableLocation, k1); + mainOutputPosition.set(destinationTableLocation, currentStateValue); + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + alternateOutputPosition.set(locationToMigrate, EMPTY_OUTPUT_POSITION); + return true; + } + + @Override + protected int rehashInternalPartial(int entriesToRehash) { + int rehashedEntries = 0; + while (rehashPointer > 0 && rehashedEntries < entriesToRehash) { + if (migrateOneLocation(--rehashPointer)) { + rehashedEntries++; + } + } + return rehashedEntries; + } + + @Override + protected void newAlternate() { + super.newAlternate(); + this.mainKeySource0 = (ImmutableByteArraySource)super.mainKeySources[0]; + this.alternateKeySource0 = (ImmutableByteArraySource)super.alternateKeySources[0]; + this.mainKeySource1 = (ImmutableCharArraySource)super.mainKeySources[1]; + this.alternateKeySource1 = (ImmutableCharArraySource)super.alternateKeySources[1]; + } + + @Override + protected void clearAlternate() { + super.clearAlternate(); + this.alternateKeySource0 = null; + this.alternateKeySource1 = null; + } + + @Override + protected void migrateFront() { + int location = 0; + while (migrateOneLocation(location++)); + } + + @Override + protected void rehashInternalFull(final int oldSize) { + final byte[] destKeyArray0 = new byte[tableSize]; + final char[] destKeyArray1 = new char[tableSize]; + final int[] destState = new int[tableSize]; + Arrays.fill(destState, EMPTY_OUTPUT_POSITION); + final byte [] originalKeyArray0 = mainKeySource0.getArray(); + mainKeySource0.setArray(destKeyArray0); + final char [] originalKeyArray1 = mainKeySource1.getArray(); + mainKeySource1.setArray(destKeyArray1); + final int [] originalStateArray = mainOutputPosition.getArray(); + mainOutputPosition.setArray(destState); + for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + continue; + } + final byte k0 = originalKeyArray0[sourceBucket]; + final char k1 = originalKeyArray1[sourceBucket]; + final int hash = hash(k0, k1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; + while (true) { + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + break; + } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); + } + } + } + + @Override + public int findPositionForKey(Object key) { + final Object [] ka = (Object[])key; + final byte k0 = TypeUtils.unbox((Byte)ka[0]); + final char k1 = TypeUtils.unbox((Character)ka[1]); + int hash = hash(k0, k1); + int tableLocation = hashToTableLocation(hash); + final int firstTableLocation = tableLocation; + while (true) { + final int positionValue = mainOutputPosition.getUnsafe(tableLocation); + if (positionValue == EMPTY_OUTPUT_POSITION) { + int alternateTableLocation = hashToTableLocationAlternate(hash); + if (alternateTableLocation >= rehashPointer) { + return -1; + } + final int firstAlternateTableLocation = alternateTableLocation; + while (true) { + final int alternatePositionValue = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (alternatePositionValue == EMPTY_OUTPUT_POSITION) { + return -1; + } + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + return alternatePositionValue; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + return positionValue; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherByteDouble.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherByteDouble.java new file mode 100644 index 00000000000..91ef34ea1e4 --- /dev/null +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherByteDouble.java @@ -0,0 +1,390 @@ +// DO NOT EDIT THIS CLASS, AUTOMATICALLY GENERATED BY io.deephaven.engine.table.impl.by.typed.TypedHasherFactory +// Copyright (c) 2016-2022 Deephaven Data Labs and Patent Pending +// +package io.deephaven.engine.table.impl.by.typed.incopenagg.gen; + +import static io.deephaven.util.compare.ByteComparisons.eq; +import static io.deephaven.util.compare.DoubleComparisons.eq; + +import io.deephaven.base.verify.Assert; +import io.deephaven.chunk.ByteChunk; +import io.deephaven.chunk.Chunk; +import io.deephaven.chunk.DoubleChunk; +import io.deephaven.chunk.WritableIntChunk; +import io.deephaven.chunk.attributes.Values; +import io.deephaven.chunk.util.hashing.ByteChunkHasher; +import io.deephaven.chunk.util.hashing.DoubleChunkHasher; +import io.deephaven.engine.rowset.RowSequence; +import io.deephaven.engine.rowset.chunkattributes.RowKeys; +import io.deephaven.engine.table.ColumnSource; +import io.deephaven.engine.table.impl.by.IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableByteArraySource; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableDoubleArraySource; +import io.deephaven.util.type.TypeUtils; +import java.lang.Byte; +import java.lang.Double; +import java.lang.Object; +import java.lang.Override; +import java.util.Arrays; + +final class IncrementalAggOpenHasherByteDouble extends IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase { + private ImmutableByteArraySource mainKeySource0; + + private ImmutableByteArraySource alternateKeySource0; + + private ImmutableDoubleArraySource mainKeySource1; + + private ImmutableDoubleArraySource alternateKeySource1; + + public IncrementalAggOpenHasherByteDouble(ColumnSource[] tableKeySources, int tableSize, + double maximumLoadFactor, double targetLoadFactor) { + super(tableKeySources, tableSize, maximumLoadFactor); + this.mainKeySource0 = (ImmutableByteArraySource) super.mainKeySources[0]; + this.mainKeySource0.ensureCapacity(tableSize); + this.mainKeySource1 = (ImmutableDoubleArraySource) super.mainKeySources[1]; + this.mainKeySource1.ensureCapacity(tableSize); + } + + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + + private int alternateNextTableLocation(int tableLocation) { + return (tableLocation + 1) & (alternateTableSize - 1); + } + + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final ByteChunk keyChunk0 = sourceKeyChunks[0].asByteChunk(); + final DoubleChunk keyChunk1 = sourceKeyChunks[1].asDoubleChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final byte k0 = keyChunk0.get(chunkPosition); + final double k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void buildForUpdate(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk reincarnatedPositions) { + final ByteChunk keyChunk0 = sourceKeyChunks[0].asByteChunk(); + final DoubleChunk keyChunk1 = sourceKeyChunks[1].asDoubleChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final byte k0 = keyChunk0.get(chunkPosition); + final double k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void doRemoveProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk emptiedPositions) { + final ByteChunk keyChunk0 = sourceKeyChunks[0].asByteChunk(); + final DoubleChunk keyChunk1 = sourceKeyChunks[1].asDoubleChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final byte k0 = keyChunk0.get(chunkPosition); + final double k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + protected void doModifyProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final ByteChunk keyChunk0 = sourceKeyChunks[0].asByteChunk(); + final DoubleChunk keyChunk1 = sourceKeyChunks[1].asDoubleChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final byte k0 = keyChunk0.get(chunkPosition); + final double k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + private static int hash(byte k0, double k1) { + int hash = ByteChunkHasher.hashInitialSingle(k0); + hash = DoubleChunkHasher.hashUpdateSingle(hash, k1); + return hash; + } + + private boolean migrateOneLocation(int locationToMigrate) { + final int currentStateValue = alternateOutputPosition.getUnsafe(locationToMigrate); + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + return false; + } + final byte k0 = alternateKeySource0.getUnsafe(locationToMigrate); + final double k1 = alternateKeySource1.getUnsafe(locationToMigrate); + final int hash = hash(k0, k1); + int destinationTableLocation = hashToTableLocation(hash); + while (mainOutputPosition.getUnsafe(destinationTableLocation) != EMPTY_OUTPUT_POSITION) { + destinationTableLocation = nextTableLocation(destinationTableLocation); + } + mainKeySource0.set(destinationTableLocation, k0); + mainKeySource1.set(destinationTableLocation, k1); + mainOutputPosition.set(destinationTableLocation, currentStateValue); + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + alternateOutputPosition.set(locationToMigrate, EMPTY_OUTPUT_POSITION); + return true; + } + + @Override + protected int rehashInternalPartial(int entriesToRehash) { + int rehashedEntries = 0; + while (rehashPointer > 0 && rehashedEntries < entriesToRehash) { + if (migrateOneLocation(--rehashPointer)) { + rehashedEntries++; + } + } + return rehashedEntries; + } + + @Override + protected void newAlternate() { + super.newAlternate(); + this.mainKeySource0 = (ImmutableByteArraySource)super.mainKeySources[0]; + this.alternateKeySource0 = (ImmutableByteArraySource)super.alternateKeySources[0]; + this.mainKeySource1 = (ImmutableDoubleArraySource)super.mainKeySources[1]; + this.alternateKeySource1 = (ImmutableDoubleArraySource)super.alternateKeySources[1]; + } + + @Override + protected void clearAlternate() { + super.clearAlternate(); + this.alternateKeySource0 = null; + this.alternateKeySource1 = null; + } + + @Override + protected void migrateFront() { + int location = 0; + while (migrateOneLocation(location++)); + } + + @Override + protected void rehashInternalFull(final int oldSize) { + final byte[] destKeyArray0 = new byte[tableSize]; + final double[] destKeyArray1 = new double[tableSize]; + final int[] destState = new int[tableSize]; + Arrays.fill(destState, EMPTY_OUTPUT_POSITION); + final byte [] originalKeyArray0 = mainKeySource0.getArray(); + mainKeySource0.setArray(destKeyArray0); + final double [] originalKeyArray1 = mainKeySource1.getArray(); + mainKeySource1.setArray(destKeyArray1); + final int [] originalStateArray = mainOutputPosition.getArray(); + mainOutputPosition.setArray(destState); + for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + continue; + } + final byte k0 = originalKeyArray0[sourceBucket]; + final double k1 = originalKeyArray1[sourceBucket]; + final int hash = hash(k0, k1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; + while (true) { + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + break; + } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); + } + } + } + + @Override + public int findPositionForKey(Object key) { + final Object [] ka = (Object[])key; + final byte k0 = TypeUtils.unbox((Byte)ka[0]); + final double k1 = TypeUtils.unbox((Double)ka[1]); + int hash = hash(k0, k1); + int tableLocation = hashToTableLocation(hash); + final int firstTableLocation = tableLocation; + while (true) { + final int positionValue = mainOutputPosition.getUnsafe(tableLocation); + if (positionValue == EMPTY_OUTPUT_POSITION) { + int alternateTableLocation = hashToTableLocationAlternate(hash); + if (alternateTableLocation >= rehashPointer) { + return -1; + } + final int firstAlternateTableLocation = alternateTableLocation; + while (true) { + final int alternatePositionValue = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (alternatePositionValue == EMPTY_OUTPUT_POSITION) { + return -1; + } + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + return alternatePositionValue; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + return positionValue; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherByteFloat.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherByteFloat.java new file mode 100644 index 00000000000..cb4b563f53f --- /dev/null +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherByteFloat.java @@ -0,0 +1,390 @@ +// DO NOT EDIT THIS CLASS, AUTOMATICALLY GENERATED BY io.deephaven.engine.table.impl.by.typed.TypedHasherFactory +// Copyright (c) 2016-2022 Deephaven Data Labs and Patent Pending +// +package io.deephaven.engine.table.impl.by.typed.incopenagg.gen; + +import static io.deephaven.util.compare.ByteComparisons.eq; +import static io.deephaven.util.compare.FloatComparisons.eq; + +import io.deephaven.base.verify.Assert; +import io.deephaven.chunk.ByteChunk; +import io.deephaven.chunk.Chunk; +import io.deephaven.chunk.FloatChunk; +import io.deephaven.chunk.WritableIntChunk; +import io.deephaven.chunk.attributes.Values; +import io.deephaven.chunk.util.hashing.ByteChunkHasher; +import io.deephaven.chunk.util.hashing.FloatChunkHasher; +import io.deephaven.engine.rowset.RowSequence; +import io.deephaven.engine.rowset.chunkattributes.RowKeys; +import io.deephaven.engine.table.ColumnSource; +import io.deephaven.engine.table.impl.by.IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableByteArraySource; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableFloatArraySource; +import io.deephaven.util.type.TypeUtils; +import java.lang.Byte; +import java.lang.Float; +import java.lang.Object; +import java.lang.Override; +import java.util.Arrays; + +final class IncrementalAggOpenHasherByteFloat extends IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase { + private ImmutableByteArraySource mainKeySource0; + + private ImmutableByteArraySource alternateKeySource0; + + private ImmutableFloatArraySource mainKeySource1; + + private ImmutableFloatArraySource alternateKeySource1; + + public IncrementalAggOpenHasherByteFloat(ColumnSource[] tableKeySources, int tableSize, + double maximumLoadFactor, double targetLoadFactor) { + super(tableKeySources, tableSize, maximumLoadFactor); + this.mainKeySource0 = (ImmutableByteArraySource) super.mainKeySources[0]; + this.mainKeySource0.ensureCapacity(tableSize); + this.mainKeySource1 = (ImmutableFloatArraySource) super.mainKeySources[1]; + this.mainKeySource1.ensureCapacity(tableSize); + } + + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + + private int alternateNextTableLocation(int tableLocation) { + return (tableLocation + 1) & (alternateTableSize - 1); + } + + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final ByteChunk keyChunk0 = sourceKeyChunks[0].asByteChunk(); + final FloatChunk keyChunk1 = sourceKeyChunks[1].asFloatChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final byte k0 = keyChunk0.get(chunkPosition); + final float k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void buildForUpdate(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk reincarnatedPositions) { + final ByteChunk keyChunk0 = sourceKeyChunks[0].asByteChunk(); + final FloatChunk keyChunk1 = sourceKeyChunks[1].asFloatChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final byte k0 = keyChunk0.get(chunkPosition); + final float k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void doRemoveProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk emptiedPositions) { + final ByteChunk keyChunk0 = sourceKeyChunks[0].asByteChunk(); + final FloatChunk keyChunk1 = sourceKeyChunks[1].asFloatChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final byte k0 = keyChunk0.get(chunkPosition); + final float k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + protected void doModifyProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final ByteChunk keyChunk0 = sourceKeyChunks[0].asByteChunk(); + final FloatChunk keyChunk1 = sourceKeyChunks[1].asFloatChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final byte k0 = keyChunk0.get(chunkPosition); + final float k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + private static int hash(byte k0, float k1) { + int hash = ByteChunkHasher.hashInitialSingle(k0); + hash = FloatChunkHasher.hashUpdateSingle(hash, k1); + return hash; + } + + private boolean migrateOneLocation(int locationToMigrate) { + final int currentStateValue = alternateOutputPosition.getUnsafe(locationToMigrate); + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + return false; + } + final byte k0 = alternateKeySource0.getUnsafe(locationToMigrate); + final float k1 = alternateKeySource1.getUnsafe(locationToMigrate); + final int hash = hash(k0, k1); + int destinationTableLocation = hashToTableLocation(hash); + while (mainOutputPosition.getUnsafe(destinationTableLocation) != EMPTY_OUTPUT_POSITION) { + destinationTableLocation = nextTableLocation(destinationTableLocation); + } + mainKeySource0.set(destinationTableLocation, k0); + mainKeySource1.set(destinationTableLocation, k1); + mainOutputPosition.set(destinationTableLocation, currentStateValue); + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + alternateOutputPosition.set(locationToMigrate, EMPTY_OUTPUT_POSITION); + return true; + } + + @Override + protected int rehashInternalPartial(int entriesToRehash) { + int rehashedEntries = 0; + while (rehashPointer > 0 && rehashedEntries < entriesToRehash) { + if (migrateOneLocation(--rehashPointer)) { + rehashedEntries++; + } + } + return rehashedEntries; + } + + @Override + protected void newAlternate() { + super.newAlternate(); + this.mainKeySource0 = (ImmutableByteArraySource)super.mainKeySources[0]; + this.alternateKeySource0 = (ImmutableByteArraySource)super.alternateKeySources[0]; + this.mainKeySource1 = (ImmutableFloatArraySource)super.mainKeySources[1]; + this.alternateKeySource1 = (ImmutableFloatArraySource)super.alternateKeySources[1]; + } + + @Override + protected void clearAlternate() { + super.clearAlternate(); + this.alternateKeySource0 = null; + this.alternateKeySource1 = null; + } + + @Override + protected void migrateFront() { + int location = 0; + while (migrateOneLocation(location++)); + } + + @Override + protected void rehashInternalFull(final int oldSize) { + final byte[] destKeyArray0 = new byte[tableSize]; + final float[] destKeyArray1 = new float[tableSize]; + final int[] destState = new int[tableSize]; + Arrays.fill(destState, EMPTY_OUTPUT_POSITION); + final byte [] originalKeyArray0 = mainKeySource0.getArray(); + mainKeySource0.setArray(destKeyArray0); + final float [] originalKeyArray1 = mainKeySource1.getArray(); + mainKeySource1.setArray(destKeyArray1); + final int [] originalStateArray = mainOutputPosition.getArray(); + mainOutputPosition.setArray(destState); + for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + continue; + } + final byte k0 = originalKeyArray0[sourceBucket]; + final float k1 = originalKeyArray1[sourceBucket]; + final int hash = hash(k0, k1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; + while (true) { + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + break; + } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); + } + } + } + + @Override + public int findPositionForKey(Object key) { + final Object [] ka = (Object[])key; + final byte k0 = TypeUtils.unbox((Byte)ka[0]); + final float k1 = TypeUtils.unbox((Float)ka[1]); + int hash = hash(k0, k1); + int tableLocation = hashToTableLocation(hash); + final int firstTableLocation = tableLocation; + while (true) { + final int positionValue = mainOutputPosition.getUnsafe(tableLocation); + if (positionValue == EMPTY_OUTPUT_POSITION) { + int alternateTableLocation = hashToTableLocationAlternate(hash); + if (alternateTableLocation >= rehashPointer) { + return -1; + } + final int firstAlternateTableLocation = alternateTableLocation; + while (true) { + final int alternatePositionValue = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (alternatePositionValue == EMPTY_OUTPUT_POSITION) { + return -1; + } + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + return alternatePositionValue; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + return positionValue; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherByteInt.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherByteInt.java new file mode 100644 index 00000000000..a033982e1a1 --- /dev/null +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherByteInt.java @@ -0,0 +1,390 @@ +// DO NOT EDIT THIS CLASS, AUTOMATICALLY GENERATED BY io.deephaven.engine.table.impl.by.typed.TypedHasherFactory +// Copyright (c) 2016-2022 Deephaven Data Labs and Patent Pending +// +package io.deephaven.engine.table.impl.by.typed.incopenagg.gen; + +import static io.deephaven.util.compare.ByteComparisons.eq; +import static io.deephaven.util.compare.IntComparisons.eq; + +import io.deephaven.base.verify.Assert; +import io.deephaven.chunk.ByteChunk; +import io.deephaven.chunk.Chunk; +import io.deephaven.chunk.IntChunk; +import io.deephaven.chunk.WritableIntChunk; +import io.deephaven.chunk.attributes.Values; +import io.deephaven.chunk.util.hashing.ByteChunkHasher; +import io.deephaven.chunk.util.hashing.IntChunkHasher; +import io.deephaven.engine.rowset.RowSequence; +import io.deephaven.engine.rowset.chunkattributes.RowKeys; +import io.deephaven.engine.table.ColumnSource; +import io.deephaven.engine.table.impl.by.IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableByteArraySource; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableIntArraySource; +import io.deephaven.util.type.TypeUtils; +import java.lang.Byte; +import java.lang.Integer; +import java.lang.Object; +import java.lang.Override; +import java.util.Arrays; + +final class IncrementalAggOpenHasherByteInt extends IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase { + private ImmutableByteArraySource mainKeySource0; + + private ImmutableByteArraySource alternateKeySource0; + + private ImmutableIntArraySource mainKeySource1; + + private ImmutableIntArraySource alternateKeySource1; + + public IncrementalAggOpenHasherByteInt(ColumnSource[] tableKeySources, int tableSize, + double maximumLoadFactor, double targetLoadFactor) { + super(tableKeySources, tableSize, maximumLoadFactor); + this.mainKeySource0 = (ImmutableByteArraySource) super.mainKeySources[0]; + this.mainKeySource0.ensureCapacity(tableSize); + this.mainKeySource1 = (ImmutableIntArraySource) super.mainKeySources[1]; + this.mainKeySource1.ensureCapacity(tableSize); + } + + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + + private int alternateNextTableLocation(int tableLocation) { + return (tableLocation + 1) & (alternateTableSize - 1); + } + + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final ByteChunk keyChunk0 = sourceKeyChunks[0].asByteChunk(); + final IntChunk keyChunk1 = sourceKeyChunks[1].asIntChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final byte k0 = keyChunk0.get(chunkPosition); + final int k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void buildForUpdate(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk reincarnatedPositions) { + final ByteChunk keyChunk0 = sourceKeyChunks[0].asByteChunk(); + final IntChunk keyChunk1 = sourceKeyChunks[1].asIntChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final byte k0 = keyChunk0.get(chunkPosition); + final int k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void doRemoveProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk emptiedPositions) { + final ByteChunk keyChunk0 = sourceKeyChunks[0].asByteChunk(); + final IntChunk keyChunk1 = sourceKeyChunks[1].asIntChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final byte k0 = keyChunk0.get(chunkPosition); + final int k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + protected void doModifyProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final ByteChunk keyChunk0 = sourceKeyChunks[0].asByteChunk(); + final IntChunk keyChunk1 = sourceKeyChunks[1].asIntChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final byte k0 = keyChunk0.get(chunkPosition); + final int k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + private static int hash(byte k0, int k1) { + int hash = ByteChunkHasher.hashInitialSingle(k0); + hash = IntChunkHasher.hashUpdateSingle(hash, k1); + return hash; + } + + private boolean migrateOneLocation(int locationToMigrate) { + final int currentStateValue = alternateOutputPosition.getUnsafe(locationToMigrate); + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + return false; + } + final byte k0 = alternateKeySource0.getUnsafe(locationToMigrate); + final int k1 = alternateKeySource1.getUnsafe(locationToMigrate); + final int hash = hash(k0, k1); + int destinationTableLocation = hashToTableLocation(hash); + while (mainOutputPosition.getUnsafe(destinationTableLocation) != EMPTY_OUTPUT_POSITION) { + destinationTableLocation = nextTableLocation(destinationTableLocation); + } + mainKeySource0.set(destinationTableLocation, k0); + mainKeySource1.set(destinationTableLocation, k1); + mainOutputPosition.set(destinationTableLocation, currentStateValue); + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + alternateOutputPosition.set(locationToMigrate, EMPTY_OUTPUT_POSITION); + return true; + } + + @Override + protected int rehashInternalPartial(int entriesToRehash) { + int rehashedEntries = 0; + while (rehashPointer > 0 && rehashedEntries < entriesToRehash) { + if (migrateOneLocation(--rehashPointer)) { + rehashedEntries++; + } + } + return rehashedEntries; + } + + @Override + protected void newAlternate() { + super.newAlternate(); + this.mainKeySource0 = (ImmutableByteArraySource)super.mainKeySources[0]; + this.alternateKeySource0 = (ImmutableByteArraySource)super.alternateKeySources[0]; + this.mainKeySource1 = (ImmutableIntArraySource)super.mainKeySources[1]; + this.alternateKeySource1 = (ImmutableIntArraySource)super.alternateKeySources[1]; + } + + @Override + protected void clearAlternate() { + super.clearAlternate(); + this.alternateKeySource0 = null; + this.alternateKeySource1 = null; + } + + @Override + protected void migrateFront() { + int location = 0; + while (migrateOneLocation(location++)); + } + + @Override + protected void rehashInternalFull(final int oldSize) { + final byte[] destKeyArray0 = new byte[tableSize]; + final int[] destKeyArray1 = new int[tableSize]; + final int[] destState = new int[tableSize]; + Arrays.fill(destState, EMPTY_OUTPUT_POSITION); + final byte [] originalKeyArray0 = mainKeySource0.getArray(); + mainKeySource0.setArray(destKeyArray0); + final int [] originalKeyArray1 = mainKeySource1.getArray(); + mainKeySource1.setArray(destKeyArray1); + final int [] originalStateArray = mainOutputPosition.getArray(); + mainOutputPosition.setArray(destState); + for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + continue; + } + final byte k0 = originalKeyArray0[sourceBucket]; + final int k1 = originalKeyArray1[sourceBucket]; + final int hash = hash(k0, k1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; + while (true) { + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + break; + } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); + } + } + } + + @Override + public int findPositionForKey(Object key) { + final Object [] ka = (Object[])key; + final byte k0 = TypeUtils.unbox((Byte)ka[0]); + final int k1 = TypeUtils.unbox((Integer)ka[1]); + int hash = hash(k0, k1); + int tableLocation = hashToTableLocation(hash); + final int firstTableLocation = tableLocation; + while (true) { + final int positionValue = mainOutputPosition.getUnsafe(tableLocation); + if (positionValue == EMPTY_OUTPUT_POSITION) { + int alternateTableLocation = hashToTableLocationAlternate(hash); + if (alternateTableLocation >= rehashPointer) { + return -1; + } + final int firstAlternateTableLocation = alternateTableLocation; + while (true) { + final int alternatePositionValue = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (alternatePositionValue == EMPTY_OUTPUT_POSITION) { + return -1; + } + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + return alternatePositionValue; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + return positionValue; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherByteLong.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherByteLong.java new file mode 100644 index 00000000000..e6d9ac39dc4 --- /dev/null +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherByteLong.java @@ -0,0 +1,390 @@ +// DO NOT EDIT THIS CLASS, AUTOMATICALLY GENERATED BY io.deephaven.engine.table.impl.by.typed.TypedHasherFactory +// Copyright (c) 2016-2022 Deephaven Data Labs and Patent Pending +// +package io.deephaven.engine.table.impl.by.typed.incopenagg.gen; + +import static io.deephaven.util.compare.ByteComparisons.eq; +import static io.deephaven.util.compare.LongComparisons.eq; + +import io.deephaven.base.verify.Assert; +import io.deephaven.chunk.ByteChunk; +import io.deephaven.chunk.Chunk; +import io.deephaven.chunk.LongChunk; +import io.deephaven.chunk.WritableIntChunk; +import io.deephaven.chunk.attributes.Values; +import io.deephaven.chunk.util.hashing.ByteChunkHasher; +import io.deephaven.chunk.util.hashing.LongChunkHasher; +import io.deephaven.engine.rowset.RowSequence; +import io.deephaven.engine.rowset.chunkattributes.RowKeys; +import io.deephaven.engine.table.ColumnSource; +import io.deephaven.engine.table.impl.by.IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableByteArraySource; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableLongArraySource; +import io.deephaven.util.type.TypeUtils; +import java.lang.Byte; +import java.lang.Long; +import java.lang.Object; +import java.lang.Override; +import java.util.Arrays; + +final class IncrementalAggOpenHasherByteLong extends IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase { + private ImmutableByteArraySource mainKeySource0; + + private ImmutableByteArraySource alternateKeySource0; + + private ImmutableLongArraySource mainKeySource1; + + private ImmutableLongArraySource alternateKeySource1; + + public IncrementalAggOpenHasherByteLong(ColumnSource[] tableKeySources, int tableSize, + double maximumLoadFactor, double targetLoadFactor) { + super(tableKeySources, tableSize, maximumLoadFactor); + this.mainKeySource0 = (ImmutableByteArraySource) super.mainKeySources[0]; + this.mainKeySource0.ensureCapacity(tableSize); + this.mainKeySource1 = (ImmutableLongArraySource) super.mainKeySources[1]; + this.mainKeySource1.ensureCapacity(tableSize); + } + + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + + private int alternateNextTableLocation(int tableLocation) { + return (tableLocation + 1) & (alternateTableSize - 1); + } + + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final ByteChunk keyChunk0 = sourceKeyChunks[0].asByteChunk(); + final LongChunk keyChunk1 = sourceKeyChunks[1].asLongChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final byte k0 = keyChunk0.get(chunkPosition); + final long k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void buildForUpdate(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk reincarnatedPositions) { + final ByteChunk keyChunk0 = sourceKeyChunks[0].asByteChunk(); + final LongChunk keyChunk1 = sourceKeyChunks[1].asLongChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final byte k0 = keyChunk0.get(chunkPosition); + final long k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void doRemoveProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk emptiedPositions) { + final ByteChunk keyChunk0 = sourceKeyChunks[0].asByteChunk(); + final LongChunk keyChunk1 = sourceKeyChunks[1].asLongChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final byte k0 = keyChunk0.get(chunkPosition); + final long k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + protected void doModifyProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final ByteChunk keyChunk0 = sourceKeyChunks[0].asByteChunk(); + final LongChunk keyChunk1 = sourceKeyChunks[1].asLongChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final byte k0 = keyChunk0.get(chunkPosition); + final long k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + private static int hash(byte k0, long k1) { + int hash = ByteChunkHasher.hashInitialSingle(k0); + hash = LongChunkHasher.hashUpdateSingle(hash, k1); + return hash; + } + + private boolean migrateOneLocation(int locationToMigrate) { + final int currentStateValue = alternateOutputPosition.getUnsafe(locationToMigrate); + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + return false; + } + final byte k0 = alternateKeySource0.getUnsafe(locationToMigrate); + final long k1 = alternateKeySource1.getUnsafe(locationToMigrate); + final int hash = hash(k0, k1); + int destinationTableLocation = hashToTableLocation(hash); + while (mainOutputPosition.getUnsafe(destinationTableLocation) != EMPTY_OUTPUT_POSITION) { + destinationTableLocation = nextTableLocation(destinationTableLocation); + } + mainKeySource0.set(destinationTableLocation, k0); + mainKeySource1.set(destinationTableLocation, k1); + mainOutputPosition.set(destinationTableLocation, currentStateValue); + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + alternateOutputPosition.set(locationToMigrate, EMPTY_OUTPUT_POSITION); + return true; + } + + @Override + protected int rehashInternalPartial(int entriesToRehash) { + int rehashedEntries = 0; + while (rehashPointer > 0 && rehashedEntries < entriesToRehash) { + if (migrateOneLocation(--rehashPointer)) { + rehashedEntries++; + } + } + return rehashedEntries; + } + + @Override + protected void newAlternate() { + super.newAlternate(); + this.mainKeySource0 = (ImmutableByteArraySource)super.mainKeySources[0]; + this.alternateKeySource0 = (ImmutableByteArraySource)super.alternateKeySources[0]; + this.mainKeySource1 = (ImmutableLongArraySource)super.mainKeySources[1]; + this.alternateKeySource1 = (ImmutableLongArraySource)super.alternateKeySources[1]; + } + + @Override + protected void clearAlternate() { + super.clearAlternate(); + this.alternateKeySource0 = null; + this.alternateKeySource1 = null; + } + + @Override + protected void migrateFront() { + int location = 0; + while (migrateOneLocation(location++)); + } + + @Override + protected void rehashInternalFull(final int oldSize) { + final byte[] destKeyArray0 = new byte[tableSize]; + final long[] destKeyArray1 = new long[tableSize]; + final int[] destState = new int[tableSize]; + Arrays.fill(destState, EMPTY_OUTPUT_POSITION); + final byte [] originalKeyArray0 = mainKeySource0.getArray(); + mainKeySource0.setArray(destKeyArray0); + final long [] originalKeyArray1 = mainKeySource1.getArray(); + mainKeySource1.setArray(destKeyArray1); + final int [] originalStateArray = mainOutputPosition.getArray(); + mainOutputPosition.setArray(destState); + for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + continue; + } + final byte k0 = originalKeyArray0[sourceBucket]; + final long k1 = originalKeyArray1[sourceBucket]; + final int hash = hash(k0, k1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; + while (true) { + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + break; + } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); + } + } + } + + @Override + public int findPositionForKey(Object key) { + final Object [] ka = (Object[])key; + final byte k0 = TypeUtils.unbox((Byte)ka[0]); + final long k1 = TypeUtils.unbox((Long)ka[1]); + int hash = hash(k0, k1); + int tableLocation = hashToTableLocation(hash); + final int firstTableLocation = tableLocation; + while (true) { + final int positionValue = mainOutputPosition.getUnsafe(tableLocation); + if (positionValue == EMPTY_OUTPUT_POSITION) { + int alternateTableLocation = hashToTableLocationAlternate(hash); + if (alternateTableLocation >= rehashPointer) { + return -1; + } + final int firstAlternateTableLocation = alternateTableLocation; + while (true) { + final int alternatePositionValue = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (alternatePositionValue == EMPTY_OUTPUT_POSITION) { + return -1; + } + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + return alternatePositionValue; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + return positionValue; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherByteObject.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherByteObject.java new file mode 100644 index 00000000000..348bec6cf53 --- /dev/null +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherByteObject.java @@ -0,0 +1,390 @@ +// DO NOT EDIT THIS CLASS, AUTOMATICALLY GENERATED BY io.deephaven.engine.table.impl.by.typed.TypedHasherFactory +// Copyright (c) 2016-2022 Deephaven Data Labs and Patent Pending +// +package io.deephaven.engine.table.impl.by.typed.incopenagg.gen; + +import static io.deephaven.util.compare.ByteComparisons.eq; +import static io.deephaven.util.compare.ObjectComparisons.eq; + +import io.deephaven.base.verify.Assert; +import io.deephaven.chunk.ByteChunk; +import io.deephaven.chunk.Chunk; +import io.deephaven.chunk.ObjectChunk; +import io.deephaven.chunk.WritableIntChunk; +import io.deephaven.chunk.attributes.Values; +import io.deephaven.chunk.util.hashing.ByteChunkHasher; +import io.deephaven.chunk.util.hashing.ObjectChunkHasher; +import io.deephaven.engine.rowset.RowSequence; +import io.deephaven.engine.rowset.chunkattributes.RowKeys; +import io.deephaven.engine.table.ColumnSource; +import io.deephaven.engine.table.impl.by.IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableByteArraySource; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableObjectArraySource; +import io.deephaven.util.type.TypeUtils; +import java.lang.Byte; +import java.lang.Object; +import java.lang.Override; +import java.util.Arrays; + +final class IncrementalAggOpenHasherByteObject extends IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase { + private ImmutableByteArraySource mainKeySource0; + + private ImmutableByteArraySource alternateKeySource0; + + private ImmutableObjectArraySource mainKeySource1; + + private ImmutableObjectArraySource alternateKeySource1; + + public IncrementalAggOpenHasherByteObject(ColumnSource[] tableKeySources, int tableSize, + double maximumLoadFactor, double targetLoadFactor) { + super(tableKeySources, tableSize, maximumLoadFactor); + this.mainKeySource0 = (ImmutableByteArraySource) super.mainKeySources[0]; + this.mainKeySource0.ensureCapacity(tableSize); + this.mainKeySource1 = (ImmutableObjectArraySource) super.mainKeySources[1]; + this.mainKeySource1.ensureCapacity(tableSize); + } + + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + + private int alternateNextTableLocation(int tableLocation) { + return (tableLocation + 1) & (alternateTableSize - 1); + } + + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final ByteChunk keyChunk0 = sourceKeyChunks[0].asByteChunk(); + final ObjectChunk keyChunk1 = sourceKeyChunks[1].asObjectChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final byte k0 = keyChunk0.get(chunkPosition); + final Object k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void buildForUpdate(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk reincarnatedPositions) { + final ByteChunk keyChunk0 = sourceKeyChunks[0].asByteChunk(); + final ObjectChunk keyChunk1 = sourceKeyChunks[1].asObjectChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final byte k0 = keyChunk0.get(chunkPosition); + final Object k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void doRemoveProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk emptiedPositions) { + final ByteChunk keyChunk0 = sourceKeyChunks[0].asByteChunk(); + final ObjectChunk keyChunk1 = sourceKeyChunks[1].asObjectChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final byte k0 = keyChunk0.get(chunkPosition); + final Object k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + protected void doModifyProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final ByteChunk keyChunk0 = sourceKeyChunks[0].asByteChunk(); + final ObjectChunk keyChunk1 = sourceKeyChunks[1].asObjectChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final byte k0 = keyChunk0.get(chunkPosition); + final Object k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + private static int hash(byte k0, Object k1) { + int hash = ByteChunkHasher.hashInitialSingle(k0); + hash = ObjectChunkHasher.hashUpdateSingle(hash, k1); + return hash; + } + + private boolean migrateOneLocation(int locationToMigrate) { + final int currentStateValue = alternateOutputPosition.getUnsafe(locationToMigrate); + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + return false; + } + final byte k0 = alternateKeySource0.getUnsafe(locationToMigrate); + final Object k1 = alternateKeySource1.getUnsafe(locationToMigrate); + final int hash = hash(k0, k1); + int destinationTableLocation = hashToTableLocation(hash); + while (mainOutputPosition.getUnsafe(destinationTableLocation) != EMPTY_OUTPUT_POSITION) { + destinationTableLocation = nextTableLocation(destinationTableLocation); + } + mainKeySource0.set(destinationTableLocation, k0); + mainKeySource1.set(destinationTableLocation, k1); + alternateKeySource1.set(locationToMigrate, null); + mainOutputPosition.set(destinationTableLocation, currentStateValue); + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + alternateOutputPosition.set(locationToMigrate, EMPTY_OUTPUT_POSITION); + return true; + } + + @Override + protected int rehashInternalPartial(int entriesToRehash) { + int rehashedEntries = 0; + while (rehashPointer > 0 && rehashedEntries < entriesToRehash) { + if (migrateOneLocation(--rehashPointer)) { + rehashedEntries++; + } + } + return rehashedEntries; + } + + @Override + protected void newAlternate() { + super.newAlternate(); + this.mainKeySource0 = (ImmutableByteArraySource)super.mainKeySources[0]; + this.alternateKeySource0 = (ImmutableByteArraySource)super.alternateKeySources[0]; + this.mainKeySource1 = (ImmutableObjectArraySource)super.mainKeySources[1]; + this.alternateKeySource1 = (ImmutableObjectArraySource)super.alternateKeySources[1]; + } + + @Override + protected void clearAlternate() { + super.clearAlternate(); + this.alternateKeySource0 = null; + this.alternateKeySource1 = null; + } + + @Override + protected void migrateFront() { + int location = 0; + while (migrateOneLocation(location++)); + } + + @Override + protected void rehashInternalFull(final int oldSize) { + final byte[] destKeyArray0 = new byte[tableSize]; + final Object[] destKeyArray1 = new Object[tableSize]; + final int[] destState = new int[tableSize]; + Arrays.fill(destState, EMPTY_OUTPUT_POSITION); + final byte [] originalKeyArray0 = mainKeySource0.getArray(); + mainKeySource0.setArray(destKeyArray0); + final Object [] originalKeyArray1 = mainKeySource1.getArray(); + mainKeySource1.setArray(destKeyArray1); + final int [] originalStateArray = mainOutputPosition.getArray(); + mainOutputPosition.setArray(destState); + for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + continue; + } + final byte k0 = originalKeyArray0[sourceBucket]; + final Object k1 = originalKeyArray1[sourceBucket]; + final int hash = hash(k0, k1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; + while (true) { + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + break; + } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); + } + } + } + + @Override + public int findPositionForKey(Object key) { + final Object [] ka = (Object[])key; + final byte k0 = TypeUtils.unbox((Byte)ka[0]); + final Object k1 = ka[1]; + int hash = hash(k0, k1); + int tableLocation = hashToTableLocation(hash); + final int firstTableLocation = tableLocation; + while (true) { + final int positionValue = mainOutputPosition.getUnsafe(tableLocation); + if (positionValue == EMPTY_OUTPUT_POSITION) { + int alternateTableLocation = hashToTableLocationAlternate(hash); + if (alternateTableLocation >= rehashPointer) { + return -1; + } + final int firstAlternateTableLocation = alternateTableLocation; + while (true) { + final int alternatePositionValue = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (alternatePositionValue == EMPTY_OUTPUT_POSITION) { + return -1; + } + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + return alternatePositionValue; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + return positionValue; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherByteShort.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherByteShort.java new file mode 100644 index 00000000000..330bdc850b8 --- /dev/null +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherByteShort.java @@ -0,0 +1,390 @@ +// DO NOT EDIT THIS CLASS, AUTOMATICALLY GENERATED BY io.deephaven.engine.table.impl.by.typed.TypedHasherFactory +// Copyright (c) 2016-2022 Deephaven Data Labs and Patent Pending +// +package io.deephaven.engine.table.impl.by.typed.incopenagg.gen; + +import static io.deephaven.util.compare.ByteComparisons.eq; +import static io.deephaven.util.compare.ShortComparisons.eq; + +import io.deephaven.base.verify.Assert; +import io.deephaven.chunk.ByteChunk; +import io.deephaven.chunk.Chunk; +import io.deephaven.chunk.ShortChunk; +import io.deephaven.chunk.WritableIntChunk; +import io.deephaven.chunk.attributes.Values; +import io.deephaven.chunk.util.hashing.ByteChunkHasher; +import io.deephaven.chunk.util.hashing.ShortChunkHasher; +import io.deephaven.engine.rowset.RowSequence; +import io.deephaven.engine.rowset.chunkattributes.RowKeys; +import io.deephaven.engine.table.ColumnSource; +import io.deephaven.engine.table.impl.by.IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableByteArraySource; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableShortArraySource; +import io.deephaven.util.type.TypeUtils; +import java.lang.Byte; +import java.lang.Object; +import java.lang.Override; +import java.lang.Short; +import java.util.Arrays; + +final class IncrementalAggOpenHasherByteShort extends IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase { + private ImmutableByteArraySource mainKeySource0; + + private ImmutableByteArraySource alternateKeySource0; + + private ImmutableShortArraySource mainKeySource1; + + private ImmutableShortArraySource alternateKeySource1; + + public IncrementalAggOpenHasherByteShort(ColumnSource[] tableKeySources, int tableSize, + double maximumLoadFactor, double targetLoadFactor) { + super(tableKeySources, tableSize, maximumLoadFactor); + this.mainKeySource0 = (ImmutableByteArraySource) super.mainKeySources[0]; + this.mainKeySource0.ensureCapacity(tableSize); + this.mainKeySource1 = (ImmutableShortArraySource) super.mainKeySources[1]; + this.mainKeySource1.ensureCapacity(tableSize); + } + + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + + private int alternateNextTableLocation(int tableLocation) { + return (tableLocation + 1) & (alternateTableSize - 1); + } + + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final ByteChunk keyChunk0 = sourceKeyChunks[0].asByteChunk(); + final ShortChunk keyChunk1 = sourceKeyChunks[1].asShortChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final byte k0 = keyChunk0.get(chunkPosition); + final short k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void buildForUpdate(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk reincarnatedPositions) { + final ByteChunk keyChunk0 = sourceKeyChunks[0].asByteChunk(); + final ShortChunk keyChunk1 = sourceKeyChunks[1].asShortChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final byte k0 = keyChunk0.get(chunkPosition); + final short k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void doRemoveProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk emptiedPositions) { + final ByteChunk keyChunk0 = sourceKeyChunks[0].asByteChunk(); + final ShortChunk keyChunk1 = sourceKeyChunks[1].asShortChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final byte k0 = keyChunk0.get(chunkPosition); + final short k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + protected void doModifyProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final ByteChunk keyChunk0 = sourceKeyChunks[0].asByteChunk(); + final ShortChunk keyChunk1 = sourceKeyChunks[1].asShortChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final byte k0 = keyChunk0.get(chunkPosition); + final short k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + private static int hash(byte k0, short k1) { + int hash = ByteChunkHasher.hashInitialSingle(k0); + hash = ShortChunkHasher.hashUpdateSingle(hash, k1); + return hash; + } + + private boolean migrateOneLocation(int locationToMigrate) { + final int currentStateValue = alternateOutputPosition.getUnsafe(locationToMigrate); + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + return false; + } + final byte k0 = alternateKeySource0.getUnsafe(locationToMigrate); + final short k1 = alternateKeySource1.getUnsafe(locationToMigrate); + final int hash = hash(k0, k1); + int destinationTableLocation = hashToTableLocation(hash); + while (mainOutputPosition.getUnsafe(destinationTableLocation) != EMPTY_OUTPUT_POSITION) { + destinationTableLocation = nextTableLocation(destinationTableLocation); + } + mainKeySource0.set(destinationTableLocation, k0); + mainKeySource1.set(destinationTableLocation, k1); + mainOutputPosition.set(destinationTableLocation, currentStateValue); + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + alternateOutputPosition.set(locationToMigrate, EMPTY_OUTPUT_POSITION); + return true; + } + + @Override + protected int rehashInternalPartial(int entriesToRehash) { + int rehashedEntries = 0; + while (rehashPointer > 0 && rehashedEntries < entriesToRehash) { + if (migrateOneLocation(--rehashPointer)) { + rehashedEntries++; + } + } + return rehashedEntries; + } + + @Override + protected void newAlternate() { + super.newAlternate(); + this.mainKeySource0 = (ImmutableByteArraySource)super.mainKeySources[0]; + this.alternateKeySource0 = (ImmutableByteArraySource)super.alternateKeySources[0]; + this.mainKeySource1 = (ImmutableShortArraySource)super.mainKeySources[1]; + this.alternateKeySource1 = (ImmutableShortArraySource)super.alternateKeySources[1]; + } + + @Override + protected void clearAlternate() { + super.clearAlternate(); + this.alternateKeySource0 = null; + this.alternateKeySource1 = null; + } + + @Override + protected void migrateFront() { + int location = 0; + while (migrateOneLocation(location++)); + } + + @Override + protected void rehashInternalFull(final int oldSize) { + final byte[] destKeyArray0 = new byte[tableSize]; + final short[] destKeyArray1 = new short[tableSize]; + final int[] destState = new int[tableSize]; + Arrays.fill(destState, EMPTY_OUTPUT_POSITION); + final byte [] originalKeyArray0 = mainKeySource0.getArray(); + mainKeySource0.setArray(destKeyArray0); + final short [] originalKeyArray1 = mainKeySource1.getArray(); + mainKeySource1.setArray(destKeyArray1); + final int [] originalStateArray = mainOutputPosition.getArray(); + mainOutputPosition.setArray(destState); + for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + continue; + } + final byte k0 = originalKeyArray0[sourceBucket]; + final short k1 = originalKeyArray1[sourceBucket]; + final int hash = hash(k0, k1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; + while (true) { + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + break; + } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); + } + } + } + + @Override + public int findPositionForKey(Object key) { + final Object [] ka = (Object[])key; + final byte k0 = TypeUtils.unbox((Byte)ka[0]); + final short k1 = TypeUtils.unbox((Short)ka[1]); + int hash = hash(k0, k1); + int tableLocation = hashToTableLocation(hash); + final int firstTableLocation = tableLocation; + while (true) { + final int positionValue = mainOutputPosition.getUnsafe(tableLocation); + if (positionValue == EMPTY_OUTPUT_POSITION) { + int alternateTableLocation = hashToTableLocationAlternate(hash); + if (alternateTableLocation >= rehashPointer) { + return -1; + } + final int firstAlternateTableLocation = alternateTableLocation; + while (true) { + final int alternatePositionValue = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (alternatePositionValue == EMPTY_OUTPUT_POSITION) { + return -1; + } + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + return alternatePositionValue; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + return positionValue; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherChar.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherChar.java new file mode 100644 index 00000000000..daac4add97a --- /dev/null +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherChar.java @@ -0,0 +1,356 @@ +// DO NOT EDIT THIS CLASS, AUTOMATICALLY GENERATED BY io.deephaven.engine.table.impl.by.typed.TypedHasherFactory +// Copyright (c) 2016-2022 Deephaven Data Labs and Patent Pending +// +package io.deephaven.engine.table.impl.by.typed.incopenagg.gen; + +import static io.deephaven.util.compare.CharComparisons.eq; + +import io.deephaven.base.verify.Assert; +import io.deephaven.chunk.CharChunk; +import io.deephaven.chunk.Chunk; +import io.deephaven.chunk.WritableIntChunk; +import io.deephaven.chunk.attributes.Values; +import io.deephaven.chunk.util.hashing.CharChunkHasher; +import io.deephaven.engine.rowset.RowSequence; +import io.deephaven.engine.rowset.chunkattributes.RowKeys; +import io.deephaven.engine.table.ColumnSource; +import io.deephaven.engine.table.impl.by.IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableCharArraySource; +import io.deephaven.util.type.TypeUtils; +import java.lang.Character; +import java.lang.Object; +import java.lang.Override; +import java.util.Arrays; + +final class IncrementalAggOpenHasherChar extends IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase { + private ImmutableCharArraySource mainKeySource0; + + private ImmutableCharArraySource alternateKeySource0; + + public IncrementalAggOpenHasherChar(ColumnSource[] tableKeySources, int tableSize, + double maximumLoadFactor, double targetLoadFactor) { + super(tableKeySources, tableSize, maximumLoadFactor); + this.mainKeySource0 = (ImmutableCharArraySource) super.mainKeySources[0]; + this.mainKeySource0.ensureCapacity(tableSize); + } + + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + + private int alternateNextTableLocation(int tableLocation) { + return (tableLocation + 1) & (alternateTableSize - 1); + } + + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final CharChunk keyChunk0 = sourceKeyChunks[0].asCharChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final char k0 = keyChunk0.get(chunkPosition); + final int hash = hash(k0); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void buildForUpdate(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk reincarnatedPositions) { + final CharChunk keyChunk0 = sourceKeyChunks[0].asCharChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final char k0 = keyChunk0.get(chunkPosition); + final int hash = hash(k0); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void doRemoveProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk emptiedPositions) { + final CharChunk keyChunk0 = sourceKeyChunks[0].asCharChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final char k0 = keyChunk0.get(chunkPosition); + final int hash = hash(k0); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + protected void doModifyProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final CharChunk keyChunk0 = sourceKeyChunks[0].asCharChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final char k0 = keyChunk0.get(chunkPosition); + final int hash = hash(k0); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0)) { + outputPositions.set(chunkPosition, outputPosition); + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0)) { + outputPositions.set(chunkPosition, outputPosition); + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + private static int hash(char k0) { + int hash = CharChunkHasher.hashInitialSingle(k0); + return hash; + } + + private boolean migrateOneLocation(int locationToMigrate) { + final int currentStateValue = alternateOutputPosition.getUnsafe(locationToMigrate); + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + return false; + } + final char k0 = alternateKeySource0.getUnsafe(locationToMigrate); + final int hash = hash(k0); + int destinationTableLocation = hashToTableLocation(hash); + while (mainOutputPosition.getUnsafe(destinationTableLocation) != EMPTY_OUTPUT_POSITION) { + destinationTableLocation = nextTableLocation(destinationTableLocation); + } + mainKeySource0.set(destinationTableLocation, k0); + mainOutputPosition.set(destinationTableLocation, currentStateValue); + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + alternateOutputPosition.set(locationToMigrate, EMPTY_OUTPUT_POSITION); + return true; + } + + @Override + protected int rehashInternalPartial(int entriesToRehash) { + int rehashedEntries = 0; + while (rehashPointer > 0 && rehashedEntries < entriesToRehash) { + if (migrateOneLocation(--rehashPointer)) { + rehashedEntries++; + } + } + return rehashedEntries; + } + + @Override + protected void newAlternate() { + super.newAlternate(); + this.mainKeySource0 = (ImmutableCharArraySource)super.mainKeySources[0]; + this.alternateKeySource0 = (ImmutableCharArraySource)super.alternateKeySources[0]; + } + + @Override + protected void clearAlternate() { + super.clearAlternate(); + this.alternateKeySource0 = null; + } + + @Override + protected void migrateFront() { + int location = 0; + while (migrateOneLocation(location++)); + } + + @Override + protected void rehashInternalFull(final int oldSize) { + final char[] destKeyArray0 = new char[tableSize]; + final int[] destState = new int[tableSize]; + Arrays.fill(destState, EMPTY_OUTPUT_POSITION); + final char [] originalKeyArray0 = mainKeySource0.getArray(); + mainKeySource0.setArray(destKeyArray0); + final int [] originalStateArray = mainOutputPosition.getArray(); + mainOutputPosition.setArray(destState); + for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + continue; + } + final char k0 = originalKeyArray0[sourceBucket]; + final int hash = hash(k0); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; + while (true) { + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + break; + } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); + } + } + } + + @Override + public int findPositionForKey(Object key) { + final char k0 = TypeUtils.unbox((Character)key); + int hash = hash(k0); + int tableLocation = hashToTableLocation(hash); + final int firstTableLocation = tableLocation; + while (true) { + final int positionValue = mainOutputPosition.getUnsafe(tableLocation); + if (positionValue == EMPTY_OUTPUT_POSITION) { + int alternateTableLocation = hashToTableLocationAlternate(hash); + if (alternateTableLocation >= rehashPointer) { + return -1; + } + final int firstAlternateTableLocation = alternateTableLocation; + while (true) { + final int alternatePositionValue = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (alternatePositionValue == EMPTY_OUTPUT_POSITION) { + return -1; + } + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0)) { + return alternatePositionValue; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (eq(mainKeySource0.getUnsafe(tableLocation), k0)) { + return positionValue; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherCharByte.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherCharByte.java new file mode 100644 index 00000000000..d655b63058d --- /dev/null +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherCharByte.java @@ -0,0 +1,390 @@ +// DO NOT EDIT THIS CLASS, AUTOMATICALLY GENERATED BY io.deephaven.engine.table.impl.by.typed.TypedHasherFactory +// Copyright (c) 2016-2022 Deephaven Data Labs and Patent Pending +// +package io.deephaven.engine.table.impl.by.typed.incopenagg.gen; + +import static io.deephaven.util.compare.ByteComparisons.eq; +import static io.deephaven.util.compare.CharComparisons.eq; + +import io.deephaven.base.verify.Assert; +import io.deephaven.chunk.ByteChunk; +import io.deephaven.chunk.CharChunk; +import io.deephaven.chunk.Chunk; +import io.deephaven.chunk.WritableIntChunk; +import io.deephaven.chunk.attributes.Values; +import io.deephaven.chunk.util.hashing.ByteChunkHasher; +import io.deephaven.chunk.util.hashing.CharChunkHasher; +import io.deephaven.engine.rowset.RowSequence; +import io.deephaven.engine.rowset.chunkattributes.RowKeys; +import io.deephaven.engine.table.ColumnSource; +import io.deephaven.engine.table.impl.by.IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableByteArraySource; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableCharArraySource; +import io.deephaven.util.type.TypeUtils; +import java.lang.Byte; +import java.lang.Character; +import java.lang.Object; +import java.lang.Override; +import java.util.Arrays; + +final class IncrementalAggOpenHasherCharByte extends IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase { + private ImmutableCharArraySource mainKeySource0; + + private ImmutableCharArraySource alternateKeySource0; + + private ImmutableByteArraySource mainKeySource1; + + private ImmutableByteArraySource alternateKeySource1; + + public IncrementalAggOpenHasherCharByte(ColumnSource[] tableKeySources, int tableSize, + double maximumLoadFactor, double targetLoadFactor) { + super(tableKeySources, tableSize, maximumLoadFactor); + this.mainKeySource0 = (ImmutableCharArraySource) super.mainKeySources[0]; + this.mainKeySource0.ensureCapacity(tableSize); + this.mainKeySource1 = (ImmutableByteArraySource) super.mainKeySources[1]; + this.mainKeySource1.ensureCapacity(tableSize); + } + + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + + private int alternateNextTableLocation(int tableLocation) { + return (tableLocation + 1) & (alternateTableSize - 1); + } + + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final CharChunk keyChunk0 = sourceKeyChunks[0].asCharChunk(); + final ByteChunk keyChunk1 = sourceKeyChunks[1].asByteChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final char k0 = keyChunk0.get(chunkPosition); + final byte k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void buildForUpdate(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk reincarnatedPositions) { + final CharChunk keyChunk0 = sourceKeyChunks[0].asCharChunk(); + final ByteChunk keyChunk1 = sourceKeyChunks[1].asByteChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final char k0 = keyChunk0.get(chunkPosition); + final byte k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void doRemoveProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk emptiedPositions) { + final CharChunk keyChunk0 = sourceKeyChunks[0].asCharChunk(); + final ByteChunk keyChunk1 = sourceKeyChunks[1].asByteChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final char k0 = keyChunk0.get(chunkPosition); + final byte k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + protected void doModifyProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final CharChunk keyChunk0 = sourceKeyChunks[0].asCharChunk(); + final ByteChunk keyChunk1 = sourceKeyChunks[1].asByteChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final char k0 = keyChunk0.get(chunkPosition); + final byte k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + private static int hash(char k0, byte k1) { + int hash = CharChunkHasher.hashInitialSingle(k0); + hash = ByteChunkHasher.hashUpdateSingle(hash, k1); + return hash; + } + + private boolean migrateOneLocation(int locationToMigrate) { + final int currentStateValue = alternateOutputPosition.getUnsafe(locationToMigrate); + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + return false; + } + final char k0 = alternateKeySource0.getUnsafe(locationToMigrate); + final byte k1 = alternateKeySource1.getUnsafe(locationToMigrate); + final int hash = hash(k0, k1); + int destinationTableLocation = hashToTableLocation(hash); + while (mainOutputPosition.getUnsafe(destinationTableLocation) != EMPTY_OUTPUT_POSITION) { + destinationTableLocation = nextTableLocation(destinationTableLocation); + } + mainKeySource0.set(destinationTableLocation, k0); + mainKeySource1.set(destinationTableLocation, k1); + mainOutputPosition.set(destinationTableLocation, currentStateValue); + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + alternateOutputPosition.set(locationToMigrate, EMPTY_OUTPUT_POSITION); + return true; + } + + @Override + protected int rehashInternalPartial(int entriesToRehash) { + int rehashedEntries = 0; + while (rehashPointer > 0 && rehashedEntries < entriesToRehash) { + if (migrateOneLocation(--rehashPointer)) { + rehashedEntries++; + } + } + return rehashedEntries; + } + + @Override + protected void newAlternate() { + super.newAlternate(); + this.mainKeySource0 = (ImmutableCharArraySource)super.mainKeySources[0]; + this.alternateKeySource0 = (ImmutableCharArraySource)super.alternateKeySources[0]; + this.mainKeySource1 = (ImmutableByteArraySource)super.mainKeySources[1]; + this.alternateKeySource1 = (ImmutableByteArraySource)super.alternateKeySources[1]; + } + + @Override + protected void clearAlternate() { + super.clearAlternate(); + this.alternateKeySource0 = null; + this.alternateKeySource1 = null; + } + + @Override + protected void migrateFront() { + int location = 0; + while (migrateOneLocation(location++)); + } + + @Override + protected void rehashInternalFull(final int oldSize) { + final char[] destKeyArray0 = new char[tableSize]; + final byte[] destKeyArray1 = new byte[tableSize]; + final int[] destState = new int[tableSize]; + Arrays.fill(destState, EMPTY_OUTPUT_POSITION); + final char [] originalKeyArray0 = mainKeySource0.getArray(); + mainKeySource0.setArray(destKeyArray0); + final byte [] originalKeyArray1 = mainKeySource1.getArray(); + mainKeySource1.setArray(destKeyArray1); + final int [] originalStateArray = mainOutputPosition.getArray(); + mainOutputPosition.setArray(destState); + for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + continue; + } + final char k0 = originalKeyArray0[sourceBucket]; + final byte k1 = originalKeyArray1[sourceBucket]; + final int hash = hash(k0, k1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; + while (true) { + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + break; + } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); + } + } + } + + @Override + public int findPositionForKey(Object key) { + final Object [] ka = (Object[])key; + final char k0 = TypeUtils.unbox((Character)ka[0]); + final byte k1 = TypeUtils.unbox((Byte)ka[1]); + int hash = hash(k0, k1); + int tableLocation = hashToTableLocation(hash); + final int firstTableLocation = tableLocation; + while (true) { + final int positionValue = mainOutputPosition.getUnsafe(tableLocation); + if (positionValue == EMPTY_OUTPUT_POSITION) { + int alternateTableLocation = hashToTableLocationAlternate(hash); + if (alternateTableLocation >= rehashPointer) { + return -1; + } + final int firstAlternateTableLocation = alternateTableLocation; + while (true) { + final int alternatePositionValue = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (alternatePositionValue == EMPTY_OUTPUT_POSITION) { + return -1; + } + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + return alternatePositionValue; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + return positionValue; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherCharChar.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherCharChar.java new file mode 100644 index 00000000000..faaf793c162 --- /dev/null +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherCharChar.java @@ -0,0 +1,385 @@ +// DO NOT EDIT THIS CLASS, AUTOMATICALLY GENERATED BY io.deephaven.engine.table.impl.by.typed.TypedHasherFactory +// Copyright (c) 2016-2022 Deephaven Data Labs and Patent Pending +// +package io.deephaven.engine.table.impl.by.typed.incopenagg.gen; + +import static io.deephaven.util.compare.CharComparisons.eq; + +import io.deephaven.base.verify.Assert; +import io.deephaven.chunk.CharChunk; +import io.deephaven.chunk.Chunk; +import io.deephaven.chunk.WritableIntChunk; +import io.deephaven.chunk.attributes.Values; +import io.deephaven.chunk.util.hashing.CharChunkHasher; +import io.deephaven.engine.rowset.RowSequence; +import io.deephaven.engine.rowset.chunkattributes.RowKeys; +import io.deephaven.engine.table.ColumnSource; +import io.deephaven.engine.table.impl.by.IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableCharArraySource; +import io.deephaven.util.type.TypeUtils; +import java.lang.Character; +import java.lang.Object; +import java.lang.Override; +import java.util.Arrays; + +final class IncrementalAggOpenHasherCharChar extends IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase { + private ImmutableCharArraySource mainKeySource0; + + private ImmutableCharArraySource alternateKeySource0; + + private ImmutableCharArraySource mainKeySource1; + + private ImmutableCharArraySource alternateKeySource1; + + public IncrementalAggOpenHasherCharChar(ColumnSource[] tableKeySources, int tableSize, + double maximumLoadFactor, double targetLoadFactor) { + super(tableKeySources, tableSize, maximumLoadFactor); + this.mainKeySource0 = (ImmutableCharArraySource) super.mainKeySources[0]; + this.mainKeySource0.ensureCapacity(tableSize); + this.mainKeySource1 = (ImmutableCharArraySource) super.mainKeySources[1]; + this.mainKeySource1.ensureCapacity(tableSize); + } + + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + + private int alternateNextTableLocation(int tableLocation) { + return (tableLocation + 1) & (alternateTableSize - 1); + } + + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final CharChunk keyChunk0 = sourceKeyChunks[0].asCharChunk(); + final CharChunk keyChunk1 = sourceKeyChunks[1].asCharChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final char k0 = keyChunk0.get(chunkPosition); + final char k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void buildForUpdate(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk reincarnatedPositions) { + final CharChunk keyChunk0 = sourceKeyChunks[0].asCharChunk(); + final CharChunk keyChunk1 = sourceKeyChunks[1].asCharChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final char k0 = keyChunk0.get(chunkPosition); + final char k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void doRemoveProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk emptiedPositions) { + final CharChunk keyChunk0 = sourceKeyChunks[0].asCharChunk(); + final CharChunk keyChunk1 = sourceKeyChunks[1].asCharChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final char k0 = keyChunk0.get(chunkPosition); + final char k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + protected void doModifyProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final CharChunk keyChunk0 = sourceKeyChunks[0].asCharChunk(); + final CharChunk keyChunk1 = sourceKeyChunks[1].asCharChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final char k0 = keyChunk0.get(chunkPosition); + final char k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + private static int hash(char k0, char k1) { + int hash = CharChunkHasher.hashInitialSingle(k0); + hash = CharChunkHasher.hashUpdateSingle(hash, k1); + return hash; + } + + private boolean migrateOneLocation(int locationToMigrate) { + final int currentStateValue = alternateOutputPosition.getUnsafe(locationToMigrate); + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + return false; + } + final char k0 = alternateKeySource0.getUnsafe(locationToMigrate); + final char k1 = alternateKeySource1.getUnsafe(locationToMigrate); + final int hash = hash(k0, k1); + int destinationTableLocation = hashToTableLocation(hash); + while (mainOutputPosition.getUnsafe(destinationTableLocation) != EMPTY_OUTPUT_POSITION) { + destinationTableLocation = nextTableLocation(destinationTableLocation); + } + mainKeySource0.set(destinationTableLocation, k0); + mainKeySource1.set(destinationTableLocation, k1); + mainOutputPosition.set(destinationTableLocation, currentStateValue); + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + alternateOutputPosition.set(locationToMigrate, EMPTY_OUTPUT_POSITION); + return true; + } + + @Override + protected int rehashInternalPartial(int entriesToRehash) { + int rehashedEntries = 0; + while (rehashPointer > 0 && rehashedEntries < entriesToRehash) { + if (migrateOneLocation(--rehashPointer)) { + rehashedEntries++; + } + } + return rehashedEntries; + } + + @Override + protected void newAlternate() { + super.newAlternate(); + this.mainKeySource0 = (ImmutableCharArraySource)super.mainKeySources[0]; + this.alternateKeySource0 = (ImmutableCharArraySource)super.alternateKeySources[0]; + this.mainKeySource1 = (ImmutableCharArraySource)super.mainKeySources[1]; + this.alternateKeySource1 = (ImmutableCharArraySource)super.alternateKeySources[1]; + } + + @Override + protected void clearAlternate() { + super.clearAlternate(); + this.alternateKeySource0 = null; + this.alternateKeySource1 = null; + } + + @Override + protected void migrateFront() { + int location = 0; + while (migrateOneLocation(location++)); + } + + @Override + protected void rehashInternalFull(final int oldSize) { + final char[] destKeyArray0 = new char[tableSize]; + final char[] destKeyArray1 = new char[tableSize]; + final int[] destState = new int[tableSize]; + Arrays.fill(destState, EMPTY_OUTPUT_POSITION); + final char [] originalKeyArray0 = mainKeySource0.getArray(); + mainKeySource0.setArray(destKeyArray0); + final char [] originalKeyArray1 = mainKeySource1.getArray(); + mainKeySource1.setArray(destKeyArray1); + final int [] originalStateArray = mainOutputPosition.getArray(); + mainOutputPosition.setArray(destState); + for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + continue; + } + final char k0 = originalKeyArray0[sourceBucket]; + final char k1 = originalKeyArray1[sourceBucket]; + final int hash = hash(k0, k1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; + while (true) { + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + break; + } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); + } + } + } + + @Override + public int findPositionForKey(Object key) { + final Object [] ka = (Object[])key; + final char k0 = TypeUtils.unbox((Character)ka[0]); + final char k1 = TypeUtils.unbox((Character)ka[1]); + int hash = hash(k0, k1); + int tableLocation = hashToTableLocation(hash); + final int firstTableLocation = tableLocation; + while (true) { + final int positionValue = mainOutputPosition.getUnsafe(tableLocation); + if (positionValue == EMPTY_OUTPUT_POSITION) { + int alternateTableLocation = hashToTableLocationAlternate(hash); + if (alternateTableLocation >= rehashPointer) { + return -1; + } + final int firstAlternateTableLocation = alternateTableLocation; + while (true) { + final int alternatePositionValue = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (alternatePositionValue == EMPTY_OUTPUT_POSITION) { + return -1; + } + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + return alternatePositionValue; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + return positionValue; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherCharDouble.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherCharDouble.java new file mode 100644 index 00000000000..05194e0585e --- /dev/null +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherCharDouble.java @@ -0,0 +1,390 @@ +// DO NOT EDIT THIS CLASS, AUTOMATICALLY GENERATED BY io.deephaven.engine.table.impl.by.typed.TypedHasherFactory +// Copyright (c) 2016-2022 Deephaven Data Labs and Patent Pending +// +package io.deephaven.engine.table.impl.by.typed.incopenagg.gen; + +import static io.deephaven.util.compare.CharComparisons.eq; +import static io.deephaven.util.compare.DoubleComparisons.eq; + +import io.deephaven.base.verify.Assert; +import io.deephaven.chunk.CharChunk; +import io.deephaven.chunk.Chunk; +import io.deephaven.chunk.DoubleChunk; +import io.deephaven.chunk.WritableIntChunk; +import io.deephaven.chunk.attributes.Values; +import io.deephaven.chunk.util.hashing.CharChunkHasher; +import io.deephaven.chunk.util.hashing.DoubleChunkHasher; +import io.deephaven.engine.rowset.RowSequence; +import io.deephaven.engine.rowset.chunkattributes.RowKeys; +import io.deephaven.engine.table.ColumnSource; +import io.deephaven.engine.table.impl.by.IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableCharArraySource; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableDoubleArraySource; +import io.deephaven.util.type.TypeUtils; +import java.lang.Character; +import java.lang.Double; +import java.lang.Object; +import java.lang.Override; +import java.util.Arrays; + +final class IncrementalAggOpenHasherCharDouble extends IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase { + private ImmutableCharArraySource mainKeySource0; + + private ImmutableCharArraySource alternateKeySource0; + + private ImmutableDoubleArraySource mainKeySource1; + + private ImmutableDoubleArraySource alternateKeySource1; + + public IncrementalAggOpenHasherCharDouble(ColumnSource[] tableKeySources, int tableSize, + double maximumLoadFactor, double targetLoadFactor) { + super(tableKeySources, tableSize, maximumLoadFactor); + this.mainKeySource0 = (ImmutableCharArraySource) super.mainKeySources[0]; + this.mainKeySource0.ensureCapacity(tableSize); + this.mainKeySource1 = (ImmutableDoubleArraySource) super.mainKeySources[1]; + this.mainKeySource1.ensureCapacity(tableSize); + } + + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + + private int alternateNextTableLocation(int tableLocation) { + return (tableLocation + 1) & (alternateTableSize - 1); + } + + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final CharChunk keyChunk0 = sourceKeyChunks[0].asCharChunk(); + final DoubleChunk keyChunk1 = sourceKeyChunks[1].asDoubleChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final char k0 = keyChunk0.get(chunkPosition); + final double k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void buildForUpdate(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk reincarnatedPositions) { + final CharChunk keyChunk0 = sourceKeyChunks[0].asCharChunk(); + final DoubleChunk keyChunk1 = sourceKeyChunks[1].asDoubleChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final char k0 = keyChunk0.get(chunkPosition); + final double k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void doRemoveProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk emptiedPositions) { + final CharChunk keyChunk0 = sourceKeyChunks[0].asCharChunk(); + final DoubleChunk keyChunk1 = sourceKeyChunks[1].asDoubleChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final char k0 = keyChunk0.get(chunkPosition); + final double k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + protected void doModifyProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final CharChunk keyChunk0 = sourceKeyChunks[0].asCharChunk(); + final DoubleChunk keyChunk1 = sourceKeyChunks[1].asDoubleChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final char k0 = keyChunk0.get(chunkPosition); + final double k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + private static int hash(char k0, double k1) { + int hash = CharChunkHasher.hashInitialSingle(k0); + hash = DoubleChunkHasher.hashUpdateSingle(hash, k1); + return hash; + } + + private boolean migrateOneLocation(int locationToMigrate) { + final int currentStateValue = alternateOutputPosition.getUnsafe(locationToMigrate); + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + return false; + } + final char k0 = alternateKeySource0.getUnsafe(locationToMigrate); + final double k1 = alternateKeySource1.getUnsafe(locationToMigrate); + final int hash = hash(k0, k1); + int destinationTableLocation = hashToTableLocation(hash); + while (mainOutputPosition.getUnsafe(destinationTableLocation) != EMPTY_OUTPUT_POSITION) { + destinationTableLocation = nextTableLocation(destinationTableLocation); + } + mainKeySource0.set(destinationTableLocation, k0); + mainKeySource1.set(destinationTableLocation, k1); + mainOutputPosition.set(destinationTableLocation, currentStateValue); + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + alternateOutputPosition.set(locationToMigrate, EMPTY_OUTPUT_POSITION); + return true; + } + + @Override + protected int rehashInternalPartial(int entriesToRehash) { + int rehashedEntries = 0; + while (rehashPointer > 0 && rehashedEntries < entriesToRehash) { + if (migrateOneLocation(--rehashPointer)) { + rehashedEntries++; + } + } + return rehashedEntries; + } + + @Override + protected void newAlternate() { + super.newAlternate(); + this.mainKeySource0 = (ImmutableCharArraySource)super.mainKeySources[0]; + this.alternateKeySource0 = (ImmutableCharArraySource)super.alternateKeySources[0]; + this.mainKeySource1 = (ImmutableDoubleArraySource)super.mainKeySources[1]; + this.alternateKeySource1 = (ImmutableDoubleArraySource)super.alternateKeySources[1]; + } + + @Override + protected void clearAlternate() { + super.clearAlternate(); + this.alternateKeySource0 = null; + this.alternateKeySource1 = null; + } + + @Override + protected void migrateFront() { + int location = 0; + while (migrateOneLocation(location++)); + } + + @Override + protected void rehashInternalFull(final int oldSize) { + final char[] destKeyArray0 = new char[tableSize]; + final double[] destKeyArray1 = new double[tableSize]; + final int[] destState = new int[tableSize]; + Arrays.fill(destState, EMPTY_OUTPUT_POSITION); + final char [] originalKeyArray0 = mainKeySource0.getArray(); + mainKeySource0.setArray(destKeyArray0); + final double [] originalKeyArray1 = mainKeySource1.getArray(); + mainKeySource1.setArray(destKeyArray1); + final int [] originalStateArray = mainOutputPosition.getArray(); + mainOutputPosition.setArray(destState); + for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + continue; + } + final char k0 = originalKeyArray0[sourceBucket]; + final double k1 = originalKeyArray1[sourceBucket]; + final int hash = hash(k0, k1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; + while (true) { + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + break; + } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); + } + } + } + + @Override + public int findPositionForKey(Object key) { + final Object [] ka = (Object[])key; + final char k0 = TypeUtils.unbox((Character)ka[0]); + final double k1 = TypeUtils.unbox((Double)ka[1]); + int hash = hash(k0, k1); + int tableLocation = hashToTableLocation(hash); + final int firstTableLocation = tableLocation; + while (true) { + final int positionValue = mainOutputPosition.getUnsafe(tableLocation); + if (positionValue == EMPTY_OUTPUT_POSITION) { + int alternateTableLocation = hashToTableLocationAlternate(hash); + if (alternateTableLocation >= rehashPointer) { + return -1; + } + final int firstAlternateTableLocation = alternateTableLocation; + while (true) { + final int alternatePositionValue = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (alternatePositionValue == EMPTY_OUTPUT_POSITION) { + return -1; + } + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + return alternatePositionValue; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + return positionValue; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherCharFloat.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherCharFloat.java new file mode 100644 index 00000000000..7ba40bdf09f --- /dev/null +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherCharFloat.java @@ -0,0 +1,390 @@ +// DO NOT EDIT THIS CLASS, AUTOMATICALLY GENERATED BY io.deephaven.engine.table.impl.by.typed.TypedHasherFactory +// Copyright (c) 2016-2022 Deephaven Data Labs and Patent Pending +// +package io.deephaven.engine.table.impl.by.typed.incopenagg.gen; + +import static io.deephaven.util.compare.CharComparisons.eq; +import static io.deephaven.util.compare.FloatComparisons.eq; + +import io.deephaven.base.verify.Assert; +import io.deephaven.chunk.CharChunk; +import io.deephaven.chunk.Chunk; +import io.deephaven.chunk.FloatChunk; +import io.deephaven.chunk.WritableIntChunk; +import io.deephaven.chunk.attributes.Values; +import io.deephaven.chunk.util.hashing.CharChunkHasher; +import io.deephaven.chunk.util.hashing.FloatChunkHasher; +import io.deephaven.engine.rowset.RowSequence; +import io.deephaven.engine.rowset.chunkattributes.RowKeys; +import io.deephaven.engine.table.ColumnSource; +import io.deephaven.engine.table.impl.by.IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableCharArraySource; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableFloatArraySource; +import io.deephaven.util.type.TypeUtils; +import java.lang.Character; +import java.lang.Float; +import java.lang.Object; +import java.lang.Override; +import java.util.Arrays; + +final class IncrementalAggOpenHasherCharFloat extends IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase { + private ImmutableCharArraySource mainKeySource0; + + private ImmutableCharArraySource alternateKeySource0; + + private ImmutableFloatArraySource mainKeySource1; + + private ImmutableFloatArraySource alternateKeySource1; + + public IncrementalAggOpenHasherCharFloat(ColumnSource[] tableKeySources, int tableSize, + double maximumLoadFactor, double targetLoadFactor) { + super(tableKeySources, tableSize, maximumLoadFactor); + this.mainKeySource0 = (ImmutableCharArraySource) super.mainKeySources[0]; + this.mainKeySource0.ensureCapacity(tableSize); + this.mainKeySource1 = (ImmutableFloatArraySource) super.mainKeySources[1]; + this.mainKeySource1.ensureCapacity(tableSize); + } + + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + + private int alternateNextTableLocation(int tableLocation) { + return (tableLocation + 1) & (alternateTableSize - 1); + } + + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final CharChunk keyChunk0 = sourceKeyChunks[0].asCharChunk(); + final FloatChunk keyChunk1 = sourceKeyChunks[1].asFloatChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final char k0 = keyChunk0.get(chunkPosition); + final float k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void buildForUpdate(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk reincarnatedPositions) { + final CharChunk keyChunk0 = sourceKeyChunks[0].asCharChunk(); + final FloatChunk keyChunk1 = sourceKeyChunks[1].asFloatChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final char k0 = keyChunk0.get(chunkPosition); + final float k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void doRemoveProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk emptiedPositions) { + final CharChunk keyChunk0 = sourceKeyChunks[0].asCharChunk(); + final FloatChunk keyChunk1 = sourceKeyChunks[1].asFloatChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final char k0 = keyChunk0.get(chunkPosition); + final float k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + protected void doModifyProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final CharChunk keyChunk0 = sourceKeyChunks[0].asCharChunk(); + final FloatChunk keyChunk1 = sourceKeyChunks[1].asFloatChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final char k0 = keyChunk0.get(chunkPosition); + final float k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + private static int hash(char k0, float k1) { + int hash = CharChunkHasher.hashInitialSingle(k0); + hash = FloatChunkHasher.hashUpdateSingle(hash, k1); + return hash; + } + + private boolean migrateOneLocation(int locationToMigrate) { + final int currentStateValue = alternateOutputPosition.getUnsafe(locationToMigrate); + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + return false; + } + final char k0 = alternateKeySource0.getUnsafe(locationToMigrate); + final float k1 = alternateKeySource1.getUnsafe(locationToMigrate); + final int hash = hash(k0, k1); + int destinationTableLocation = hashToTableLocation(hash); + while (mainOutputPosition.getUnsafe(destinationTableLocation) != EMPTY_OUTPUT_POSITION) { + destinationTableLocation = nextTableLocation(destinationTableLocation); + } + mainKeySource0.set(destinationTableLocation, k0); + mainKeySource1.set(destinationTableLocation, k1); + mainOutputPosition.set(destinationTableLocation, currentStateValue); + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + alternateOutputPosition.set(locationToMigrate, EMPTY_OUTPUT_POSITION); + return true; + } + + @Override + protected int rehashInternalPartial(int entriesToRehash) { + int rehashedEntries = 0; + while (rehashPointer > 0 && rehashedEntries < entriesToRehash) { + if (migrateOneLocation(--rehashPointer)) { + rehashedEntries++; + } + } + return rehashedEntries; + } + + @Override + protected void newAlternate() { + super.newAlternate(); + this.mainKeySource0 = (ImmutableCharArraySource)super.mainKeySources[0]; + this.alternateKeySource0 = (ImmutableCharArraySource)super.alternateKeySources[0]; + this.mainKeySource1 = (ImmutableFloatArraySource)super.mainKeySources[1]; + this.alternateKeySource1 = (ImmutableFloatArraySource)super.alternateKeySources[1]; + } + + @Override + protected void clearAlternate() { + super.clearAlternate(); + this.alternateKeySource0 = null; + this.alternateKeySource1 = null; + } + + @Override + protected void migrateFront() { + int location = 0; + while (migrateOneLocation(location++)); + } + + @Override + protected void rehashInternalFull(final int oldSize) { + final char[] destKeyArray0 = new char[tableSize]; + final float[] destKeyArray1 = new float[tableSize]; + final int[] destState = new int[tableSize]; + Arrays.fill(destState, EMPTY_OUTPUT_POSITION); + final char [] originalKeyArray0 = mainKeySource0.getArray(); + mainKeySource0.setArray(destKeyArray0); + final float [] originalKeyArray1 = mainKeySource1.getArray(); + mainKeySource1.setArray(destKeyArray1); + final int [] originalStateArray = mainOutputPosition.getArray(); + mainOutputPosition.setArray(destState); + for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + continue; + } + final char k0 = originalKeyArray0[sourceBucket]; + final float k1 = originalKeyArray1[sourceBucket]; + final int hash = hash(k0, k1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; + while (true) { + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + break; + } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); + } + } + } + + @Override + public int findPositionForKey(Object key) { + final Object [] ka = (Object[])key; + final char k0 = TypeUtils.unbox((Character)ka[0]); + final float k1 = TypeUtils.unbox((Float)ka[1]); + int hash = hash(k0, k1); + int tableLocation = hashToTableLocation(hash); + final int firstTableLocation = tableLocation; + while (true) { + final int positionValue = mainOutputPosition.getUnsafe(tableLocation); + if (positionValue == EMPTY_OUTPUT_POSITION) { + int alternateTableLocation = hashToTableLocationAlternate(hash); + if (alternateTableLocation >= rehashPointer) { + return -1; + } + final int firstAlternateTableLocation = alternateTableLocation; + while (true) { + final int alternatePositionValue = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (alternatePositionValue == EMPTY_OUTPUT_POSITION) { + return -1; + } + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + return alternatePositionValue; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + return positionValue; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherCharInt.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherCharInt.java new file mode 100644 index 00000000000..4cfb90cf856 --- /dev/null +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherCharInt.java @@ -0,0 +1,390 @@ +// DO NOT EDIT THIS CLASS, AUTOMATICALLY GENERATED BY io.deephaven.engine.table.impl.by.typed.TypedHasherFactory +// Copyright (c) 2016-2022 Deephaven Data Labs and Patent Pending +// +package io.deephaven.engine.table.impl.by.typed.incopenagg.gen; + +import static io.deephaven.util.compare.CharComparisons.eq; +import static io.deephaven.util.compare.IntComparisons.eq; + +import io.deephaven.base.verify.Assert; +import io.deephaven.chunk.CharChunk; +import io.deephaven.chunk.Chunk; +import io.deephaven.chunk.IntChunk; +import io.deephaven.chunk.WritableIntChunk; +import io.deephaven.chunk.attributes.Values; +import io.deephaven.chunk.util.hashing.CharChunkHasher; +import io.deephaven.chunk.util.hashing.IntChunkHasher; +import io.deephaven.engine.rowset.RowSequence; +import io.deephaven.engine.rowset.chunkattributes.RowKeys; +import io.deephaven.engine.table.ColumnSource; +import io.deephaven.engine.table.impl.by.IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableCharArraySource; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableIntArraySource; +import io.deephaven.util.type.TypeUtils; +import java.lang.Character; +import java.lang.Integer; +import java.lang.Object; +import java.lang.Override; +import java.util.Arrays; + +final class IncrementalAggOpenHasherCharInt extends IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase { + private ImmutableCharArraySource mainKeySource0; + + private ImmutableCharArraySource alternateKeySource0; + + private ImmutableIntArraySource mainKeySource1; + + private ImmutableIntArraySource alternateKeySource1; + + public IncrementalAggOpenHasherCharInt(ColumnSource[] tableKeySources, int tableSize, + double maximumLoadFactor, double targetLoadFactor) { + super(tableKeySources, tableSize, maximumLoadFactor); + this.mainKeySource0 = (ImmutableCharArraySource) super.mainKeySources[0]; + this.mainKeySource0.ensureCapacity(tableSize); + this.mainKeySource1 = (ImmutableIntArraySource) super.mainKeySources[1]; + this.mainKeySource1.ensureCapacity(tableSize); + } + + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + + private int alternateNextTableLocation(int tableLocation) { + return (tableLocation + 1) & (alternateTableSize - 1); + } + + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final CharChunk keyChunk0 = sourceKeyChunks[0].asCharChunk(); + final IntChunk keyChunk1 = sourceKeyChunks[1].asIntChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final char k0 = keyChunk0.get(chunkPosition); + final int k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void buildForUpdate(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk reincarnatedPositions) { + final CharChunk keyChunk0 = sourceKeyChunks[0].asCharChunk(); + final IntChunk keyChunk1 = sourceKeyChunks[1].asIntChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final char k0 = keyChunk0.get(chunkPosition); + final int k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void doRemoveProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk emptiedPositions) { + final CharChunk keyChunk0 = sourceKeyChunks[0].asCharChunk(); + final IntChunk keyChunk1 = sourceKeyChunks[1].asIntChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final char k0 = keyChunk0.get(chunkPosition); + final int k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + protected void doModifyProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final CharChunk keyChunk0 = sourceKeyChunks[0].asCharChunk(); + final IntChunk keyChunk1 = sourceKeyChunks[1].asIntChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final char k0 = keyChunk0.get(chunkPosition); + final int k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + private static int hash(char k0, int k1) { + int hash = CharChunkHasher.hashInitialSingle(k0); + hash = IntChunkHasher.hashUpdateSingle(hash, k1); + return hash; + } + + private boolean migrateOneLocation(int locationToMigrate) { + final int currentStateValue = alternateOutputPosition.getUnsafe(locationToMigrate); + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + return false; + } + final char k0 = alternateKeySource0.getUnsafe(locationToMigrate); + final int k1 = alternateKeySource1.getUnsafe(locationToMigrate); + final int hash = hash(k0, k1); + int destinationTableLocation = hashToTableLocation(hash); + while (mainOutputPosition.getUnsafe(destinationTableLocation) != EMPTY_OUTPUT_POSITION) { + destinationTableLocation = nextTableLocation(destinationTableLocation); + } + mainKeySource0.set(destinationTableLocation, k0); + mainKeySource1.set(destinationTableLocation, k1); + mainOutputPosition.set(destinationTableLocation, currentStateValue); + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + alternateOutputPosition.set(locationToMigrate, EMPTY_OUTPUT_POSITION); + return true; + } + + @Override + protected int rehashInternalPartial(int entriesToRehash) { + int rehashedEntries = 0; + while (rehashPointer > 0 && rehashedEntries < entriesToRehash) { + if (migrateOneLocation(--rehashPointer)) { + rehashedEntries++; + } + } + return rehashedEntries; + } + + @Override + protected void newAlternate() { + super.newAlternate(); + this.mainKeySource0 = (ImmutableCharArraySource)super.mainKeySources[0]; + this.alternateKeySource0 = (ImmutableCharArraySource)super.alternateKeySources[0]; + this.mainKeySource1 = (ImmutableIntArraySource)super.mainKeySources[1]; + this.alternateKeySource1 = (ImmutableIntArraySource)super.alternateKeySources[1]; + } + + @Override + protected void clearAlternate() { + super.clearAlternate(); + this.alternateKeySource0 = null; + this.alternateKeySource1 = null; + } + + @Override + protected void migrateFront() { + int location = 0; + while (migrateOneLocation(location++)); + } + + @Override + protected void rehashInternalFull(final int oldSize) { + final char[] destKeyArray0 = new char[tableSize]; + final int[] destKeyArray1 = new int[tableSize]; + final int[] destState = new int[tableSize]; + Arrays.fill(destState, EMPTY_OUTPUT_POSITION); + final char [] originalKeyArray0 = mainKeySource0.getArray(); + mainKeySource0.setArray(destKeyArray0); + final int [] originalKeyArray1 = mainKeySource1.getArray(); + mainKeySource1.setArray(destKeyArray1); + final int [] originalStateArray = mainOutputPosition.getArray(); + mainOutputPosition.setArray(destState); + for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + continue; + } + final char k0 = originalKeyArray0[sourceBucket]; + final int k1 = originalKeyArray1[sourceBucket]; + final int hash = hash(k0, k1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; + while (true) { + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + break; + } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); + } + } + } + + @Override + public int findPositionForKey(Object key) { + final Object [] ka = (Object[])key; + final char k0 = TypeUtils.unbox((Character)ka[0]); + final int k1 = TypeUtils.unbox((Integer)ka[1]); + int hash = hash(k0, k1); + int tableLocation = hashToTableLocation(hash); + final int firstTableLocation = tableLocation; + while (true) { + final int positionValue = mainOutputPosition.getUnsafe(tableLocation); + if (positionValue == EMPTY_OUTPUT_POSITION) { + int alternateTableLocation = hashToTableLocationAlternate(hash); + if (alternateTableLocation >= rehashPointer) { + return -1; + } + final int firstAlternateTableLocation = alternateTableLocation; + while (true) { + final int alternatePositionValue = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (alternatePositionValue == EMPTY_OUTPUT_POSITION) { + return -1; + } + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + return alternatePositionValue; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + return positionValue; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherCharLong.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherCharLong.java new file mode 100644 index 00000000000..d3989c2d1c5 --- /dev/null +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherCharLong.java @@ -0,0 +1,390 @@ +// DO NOT EDIT THIS CLASS, AUTOMATICALLY GENERATED BY io.deephaven.engine.table.impl.by.typed.TypedHasherFactory +// Copyright (c) 2016-2022 Deephaven Data Labs and Patent Pending +// +package io.deephaven.engine.table.impl.by.typed.incopenagg.gen; + +import static io.deephaven.util.compare.CharComparisons.eq; +import static io.deephaven.util.compare.LongComparisons.eq; + +import io.deephaven.base.verify.Assert; +import io.deephaven.chunk.CharChunk; +import io.deephaven.chunk.Chunk; +import io.deephaven.chunk.LongChunk; +import io.deephaven.chunk.WritableIntChunk; +import io.deephaven.chunk.attributes.Values; +import io.deephaven.chunk.util.hashing.CharChunkHasher; +import io.deephaven.chunk.util.hashing.LongChunkHasher; +import io.deephaven.engine.rowset.RowSequence; +import io.deephaven.engine.rowset.chunkattributes.RowKeys; +import io.deephaven.engine.table.ColumnSource; +import io.deephaven.engine.table.impl.by.IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableCharArraySource; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableLongArraySource; +import io.deephaven.util.type.TypeUtils; +import java.lang.Character; +import java.lang.Long; +import java.lang.Object; +import java.lang.Override; +import java.util.Arrays; + +final class IncrementalAggOpenHasherCharLong extends IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase { + private ImmutableCharArraySource mainKeySource0; + + private ImmutableCharArraySource alternateKeySource0; + + private ImmutableLongArraySource mainKeySource1; + + private ImmutableLongArraySource alternateKeySource1; + + public IncrementalAggOpenHasherCharLong(ColumnSource[] tableKeySources, int tableSize, + double maximumLoadFactor, double targetLoadFactor) { + super(tableKeySources, tableSize, maximumLoadFactor); + this.mainKeySource0 = (ImmutableCharArraySource) super.mainKeySources[0]; + this.mainKeySource0.ensureCapacity(tableSize); + this.mainKeySource1 = (ImmutableLongArraySource) super.mainKeySources[1]; + this.mainKeySource1.ensureCapacity(tableSize); + } + + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + + private int alternateNextTableLocation(int tableLocation) { + return (tableLocation + 1) & (alternateTableSize - 1); + } + + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final CharChunk keyChunk0 = sourceKeyChunks[0].asCharChunk(); + final LongChunk keyChunk1 = sourceKeyChunks[1].asLongChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final char k0 = keyChunk0.get(chunkPosition); + final long k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void buildForUpdate(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk reincarnatedPositions) { + final CharChunk keyChunk0 = sourceKeyChunks[0].asCharChunk(); + final LongChunk keyChunk1 = sourceKeyChunks[1].asLongChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final char k0 = keyChunk0.get(chunkPosition); + final long k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void doRemoveProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk emptiedPositions) { + final CharChunk keyChunk0 = sourceKeyChunks[0].asCharChunk(); + final LongChunk keyChunk1 = sourceKeyChunks[1].asLongChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final char k0 = keyChunk0.get(chunkPosition); + final long k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + protected void doModifyProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final CharChunk keyChunk0 = sourceKeyChunks[0].asCharChunk(); + final LongChunk keyChunk1 = sourceKeyChunks[1].asLongChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final char k0 = keyChunk0.get(chunkPosition); + final long k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + private static int hash(char k0, long k1) { + int hash = CharChunkHasher.hashInitialSingle(k0); + hash = LongChunkHasher.hashUpdateSingle(hash, k1); + return hash; + } + + private boolean migrateOneLocation(int locationToMigrate) { + final int currentStateValue = alternateOutputPosition.getUnsafe(locationToMigrate); + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + return false; + } + final char k0 = alternateKeySource0.getUnsafe(locationToMigrate); + final long k1 = alternateKeySource1.getUnsafe(locationToMigrate); + final int hash = hash(k0, k1); + int destinationTableLocation = hashToTableLocation(hash); + while (mainOutputPosition.getUnsafe(destinationTableLocation) != EMPTY_OUTPUT_POSITION) { + destinationTableLocation = nextTableLocation(destinationTableLocation); + } + mainKeySource0.set(destinationTableLocation, k0); + mainKeySource1.set(destinationTableLocation, k1); + mainOutputPosition.set(destinationTableLocation, currentStateValue); + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + alternateOutputPosition.set(locationToMigrate, EMPTY_OUTPUT_POSITION); + return true; + } + + @Override + protected int rehashInternalPartial(int entriesToRehash) { + int rehashedEntries = 0; + while (rehashPointer > 0 && rehashedEntries < entriesToRehash) { + if (migrateOneLocation(--rehashPointer)) { + rehashedEntries++; + } + } + return rehashedEntries; + } + + @Override + protected void newAlternate() { + super.newAlternate(); + this.mainKeySource0 = (ImmutableCharArraySource)super.mainKeySources[0]; + this.alternateKeySource0 = (ImmutableCharArraySource)super.alternateKeySources[0]; + this.mainKeySource1 = (ImmutableLongArraySource)super.mainKeySources[1]; + this.alternateKeySource1 = (ImmutableLongArraySource)super.alternateKeySources[1]; + } + + @Override + protected void clearAlternate() { + super.clearAlternate(); + this.alternateKeySource0 = null; + this.alternateKeySource1 = null; + } + + @Override + protected void migrateFront() { + int location = 0; + while (migrateOneLocation(location++)); + } + + @Override + protected void rehashInternalFull(final int oldSize) { + final char[] destKeyArray0 = new char[tableSize]; + final long[] destKeyArray1 = new long[tableSize]; + final int[] destState = new int[tableSize]; + Arrays.fill(destState, EMPTY_OUTPUT_POSITION); + final char [] originalKeyArray0 = mainKeySource0.getArray(); + mainKeySource0.setArray(destKeyArray0); + final long [] originalKeyArray1 = mainKeySource1.getArray(); + mainKeySource1.setArray(destKeyArray1); + final int [] originalStateArray = mainOutputPosition.getArray(); + mainOutputPosition.setArray(destState); + for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + continue; + } + final char k0 = originalKeyArray0[sourceBucket]; + final long k1 = originalKeyArray1[sourceBucket]; + final int hash = hash(k0, k1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; + while (true) { + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + break; + } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); + } + } + } + + @Override + public int findPositionForKey(Object key) { + final Object [] ka = (Object[])key; + final char k0 = TypeUtils.unbox((Character)ka[0]); + final long k1 = TypeUtils.unbox((Long)ka[1]); + int hash = hash(k0, k1); + int tableLocation = hashToTableLocation(hash); + final int firstTableLocation = tableLocation; + while (true) { + final int positionValue = mainOutputPosition.getUnsafe(tableLocation); + if (positionValue == EMPTY_OUTPUT_POSITION) { + int alternateTableLocation = hashToTableLocationAlternate(hash); + if (alternateTableLocation >= rehashPointer) { + return -1; + } + final int firstAlternateTableLocation = alternateTableLocation; + while (true) { + final int alternatePositionValue = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (alternatePositionValue == EMPTY_OUTPUT_POSITION) { + return -1; + } + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + return alternatePositionValue; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + return positionValue; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherCharObject.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherCharObject.java new file mode 100644 index 00000000000..a393189f3c6 --- /dev/null +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherCharObject.java @@ -0,0 +1,390 @@ +// DO NOT EDIT THIS CLASS, AUTOMATICALLY GENERATED BY io.deephaven.engine.table.impl.by.typed.TypedHasherFactory +// Copyright (c) 2016-2022 Deephaven Data Labs and Patent Pending +// +package io.deephaven.engine.table.impl.by.typed.incopenagg.gen; + +import static io.deephaven.util.compare.CharComparisons.eq; +import static io.deephaven.util.compare.ObjectComparisons.eq; + +import io.deephaven.base.verify.Assert; +import io.deephaven.chunk.CharChunk; +import io.deephaven.chunk.Chunk; +import io.deephaven.chunk.ObjectChunk; +import io.deephaven.chunk.WritableIntChunk; +import io.deephaven.chunk.attributes.Values; +import io.deephaven.chunk.util.hashing.CharChunkHasher; +import io.deephaven.chunk.util.hashing.ObjectChunkHasher; +import io.deephaven.engine.rowset.RowSequence; +import io.deephaven.engine.rowset.chunkattributes.RowKeys; +import io.deephaven.engine.table.ColumnSource; +import io.deephaven.engine.table.impl.by.IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableCharArraySource; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableObjectArraySource; +import io.deephaven.util.type.TypeUtils; +import java.lang.Character; +import java.lang.Object; +import java.lang.Override; +import java.util.Arrays; + +final class IncrementalAggOpenHasherCharObject extends IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase { + private ImmutableCharArraySource mainKeySource0; + + private ImmutableCharArraySource alternateKeySource0; + + private ImmutableObjectArraySource mainKeySource1; + + private ImmutableObjectArraySource alternateKeySource1; + + public IncrementalAggOpenHasherCharObject(ColumnSource[] tableKeySources, int tableSize, + double maximumLoadFactor, double targetLoadFactor) { + super(tableKeySources, tableSize, maximumLoadFactor); + this.mainKeySource0 = (ImmutableCharArraySource) super.mainKeySources[0]; + this.mainKeySource0.ensureCapacity(tableSize); + this.mainKeySource1 = (ImmutableObjectArraySource) super.mainKeySources[1]; + this.mainKeySource1.ensureCapacity(tableSize); + } + + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + + private int alternateNextTableLocation(int tableLocation) { + return (tableLocation + 1) & (alternateTableSize - 1); + } + + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final CharChunk keyChunk0 = sourceKeyChunks[0].asCharChunk(); + final ObjectChunk keyChunk1 = sourceKeyChunks[1].asObjectChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final char k0 = keyChunk0.get(chunkPosition); + final Object k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void buildForUpdate(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk reincarnatedPositions) { + final CharChunk keyChunk0 = sourceKeyChunks[0].asCharChunk(); + final ObjectChunk keyChunk1 = sourceKeyChunks[1].asObjectChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final char k0 = keyChunk0.get(chunkPosition); + final Object k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void doRemoveProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk emptiedPositions) { + final CharChunk keyChunk0 = sourceKeyChunks[0].asCharChunk(); + final ObjectChunk keyChunk1 = sourceKeyChunks[1].asObjectChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final char k0 = keyChunk0.get(chunkPosition); + final Object k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + protected void doModifyProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final CharChunk keyChunk0 = sourceKeyChunks[0].asCharChunk(); + final ObjectChunk keyChunk1 = sourceKeyChunks[1].asObjectChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final char k0 = keyChunk0.get(chunkPosition); + final Object k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + private static int hash(char k0, Object k1) { + int hash = CharChunkHasher.hashInitialSingle(k0); + hash = ObjectChunkHasher.hashUpdateSingle(hash, k1); + return hash; + } + + private boolean migrateOneLocation(int locationToMigrate) { + final int currentStateValue = alternateOutputPosition.getUnsafe(locationToMigrate); + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + return false; + } + final char k0 = alternateKeySource0.getUnsafe(locationToMigrate); + final Object k1 = alternateKeySource1.getUnsafe(locationToMigrate); + final int hash = hash(k0, k1); + int destinationTableLocation = hashToTableLocation(hash); + while (mainOutputPosition.getUnsafe(destinationTableLocation) != EMPTY_OUTPUT_POSITION) { + destinationTableLocation = nextTableLocation(destinationTableLocation); + } + mainKeySource0.set(destinationTableLocation, k0); + mainKeySource1.set(destinationTableLocation, k1); + alternateKeySource1.set(locationToMigrate, null); + mainOutputPosition.set(destinationTableLocation, currentStateValue); + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + alternateOutputPosition.set(locationToMigrate, EMPTY_OUTPUT_POSITION); + return true; + } + + @Override + protected int rehashInternalPartial(int entriesToRehash) { + int rehashedEntries = 0; + while (rehashPointer > 0 && rehashedEntries < entriesToRehash) { + if (migrateOneLocation(--rehashPointer)) { + rehashedEntries++; + } + } + return rehashedEntries; + } + + @Override + protected void newAlternate() { + super.newAlternate(); + this.mainKeySource0 = (ImmutableCharArraySource)super.mainKeySources[0]; + this.alternateKeySource0 = (ImmutableCharArraySource)super.alternateKeySources[0]; + this.mainKeySource1 = (ImmutableObjectArraySource)super.mainKeySources[1]; + this.alternateKeySource1 = (ImmutableObjectArraySource)super.alternateKeySources[1]; + } + + @Override + protected void clearAlternate() { + super.clearAlternate(); + this.alternateKeySource0 = null; + this.alternateKeySource1 = null; + } + + @Override + protected void migrateFront() { + int location = 0; + while (migrateOneLocation(location++)); + } + + @Override + protected void rehashInternalFull(final int oldSize) { + final char[] destKeyArray0 = new char[tableSize]; + final Object[] destKeyArray1 = new Object[tableSize]; + final int[] destState = new int[tableSize]; + Arrays.fill(destState, EMPTY_OUTPUT_POSITION); + final char [] originalKeyArray0 = mainKeySource0.getArray(); + mainKeySource0.setArray(destKeyArray0); + final Object [] originalKeyArray1 = mainKeySource1.getArray(); + mainKeySource1.setArray(destKeyArray1); + final int [] originalStateArray = mainOutputPosition.getArray(); + mainOutputPosition.setArray(destState); + for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + continue; + } + final char k0 = originalKeyArray0[sourceBucket]; + final Object k1 = originalKeyArray1[sourceBucket]; + final int hash = hash(k0, k1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; + while (true) { + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + break; + } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); + } + } + } + + @Override + public int findPositionForKey(Object key) { + final Object [] ka = (Object[])key; + final char k0 = TypeUtils.unbox((Character)ka[0]); + final Object k1 = ka[1]; + int hash = hash(k0, k1); + int tableLocation = hashToTableLocation(hash); + final int firstTableLocation = tableLocation; + while (true) { + final int positionValue = mainOutputPosition.getUnsafe(tableLocation); + if (positionValue == EMPTY_OUTPUT_POSITION) { + int alternateTableLocation = hashToTableLocationAlternate(hash); + if (alternateTableLocation >= rehashPointer) { + return -1; + } + final int firstAlternateTableLocation = alternateTableLocation; + while (true) { + final int alternatePositionValue = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (alternatePositionValue == EMPTY_OUTPUT_POSITION) { + return -1; + } + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + return alternatePositionValue; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + return positionValue; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherCharShort.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherCharShort.java new file mode 100644 index 00000000000..1a233780421 --- /dev/null +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherCharShort.java @@ -0,0 +1,390 @@ +// DO NOT EDIT THIS CLASS, AUTOMATICALLY GENERATED BY io.deephaven.engine.table.impl.by.typed.TypedHasherFactory +// Copyright (c) 2016-2022 Deephaven Data Labs and Patent Pending +// +package io.deephaven.engine.table.impl.by.typed.incopenagg.gen; + +import static io.deephaven.util.compare.CharComparisons.eq; +import static io.deephaven.util.compare.ShortComparisons.eq; + +import io.deephaven.base.verify.Assert; +import io.deephaven.chunk.CharChunk; +import io.deephaven.chunk.Chunk; +import io.deephaven.chunk.ShortChunk; +import io.deephaven.chunk.WritableIntChunk; +import io.deephaven.chunk.attributes.Values; +import io.deephaven.chunk.util.hashing.CharChunkHasher; +import io.deephaven.chunk.util.hashing.ShortChunkHasher; +import io.deephaven.engine.rowset.RowSequence; +import io.deephaven.engine.rowset.chunkattributes.RowKeys; +import io.deephaven.engine.table.ColumnSource; +import io.deephaven.engine.table.impl.by.IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableCharArraySource; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableShortArraySource; +import io.deephaven.util.type.TypeUtils; +import java.lang.Character; +import java.lang.Object; +import java.lang.Override; +import java.lang.Short; +import java.util.Arrays; + +final class IncrementalAggOpenHasherCharShort extends IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase { + private ImmutableCharArraySource mainKeySource0; + + private ImmutableCharArraySource alternateKeySource0; + + private ImmutableShortArraySource mainKeySource1; + + private ImmutableShortArraySource alternateKeySource1; + + public IncrementalAggOpenHasherCharShort(ColumnSource[] tableKeySources, int tableSize, + double maximumLoadFactor, double targetLoadFactor) { + super(tableKeySources, tableSize, maximumLoadFactor); + this.mainKeySource0 = (ImmutableCharArraySource) super.mainKeySources[0]; + this.mainKeySource0.ensureCapacity(tableSize); + this.mainKeySource1 = (ImmutableShortArraySource) super.mainKeySources[1]; + this.mainKeySource1.ensureCapacity(tableSize); + } + + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + + private int alternateNextTableLocation(int tableLocation) { + return (tableLocation + 1) & (alternateTableSize - 1); + } + + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final CharChunk keyChunk0 = sourceKeyChunks[0].asCharChunk(); + final ShortChunk keyChunk1 = sourceKeyChunks[1].asShortChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final char k0 = keyChunk0.get(chunkPosition); + final short k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void buildForUpdate(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk reincarnatedPositions) { + final CharChunk keyChunk0 = sourceKeyChunks[0].asCharChunk(); + final ShortChunk keyChunk1 = sourceKeyChunks[1].asShortChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final char k0 = keyChunk0.get(chunkPosition); + final short k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void doRemoveProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk emptiedPositions) { + final CharChunk keyChunk0 = sourceKeyChunks[0].asCharChunk(); + final ShortChunk keyChunk1 = sourceKeyChunks[1].asShortChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final char k0 = keyChunk0.get(chunkPosition); + final short k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + protected void doModifyProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final CharChunk keyChunk0 = sourceKeyChunks[0].asCharChunk(); + final ShortChunk keyChunk1 = sourceKeyChunks[1].asShortChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final char k0 = keyChunk0.get(chunkPosition); + final short k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + private static int hash(char k0, short k1) { + int hash = CharChunkHasher.hashInitialSingle(k0); + hash = ShortChunkHasher.hashUpdateSingle(hash, k1); + return hash; + } + + private boolean migrateOneLocation(int locationToMigrate) { + final int currentStateValue = alternateOutputPosition.getUnsafe(locationToMigrate); + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + return false; + } + final char k0 = alternateKeySource0.getUnsafe(locationToMigrate); + final short k1 = alternateKeySource1.getUnsafe(locationToMigrate); + final int hash = hash(k0, k1); + int destinationTableLocation = hashToTableLocation(hash); + while (mainOutputPosition.getUnsafe(destinationTableLocation) != EMPTY_OUTPUT_POSITION) { + destinationTableLocation = nextTableLocation(destinationTableLocation); + } + mainKeySource0.set(destinationTableLocation, k0); + mainKeySource1.set(destinationTableLocation, k1); + mainOutputPosition.set(destinationTableLocation, currentStateValue); + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + alternateOutputPosition.set(locationToMigrate, EMPTY_OUTPUT_POSITION); + return true; + } + + @Override + protected int rehashInternalPartial(int entriesToRehash) { + int rehashedEntries = 0; + while (rehashPointer > 0 && rehashedEntries < entriesToRehash) { + if (migrateOneLocation(--rehashPointer)) { + rehashedEntries++; + } + } + return rehashedEntries; + } + + @Override + protected void newAlternate() { + super.newAlternate(); + this.mainKeySource0 = (ImmutableCharArraySource)super.mainKeySources[0]; + this.alternateKeySource0 = (ImmutableCharArraySource)super.alternateKeySources[0]; + this.mainKeySource1 = (ImmutableShortArraySource)super.mainKeySources[1]; + this.alternateKeySource1 = (ImmutableShortArraySource)super.alternateKeySources[1]; + } + + @Override + protected void clearAlternate() { + super.clearAlternate(); + this.alternateKeySource0 = null; + this.alternateKeySource1 = null; + } + + @Override + protected void migrateFront() { + int location = 0; + while (migrateOneLocation(location++)); + } + + @Override + protected void rehashInternalFull(final int oldSize) { + final char[] destKeyArray0 = new char[tableSize]; + final short[] destKeyArray1 = new short[tableSize]; + final int[] destState = new int[tableSize]; + Arrays.fill(destState, EMPTY_OUTPUT_POSITION); + final char [] originalKeyArray0 = mainKeySource0.getArray(); + mainKeySource0.setArray(destKeyArray0); + final short [] originalKeyArray1 = mainKeySource1.getArray(); + mainKeySource1.setArray(destKeyArray1); + final int [] originalStateArray = mainOutputPosition.getArray(); + mainOutputPosition.setArray(destState); + for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + continue; + } + final char k0 = originalKeyArray0[sourceBucket]; + final short k1 = originalKeyArray1[sourceBucket]; + final int hash = hash(k0, k1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; + while (true) { + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + break; + } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); + } + } + } + + @Override + public int findPositionForKey(Object key) { + final Object [] ka = (Object[])key; + final char k0 = TypeUtils.unbox((Character)ka[0]); + final short k1 = TypeUtils.unbox((Short)ka[1]); + int hash = hash(k0, k1); + int tableLocation = hashToTableLocation(hash); + final int firstTableLocation = tableLocation; + while (true) { + final int positionValue = mainOutputPosition.getUnsafe(tableLocation); + if (positionValue == EMPTY_OUTPUT_POSITION) { + int alternateTableLocation = hashToTableLocationAlternate(hash); + if (alternateTableLocation >= rehashPointer) { + return -1; + } + final int firstAlternateTableLocation = alternateTableLocation; + while (true) { + final int alternatePositionValue = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (alternatePositionValue == EMPTY_OUTPUT_POSITION) { + return -1; + } + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + return alternatePositionValue; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + return positionValue; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherDouble.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherDouble.java new file mode 100644 index 00000000000..1b51043103d --- /dev/null +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherDouble.java @@ -0,0 +1,356 @@ +// DO NOT EDIT THIS CLASS, AUTOMATICALLY GENERATED BY io.deephaven.engine.table.impl.by.typed.TypedHasherFactory +// Copyright (c) 2016-2022 Deephaven Data Labs and Patent Pending +// +package io.deephaven.engine.table.impl.by.typed.incopenagg.gen; + +import static io.deephaven.util.compare.DoubleComparisons.eq; + +import io.deephaven.base.verify.Assert; +import io.deephaven.chunk.Chunk; +import io.deephaven.chunk.DoubleChunk; +import io.deephaven.chunk.WritableIntChunk; +import io.deephaven.chunk.attributes.Values; +import io.deephaven.chunk.util.hashing.DoubleChunkHasher; +import io.deephaven.engine.rowset.RowSequence; +import io.deephaven.engine.rowset.chunkattributes.RowKeys; +import io.deephaven.engine.table.ColumnSource; +import io.deephaven.engine.table.impl.by.IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableDoubleArraySource; +import io.deephaven.util.type.TypeUtils; +import java.lang.Double; +import java.lang.Object; +import java.lang.Override; +import java.util.Arrays; + +final class IncrementalAggOpenHasherDouble extends IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase { + private ImmutableDoubleArraySource mainKeySource0; + + private ImmutableDoubleArraySource alternateKeySource0; + + public IncrementalAggOpenHasherDouble(ColumnSource[] tableKeySources, int tableSize, + double maximumLoadFactor, double targetLoadFactor) { + super(tableKeySources, tableSize, maximumLoadFactor); + this.mainKeySource0 = (ImmutableDoubleArraySource) super.mainKeySources[0]; + this.mainKeySource0.ensureCapacity(tableSize); + } + + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + + private int alternateNextTableLocation(int tableLocation) { + return (tableLocation + 1) & (alternateTableSize - 1); + } + + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final DoubleChunk keyChunk0 = sourceKeyChunks[0].asDoubleChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final double k0 = keyChunk0.get(chunkPosition); + final int hash = hash(k0); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void buildForUpdate(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk reincarnatedPositions) { + final DoubleChunk keyChunk0 = sourceKeyChunks[0].asDoubleChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final double k0 = keyChunk0.get(chunkPosition); + final int hash = hash(k0); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void doRemoveProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk emptiedPositions) { + final DoubleChunk keyChunk0 = sourceKeyChunks[0].asDoubleChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final double k0 = keyChunk0.get(chunkPosition); + final int hash = hash(k0); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + protected void doModifyProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final DoubleChunk keyChunk0 = sourceKeyChunks[0].asDoubleChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final double k0 = keyChunk0.get(chunkPosition); + final int hash = hash(k0); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0)) { + outputPositions.set(chunkPosition, outputPosition); + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0)) { + outputPositions.set(chunkPosition, outputPosition); + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + private static int hash(double k0) { + int hash = DoubleChunkHasher.hashInitialSingle(k0); + return hash; + } + + private boolean migrateOneLocation(int locationToMigrate) { + final int currentStateValue = alternateOutputPosition.getUnsafe(locationToMigrate); + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + return false; + } + final double k0 = alternateKeySource0.getUnsafe(locationToMigrate); + final int hash = hash(k0); + int destinationTableLocation = hashToTableLocation(hash); + while (mainOutputPosition.getUnsafe(destinationTableLocation) != EMPTY_OUTPUT_POSITION) { + destinationTableLocation = nextTableLocation(destinationTableLocation); + } + mainKeySource0.set(destinationTableLocation, k0); + mainOutputPosition.set(destinationTableLocation, currentStateValue); + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + alternateOutputPosition.set(locationToMigrate, EMPTY_OUTPUT_POSITION); + return true; + } + + @Override + protected int rehashInternalPartial(int entriesToRehash) { + int rehashedEntries = 0; + while (rehashPointer > 0 && rehashedEntries < entriesToRehash) { + if (migrateOneLocation(--rehashPointer)) { + rehashedEntries++; + } + } + return rehashedEntries; + } + + @Override + protected void newAlternate() { + super.newAlternate(); + this.mainKeySource0 = (ImmutableDoubleArraySource)super.mainKeySources[0]; + this.alternateKeySource0 = (ImmutableDoubleArraySource)super.alternateKeySources[0]; + } + + @Override + protected void clearAlternate() { + super.clearAlternate(); + this.alternateKeySource0 = null; + } + + @Override + protected void migrateFront() { + int location = 0; + while (migrateOneLocation(location++)); + } + + @Override + protected void rehashInternalFull(final int oldSize) { + final double[] destKeyArray0 = new double[tableSize]; + final int[] destState = new int[tableSize]; + Arrays.fill(destState, EMPTY_OUTPUT_POSITION); + final double [] originalKeyArray0 = mainKeySource0.getArray(); + mainKeySource0.setArray(destKeyArray0); + final int [] originalStateArray = mainOutputPosition.getArray(); + mainOutputPosition.setArray(destState); + for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + continue; + } + final double k0 = originalKeyArray0[sourceBucket]; + final int hash = hash(k0); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; + while (true) { + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + break; + } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); + } + } + } + + @Override + public int findPositionForKey(Object key) { + final double k0 = TypeUtils.unbox((Double)key); + int hash = hash(k0); + int tableLocation = hashToTableLocation(hash); + final int firstTableLocation = tableLocation; + while (true) { + final int positionValue = mainOutputPosition.getUnsafe(tableLocation); + if (positionValue == EMPTY_OUTPUT_POSITION) { + int alternateTableLocation = hashToTableLocationAlternate(hash); + if (alternateTableLocation >= rehashPointer) { + return -1; + } + final int firstAlternateTableLocation = alternateTableLocation; + while (true) { + final int alternatePositionValue = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (alternatePositionValue == EMPTY_OUTPUT_POSITION) { + return -1; + } + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0)) { + return alternatePositionValue; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (eq(mainKeySource0.getUnsafe(tableLocation), k0)) { + return positionValue; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherDoubleByte.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherDoubleByte.java new file mode 100644 index 00000000000..ae2ea470d97 --- /dev/null +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherDoubleByte.java @@ -0,0 +1,390 @@ +// DO NOT EDIT THIS CLASS, AUTOMATICALLY GENERATED BY io.deephaven.engine.table.impl.by.typed.TypedHasherFactory +// Copyright (c) 2016-2022 Deephaven Data Labs and Patent Pending +// +package io.deephaven.engine.table.impl.by.typed.incopenagg.gen; + +import static io.deephaven.util.compare.ByteComparisons.eq; +import static io.deephaven.util.compare.DoubleComparisons.eq; + +import io.deephaven.base.verify.Assert; +import io.deephaven.chunk.ByteChunk; +import io.deephaven.chunk.Chunk; +import io.deephaven.chunk.DoubleChunk; +import io.deephaven.chunk.WritableIntChunk; +import io.deephaven.chunk.attributes.Values; +import io.deephaven.chunk.util.hashing.ByteChunkHasher; +import io.deephaven.chunk.util.hashing.DoubleChunkHasher; +import io.deephaven.engine.rowset.RowSequence; +import io.deephaven.engine.rowset.chunkattributes.RowKeys; +import io.deephaven.engine.table.ColumnSource; +import io.deephaven.engine.table.impl.by.IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableByteArraySource; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableDoubleArraySource; +import io.deephaven.util.type.TypeUtils; +import java.lang.Byte; +import java.lang.Double; +import java.lang.Object; +import java.lang.Override; +import java.util.Arrays; + +final class IncrementalAggOpenHasherDoubleByte extends IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase { + private ImmutableDoubleArraySource mainKeySource0; + + private ImmutableDoubleArraySource alternateKeySource0; + + private ImmutableByteArraySource mainKeySource1; + + private ImmutableByteArraySource alternateKeySource1; + + public IncrementalAggOpenHasherDoubleByte(ColumnSource[] tableKeySources, int tableSize, + double maximumLoadFactor, double targetLoadFactor) { + super(tableKeySources, tableSize, maximumLoadFactor); + this.mainKeySource0 = (ImmutableDoubleArraySource) super.mainKeySources[0]; + this.mainKeySource0.ensureCapacity(tableSize); + this.mainKeySource1 = (ImmutableByteArraySource) super.mainKeySources[1]; + this.mainKeySource1.ensureCapacity(tableSize); + } + + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + + private int alternateNextTableLocation(int tableLocation) { + return (tableLocation + 1) & (alternateTableSize - 1); + } + + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final DoubleChunk keyChunk0 = sourceKeyChunks[0].asDoubleChunk(); + final ByteChunk keyChunk1 = sourceKeyChunks[1].asByteChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final double k0 = keyChunk0.get(chunkPosition); + final byte k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void buildForUpdate(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk reincarnatedPositions) { + final DoubleChunk keyChunk0 = sourceKeyChunks[0].asDoubleChunk(); + final ByteChunk keyChunk1 = sourceKeyChunks[1].asByteChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final double k0 = keyChunk0.get(chunkPosition); + final byte k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void doRemoveProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk emptiedPositions) { + final DoubleChunk keyChunk0 = sourceKeyChunks[0].asDoubleChunk(); + final ByteChunk keyChunk1 = sourceKeyChunks[1].asByteChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final double k0 = keyChunk0.get(chunkPosition); + final byte k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + protected void doModifyProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final DoubleChunk keyChunk0 = sourceKeyChunks[0].asDoubleChunk(); + final ByteChunk keyChunk1 = sourceKeyChunks[1].asByteChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final double k0 = keyChunk0.get(chunkPosition); + final byte k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + private static int hash(double k0, byte k1) { + int hash = DoubleChunkHasher.hashInitialSingle(k0); + hash = ByteChunkHasher.hashUpdateSingle(hash, k1); + return hash; + } + + private boolean migrateOneLocation(int locationToMigrate) { + final int currentStateValue = alternateOutputPosition.getUnsafe(locationToMigrate); + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + return false; + } + final double k0 = alternateKeySource0.getUnsafe(locationToMigrate); + final byte k1 = alternateKeySource1.getUnsafe(locationToMigrate); + final int hash = hash(k0, k1); + int destinationTableLocation = hashToTableLocation(hash); + while (mainOutputPosition.getUnsafe(destinationTableLocation) != EMPTY_OUTPUT_POSITION) { + destinationTableLocation = nextTableLocation(destinationTableLocation); + } + mainKeySource0.set(destinationTableLocation, k0); + mainKeySource1.set(destinationTableLocation, k1); + mainOutputPosition.set(destinationTableLocation, currentStateValue); + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + alternateOutputPosition.set(locationToMigrate, EMPTY_OUTPUT_POSITION); + return true; + } + + @Override + protected int rehashInternalPartial(int entriesToRehash) { + int rehashedEntries = 0; + while (rehashPointer > 0 && rehashedEntries < entriesToRehash) { + if (migrateOneLocation(--rehashPointer)) { + rehashedEntries++; + } + } + return rehashedEntries; + } + + @Override + protected void newAlternate() { + super.newAlternate(); + this.mainKeySource0 = (ImmutableDoubleArraySource)super.mainKeySources[0]; + this.alternateKeySource0 = (ImmutableDoubleArraySource)super.alternateKeySources[0]; + this.mainKeySource1 = (ImmutableByteArraySource)super.mainKeySources[1]; + this.alternateKeySource1 = (ImmutableByteArraySource)super.alternateKeySources[1]; + } + + @Override + protected void clearAlternate() { + super.clearAlternate(); + this.alternateKeySource0 = null; + this.alternateKeySource1 = null; + } + + @Override + protected void migrateFront() { + int location = 0; + while (migrateOneLocation(location++)); + } + + @Override + protected void rehashInternalFull(final int oldSize) { + final double[] destKeyArray0 = new double[tableSize]; + final byte[] destKeyArray1 = new byte[tableSize]; + final int[] destState = new int[tableSize]; + Arrays.fill(destState, EMPTY_OUTPUT_POSITION); + final double [] originalKeyArray0 = mainKeySource0.getArray(); + mainKeySource0.setArray(destKeyArray0); + final byte [] originalKeyArray1 = mainKeySource1.getArray(); + mainKeySource1.setArray(destKeyArray1); + final int [] originalStateArray = mainOutputPosition.getArray(); + mainOutputPosition.setArray(destState); + for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + continue; + } + final double k0 = originalKeyArray0[sourceBucket]; + final byte k1 = originalKeyArray1[sourceBucket]; + final int hash = hash(k0, k1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; + while (true) { + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + break; + } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); + } + } + } + + @Override + public int findPositionForKey(Object key) { + final Object [] ka = (Object[])key; + final double k0 = TypeUtils.unbox((Double)ka[0]); + final byte k1 = TypeUtils.unbox((Byte)ka[1]); + int hash = hash(k0, k1); + int tableLocation = hashToTableLocation(hash); + final int firstTableLocation = tableLocation; + while (true) { + final int positionValue = mainOutputPosition.getUnsafe(tableLocation); + if (positionValue == EMPTY_OUTPUT_POSITION) { + int alternateTableLocation = hashToTableLocationAlternate(hash); + if (alternateTableLocation >= rehashPointer) { + return -1; + } + final int firstAlternateTableLocation = alternateTableLocation; + while (true) { + final int alternatePositionValue = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (alternatePositionValue == EMPTY_OUTPUT_POSITION) { + return -1; + } + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + return alternatePositionValue; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + return positionValue; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherDoubleChar.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherDoubleChar.java new file mode 100644 index 00000000000..18cb6210be7 --- /dev/null +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherDoubleChar.java @@ -0,0 +1,390 @@ +// DO NOT EDIT THIS CLASS, AUTOMATICALLY GENERATED BY io.deephaven.engine.table.impl.by.typed.TypedHasherFactory +// Copyright (c) 2016-2022 Deephaven Data Labs and Patent Pending +// +package io.deephaven.engine.table.impl.by.typed.incopenagg.gen; + +import static io.deephaven.util.compare.CharComparisons.eq; +import static io.deephaven.util.compare.DoubleComparisons.eq; + +import io.deephaven.base.verify.Assert; +import io.deephaven.chunk.CharChunk; +import io.deephaven.chunk.Chunk; +import io.deephaven.chunk.DoubleChunk; +import io.deephaven.chunk.WritableIntChunk; +import io.deephaven.chunk.attributes.Values; +import io.deephaven.chunk.util.hashing.CharChunkHasher; +import io.deephaven.chunk.util.hashing.DoubleChunkHasher; +import io.deephaven.engine.rowset.RowSequence; +import io.deephaven.engine.rowset.chunkattributes.RowKeys; +import io.deephaven.engine.table.ColumnSource; +import io.deephaven.engine.table.impl.by.IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableCharArraySource; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableDoubleArraySource; +import io.deephaven.util.type.TypeUtils; +import java.lang.Character; +import java.lang.Double; +import java.lang.Object; +import java.lang.Override; +import java.util.Arrays; + +final class IncrementalAggOpenHasherDoubleChar extends IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase { + private ImmutableDoubleArraySource mainKeySource0; + + private ImmutableDoubleArraySource alternateKeySource0; + + private ImmutableCharArraySource mainKeySource1; + + private ImmutableCharArraySource alternateKeySource1; + + public IncrementalAggOpenHasherDoubleChar(ColumnSource[] tableKeySources, int tableSize, + double maximumLoadFactor, double targetLoadFactor) { + super(tableKeySources, tableSize, maximumLoadFactor); + this.mainKeySource0 = (ImmutableDoubleArraySource) super.mainKeySources[0]; + this.mainKeySource0.ensureCapacity(tableSize); + this.mainKeySource1 = (ImmutableCharArraySource) super.mainKeySources[1]; + this.mainKeySource1.ensureCapacity(tableSize); + } + + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + + private int alternateNextTableLocation(int tableLocation) { + return (tableLocation + 1) & (alternateTableSize - 1); + } + + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final DoubleChunk keyChunk0 = sourceKeyChunks[0].asDoubleChunk(); + final CharChunk keyChunk1 = sourceKeyChunks[1].asCharChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final double k0 = keyChunk0.get(chunkPosition); + final char k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void buildForUpdate(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk reincarnatedPositions) { + final DoubleChunk keyChunk0 = sourceKeyChunks[0].asDoubleChunk(); + final CharChunk keyChunk1 = sourceKeyChunks[1].asCharChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final double k0 = keyChunk0.get(chunkPosition); + final char k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void doRemoveProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk emptiedPositions) { + final DoubleChunk keyChunk0 = sourceKeyChunks[0].asDoubleChunk(); + final CharChunk keyChunk1 = sourceKeyChunks[1].asCharChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final double k0 = keyChunk0.get(chunkPosition); + final char k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + protected void doModifyProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final DoubleChunk keyChunk0 = sourceKeyChunks[0].asDoubleChunk(); + final CharChunk keyChunk1 = sourceKeyChunks[1].asCharChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final double k0 = keyChunk0.get(chunkPosition); + final char k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + private static int hash(double k0, char k1) { + int hash = DoubleChunkHasher.hashInitialSingle(k0); + hash = CharChunkHasher.hashUpdateSingle(hash, k1); + return hash; + } + + private boolean migrateOneLocation(int locationToMigrate) { + final int currentStateValue = alternateOutputPosition.getUnsafe(locationToMigrate); + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + return false; + } + final double k0 = alternateKeySource0.getUnsafe(locationToMigrate); + final char k1 = alternateKeySource1.getUnsafe(locationToMigrate); + final int hash = hash(k0, k1); + int destinationTableLocation = hashToTableLocation(hash); + while (mainOutputPosition.getUnsafe(destinationTableLocation) != EMPTY_OUTPUT_POSITION) { + destinationTableLocation = nextTableLocation(destinationTableLocation); + } + mainKeySource0.set(destinationTableLocation, k0); + mainKeySource1.set(destinationTableLocation, k1); + mainOutputPosition.set(destinationTableLocation, currentStateValue); + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + alternateOutputPosition.set(locationToMigrate, EMPTY_OUTPUT_POSITION); + return true; + } + + @Override + protected int rehashInternalPartial(int entriesToRehash) { + int rehashedEntries = 0; + while (rehashPointer > 0 && rehashedEntries < entriesToRehash) { + if (migrateOneLocation(--rehashPointer)) { + rehashedEntries++; + } + } + return rehashedEntries; + } + + @Override + protected void newAlternate() { + super.newAlternate(); + this.mainKeySource0 = (ImmutableDoubleArraySource)super.mainKeySources[0]; + this.alternateKeySource0 = (ImmutableDoubleArraySource)super.alternateKeySources[0]; + this.mainKeySource1 = (ImmutableCharArraySource)super.mainKeySources[1]; + this.alternateKeySource1 = (ImmutableCharArraySource)super.alternateKeySources[1]; + } + + @Override + protected void clearAlternate() { + super.clearAlternate(); + this.alternateKeySource0 = null; + this.alternateKeySource1 = null; + } + + @Override + protected void migrateFront() { + int location = 0; + while (migrateOneLocation(location++)); + } + + @Override + protected void rehashInternalFull(final int oldSize) { + final double[] destKeyArray0 = new double[tableSize]; + final char[] destKeyArray1 = new char[tableSize]; + final int[] destState = new int[tableSize]; + Arrays.fill(destState, EMPTY_OUTPUT_POSITION); + final double [] originalKeyArray0 = mainKeySource0.getArray(); + mainKeySource0.setArray(destKeyArray0); + final char [] originalKeyArray1 = mainKeySource1.getArray(); + mainKeySource1.setArray(destKeyArray1); + final int [] originalStateArray = mainOutputPosition.getArray(); + mainOutputPosition.setArray(destState); + for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + continue; + } + final double k0 = originalKeyArray0[sourceBucket]; + final char k1 = originalKeyArray1[sourceBucket]; + final int hash = hash(k0, k1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; + while (true) { + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + break; + } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); + } + } + } + + @Override + public int findPositionForKey(Object key) { + final Object [] ka = (Object[])key; + final double k0 = TypeUtils.unbox((Double)ka[0]); + final char k1 = TypeUtils.unbox((Character)ka[1]); + int hash = hash(k0, k1); + int tableLocation = hashToTableLocation(hash); + final int firstTableLocation = tableLocation; + while (true) { + final int positionValue = mainOutputPosition.getUnsafe(tableLocation); + if (positionValue == EMPTY_OUTPUT_POSITION) { + int alternateTableLocation = hashToTableLocationAlternate(hash); + if (alternateTableLocation >= rehashPointer) { + return -1; + } + final int firstAlternateTableLocation = alternateTableLocation; + while (true) { + final int alternatePositionValue = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (alternatePositionValue == EMPTY_OUTPUT_POSITION) { + return -1; + } + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + return alternatePositionValue; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + return positionValue; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherDoubleDouble.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherDoubleDouble.java new file mode 100644 index 00000000000..a04646ba07f --- /dev/null +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherDoubleDouble.java @@ -0,0 +1,385 @@ +// DO NOT EDIT THIS CLASS, AUTOMATICALLY GENERATED BY io.deephaven.engine.table.impl.by.typed.TypedHasherFactory +// Copyright (c) 2016-2022 Deephaven Data Labs and Patent Pending +// +package io.deephaven.engine.table.impl.by.typed.incopenagg.gen; + +import static io.deephaven.util.compare.DoubleComparisons.eq; + +import io.deephaven.base.verify.Assert; +import io.deephaven.chunk.Chunk; +import io.deephaven.chunk.DoubleChunk; +import io.deephaven.chunk.WritableIntChunk; +import io.deephaven.chunk.attributes.Values; +import io.deephaven.chunk.util.hashing.DoubleChunkHasher; +import io.deephaven.engine.rowset.RowSequence; +import io.deephaven.engine.rowset.chunkattributes.RowKeys; +import io.deephaven.engine.table.ColumnSource; +import io.deephaven.engine.table.impl.by.IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableDoubleArraySource; +import io.deephaven.util.type.TypeUtils; +import java.lang.Double; +import java.lang.Object; +import java.lang.Override; +import java.util.Arrays; + +final class IncrementalAggOpenHasherDoubleDouble extends IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase { + private ImmutableDoubleArraySource mainKeySource0; + + private ImmutableDoubleArraySource alternateKeySource0; + + private ImmutableDoubleArraySource mainKeySource1; + + private ImmutableDoubleArraySource alternateKeySource1; + + public IncrementalAggOpenHasherDoubleDouble(ColumnSource[] tableKeySources, int tableSize, + double maximumLoadFactor, double targetLoadFactor) { + super(tableKeySources, tableSize, maximumLoadFactor); + this.mainKeySource0 = (ImmutableDoubleArraySource) super.mainKeySources[0]; + this.mainKeySource0.ensureCapacity(tableSize); + this.mainKeySource1 = (ImmutableDoubleArraySource) super.mainKeySources[1]; + this.mainKeySource1.ensureCapacity(tableSize); + } + + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + + private int alternateNextTableLocation(int tableLocation) { + return (tableLocation + 1) & (alternateTableSize - 1); + } + + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final DoubleChunk keyChunk0 = sourceKeyChunks[0].asDoubleChunk(); + final DoubleChunk keyChunk1 = sourceKeyChunks[1].asDoubleChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final double k0 = keyChunk0.get(chunkPosition); + final double k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void buildForUpdate(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk reincarnatedPositions) { + final DoubleChunk keyChunk0 = sourceKeyChunks[0].asDoubleChunk(); + final DoubleChunk keyChunk1 = sourceKeyChunks[1].asDoubleChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final double k0 = keyChunk0.get(chunkPosition); + final double k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void doRemoveProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk emptiedPositions) { + final DoubleChunk keyChunk0 = sourceKeyChunks[0].asDoubleChunk(); + final DoubleChunk keyChunk1 = sourceKeyChunks[1].asDoubleChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final double k0 = keyChunk0.get(chunkPosition); + final double k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + protected void doModifyProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final DoubleChunk keyChunk0 = sourceKeyChunks[0].asDoubleChunk(); + final DoubleChunk keyChunk1 = sourceKeyChunks[1].asDoubleChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final double k0 = keyChunk0.get(chunkPosition); + final double k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + private static int hash(double k0, double k1) { + int hash = DoubleChunkHasher.hashInitialSingle(k0); + hash = DoubleChunkHasher.hashUpdateSingle(hash, k1); + return hash; + } + + private boolean migrateOneLocation(int locationToMigrate) { + final int currentStateValue = alternateOutputPosition.getUnsafe(locationToMigrate); + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + return false; + } + final double k0 = alternateKeySource0.getUnsafe(locationToMigrate); + final double k1 = alternateKeySource1.getUnsafe(locationToMigrate); + final int hash = hash(k0, k1); + int destinationTableLocation = hashToTableLocation(hash); + while (mainOutputPosition.getUnsafe(destinationTableLocation) != EMPTY_OUTPUT_POSITION) { + destinationTableLocation = nextTableLocation(destinationTableLocation); + } + mainKeySource0.set(destinationTableLocation, k0); + mainKeySource1.set(destinationTableLocation, k1); + mainOutputPosition.set(destinationTableLocation, currentStateValue); + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + alternateOutputPosition.set(locationToMigrate, EMPTY_OUTPUT_POSITION); + return true; + } + + @Override + protected int rehashInternalPartial(int entriesToRehash) { + int rehashedEntries = 0; + while (rehashPointer > 0 && rehashedEntries < entriesToRehash) { + if (migrateOneLocation(--rehashPointer)) { + rehashedEntries++; + } + } + return rehashedEntries; + } + + @Override + protected void newAlternate() { + super.newAlternate(); + this.mainKeySource0 = (ImmutableDoubleArraySource)super.mainKeySources[0]; + this.alternateKeySource0 = (ImmutableDoubleArraySource)super.alternateKeySources[0]; + this.mainKeySource1 = (ImmutableDoubleArraySource)super.mainKeySources[1]; + this.alternateKeySource1 = (ImmutableDoubleArraySource)super.alternateKeySources[1]; + } + + @Override + protected void clearAlternate() { + super.clearAlternate(); + this.alternateKeySource0 = null; + this.alternateKeySource1 = null; + } + + @Override + protected void migrateFront() { + int location = 0; + while (migrateOneLocation(location++)); + } + + @Override + protected void rehashInternalFull(final int oldSize) { + final double[] destKeyArray0 = new double[tableSize]; + final double[] destKeyArray1 = new double[tableSize]; + final int[] destState = new int[tableSize]; + Arrays.fill(destState, EMPTY_OUTPUT_POSITION); + final double [] originalKeyArray0 = mainKeySource0.getArray(); + mainKeySource0.setArray(destKeyArray0); + final double [] originalKeyArray1 = mainKeySource1.getArray(); + mainKeySource1.setArray(destKeyArray1); + final int [] originalStateArray = mainOutputPosition.getArray(); + mainOutputPosition.setArray(destState); + for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + continue; + } + final double k0 = originalKeyArray0[sourceBucket]; + final double k1 = originalKeyArray1[sourceBucket]; + final int hash = hash(k0, k1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; + while (true) { + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + break; + } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); + } + } + } + + @Override + public int findPositionForKey(Object key) { + final Object [] ka = (Object[])key; + final double k0 = TypeUtils.unbox((Double)ka[0]); + final double k1 = TypeUtils.unbox((Double)ka[1]); + int hash = hash(k0, k1); + int tableLocation = hashToTableLocation(hash); + final int firstTableLocation = tableLocation; + while (true) { + final int positionValue = mainOutputPosition.getUnsafe(tableLocation); + if (positionValue == EMPTY_OUTPUT_POSITION) { + int alternateTableLocation = hashToTableLocationAlternate(hash); + if (alternateTableLocation >= rehashPointer) { + return -1; + } + final int firstAlternateTableLocation = alternateTableLocation; + while (true) { + final int alternatePositionValue = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (alternatePositionValue == EMPTY_OUTPUT_POSITION) { + return -1; + } + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + return alternatePositionValue; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + return positionValue; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherDoubleFloat.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherDoubleFloat.java new file mode 100644 index 00000000000..88ad4d9aa19 --- /dev/null +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherDoubleFloat.java @@ -0,0 +1,390 @@ +// DO NOT EDIT THIS CLASS, AUTOMATICALLY GENERATED BY io.deephaven.engine.table.impl.by.typed.TypedHasherFactory +// Copyright (c) 2016-2022 Deephaven Data Labs and Patent Pending +// +package io.deephaven.engine.table.impl.by.typed.incopenagg.gen; + +import static io.deephaven.util.compare.DoubleComparisons.eq; +import static io.deephaven.util.compare.FloatComparisons.eq; + +import io.deephaven.base.verify.Assert; +import io.deephaven.chunk.Chunk; +import io.deephaven.chunk.DoubleChunk; +import io.deephaven.chunk.FloatChunk; +import io.deephaven.chunk.WritableIntChunk; +import io.deephaven.chunk.attributes.Values; +import io.deephaven.chunk.util.hashing.DoubleChunkHasher; +import io.deephaven.chunk.util.hashing.FloatChunkHasher; +import io.deephaven.engine.rowset.RowSequence; +import io.deephaven.engine.rowset.chunkattributes.RowKeys; +import io.deephaven.engine.table.ColumnSource; +import io.deephaven.engine.table.impl.by.IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableDoubleArraySource; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableFloatArraySource; +import io.deephaven.util.type.TypeUtils; +import java.lang.Double; +import java.lang.Float; +import java.lang.Object; +import java.lang.Override; +import java.util.Arrays; + +final class IncrementalAggOpenHasherDoubleFloat extends IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase { + private ImmutableDoubleArraySource mainKeySource0; + + private ImmutableDoubleArraySource alternateKeySource0; + + private ImmutableFloatArraySource mainKeySource1; + + private ImmutableFloatArraySource alternateKeySource1; + + public IncrementalAggOpenHasherDoubleFloat(ColumnSource[] tableKeySources, int tableSize, + double maximumLoadFactor, double targetLoadFactor) { + super(tableKeySources, tableSize, maximumLoadFactor); + this.mainKeySource0 = (ImmutableDoubleArraySource) super.mainKeySources[0]; + this.mainKeySource0.ensureCapacity(tableSize); + this.mainKeySource1 = (ImmutableFloatArraySource) super.mainKeySources[1]; + this.mainKeySource1.ensureCapacity(tableSize); + } + + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + + private int alternateNextTableLocation(int tableLocation) { + return (tableLocation + 1) & (alternateTableSize - 1); + } + + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final DoubleChunk keyChunk0 = sourceKeyChunks[0].asDoubleChunk(); + final FloatChunk keyChunk1 = sourceKeyChunks[1].asFloatChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final double k0 = keyChunk0.get(chunkPosition); + final float k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void buildForUpdate(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk reincarnatedPositions) { + final DoubleChunk keyChunk0 = sourceKeyChunks[0].asDoubleChunk(); + final FloatChunk keyChunk1 = sourceKeyChunks[1].asFloatChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final double k0 = keyChunk0.get(chunkPosition); + final float k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void doRemoveProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk emptiedPositions) { + final DoubleChunk keyChunk0 = sourceKeyChunks[0].asDoubleChunk(); + final FloatChunk keyChunk1 = sourceKeyChunks[1].asFloatChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final double k0 = keyChunk0.get(chunkPosition); + final float k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + protected void doModifyProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final DoubleChunk keyChunk0 = sourceKeyChunks[0].asDoubleChunk(); + final FloatChunk keyChunk1 = sourceKeyChunks[1].asFloatChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final double k0 = keyChunk0.get(chunkPosition); + final float k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + private static int hash(double k0, float k1) { + int hash = DoubleChunkHasher.hashInitialSingle(k0); + hash = FloatChunkHasher.hashUpdateSingle(hash, k1); + return hash; + } + + private boolean migrateOneLocation(int locationToMigrate) { + final int currentStateValue = alternateOutputPosition.getUnsafe(locationToMigrate); + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + return false; + } + final double k0 = alternateKeySource0.getUnsafe(locationToMigrate); + final float k1 = alternateKeySource1.getUnsafe(locationToMigrate); + final int hash = hash(k0, k1); + int destinationTableLocation = hashToTableLocation(hash); + while (mainOutputPosition.getUnsafe(destinationTableLocation) != EMPTY_OUTPUT_POSITION) { + destinationTableLocation = nextTableLocation(destinationTableLocation); + } + mainKeySource0.set(destinationTableLocation, k0); + mainKeySource1.set(destinationTableLocation, k1); + mainOutputPosition.set(destinationTableLocation, currentStateValue); + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + alternateOutputPosition.set(locationToMigrate, EMPTY_OUTPUT_POSITION); + return true; + } + + @Override + protected int rehashInternalPartial(int entriesToRehash) { + int rehashedEntries = 0; + while (rehashPointer > 0 && rehashedEntries < entriesToRehash) { + if (migrateOneLocation(--rehashPointer)) { + rehashedEntries++; + } + } + return rehashedEntries; + } + + @Override + protected void newAlternate() { + super.newAlternate(); + this.mainKeySource0 = (ImmutableDoubleArraySource)super.mainKeySources[0]; + this.alternateKeySource0 = (ImmutableDoubleArraySource)super.alternateKeySources[0]; + this.mainKeySource1 = (ImmutableFloatArraySource)super.mainKeySources[1]; + this.alternateKeySource1 = (ImmutableFloatArraySource)super.alternateKeySources[1]; + } + + @Override + protected void clearAlternate() { + super.clearAlternate(); + this.alternateKeySource0 = null; + this.alternateKeySource1 = null; + } + + @Override + protected void migrateFront() { + int location = 0; + while (migrateOneLocation(location++)); + } + + @Override + protected void rehashInternalFull(final int oldSize) { + final double[] destKeyArray0 = new double[tableSize]; + final float[] destKeyArray1 = new float[tableSize]; + final int[] destState = new int[tableSize]; + Arrays.fill(destState, EMPTY_OUTPUT_POSITION); + final double [] originalKeyArray0 = mainKeySource0.getArray(); + mainKeySource0.setArray(destKeyArray0); + final float [] originalKeyArray1 = mainKeySource1.getArray(); + mainKeySource1.setArray(destKeyArray1); + final int [] originalStateArray = mainOutputPosition.getArray(); + mainOutputPosition.setArray(destState); + for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + continue; + } + final double k0 = originalKeyArray0[sourceBucket]; + final float k1 = originalKeyArray1[sourceBucket]; + final int hash = hash(k0, k1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; + while (true) { + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + break; + } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); + } + } + } + + @Override + public int findPositionForKey(Object key) { + final Object [] ka = (Object[])key; + final double k0 = TypeUtils.unbox((Double)ka[0]); + final float k1 = TypeUtils.unbox((Float)ka[1]); + int hash = hash(k0, k1); + int tableLocation = hashToTableLocation(hash); + final int firstTableLocation = tableLocation; + while (true) { + final int positionValue = mainOutputPosition.getUnsafe(tableLocation); + if (positionValue == EMPTY_OUTPUT_POSITION) { + int alternateTableLocation = hashToTableLocationAlternate(hash); + if (alternateTableLocation >= rehashPointer) { + return -1; + } + final int firstAlternateTableLocation = alternateTableLocation; + while (true) { + final int alternatePositionValue = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (alternatePositionValue == EMPTY_OUTPUT_POSITION) { + return -1; + } + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + return alternatePositionValue; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + return positionValue; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherDoubleInt.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherDoubleInt.java new file mode 100644 index 00000000000..11b3a80d78a --- /dev/null +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherDoubleInt.java @@ -0,0 +1,390 @@ +// DO NOT EDIT THIS CLASS, AUTOMATICALLY GENERATED BY io.deephaven.engine.table.impl.by.typed.TypedHasherFactory +// Copyright (c) 2016-2022 Deephaven Data Labs and Patent Pending +// +package io.deephaven.engine.table.impl.by.typed.incopenagg.gen; + +import static io.deephaven.util.compare.DoubleComparisons.eq; +import static io.deephaven.util.compare.IntComparisons.eq; + +import io.deephaven.base.verify.Assert; +import io.deephaven.chunk.Chunk; +import io.deephaven.chunk.DoubleChunk; +import io.deephaven.chunk.IntChunk; +import io.deephaven.chunk.WritableIntChunk; +import io.deephaven.chunk.attributes.Values; +import io.deephaven.chunk.util.hashing.DoubleChunkHasher; +import io.deephaven.chunk.util.hashing.IntChunkHasher; +import io.deephaven.engine.rowset.RowSequence; +import io.deephaven.engine.rowset.chunkattributes.RowKeys; +import io.deephaven.engine.table.ColumnSource; +import io.deephaven.engine.table.impl.by.IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableDoubleArraySource; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableIntArraySource; +import io.deephaven.util.type.TypeUtils; +import java.lang.Double; +import java.lang.Integer; +import java.lang.Object; +import java.lang.Override; +import java.util.Arrays; + +final class IncrementalAggOpenHasherDoubleInt extends IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase { + private ImmutableDoubleArraySource mainKeySource0; + + private ImmutableDoubleArraySource alternateKeySource0; + + private ImmutableIntArraySource mainKeySource1; + + private ImmutableIntArraySource alternateKeySource1; + + public IncrementalAggOpenHasherDoubleInt(ColumnSource[] tableKeySources, int tableSize, + double maximumLoadFactor, double targetLoadFactor) { + super(tableKeySources, tableSize, maximumLoadFactor); + this.mainKeySource0 = (ImmutableDoubleArraySource) super.mainKeySources[0]; + this.mainKeySource0.ensureCapacity(tableSize); + this.mainKeySource1 = (ImmutableIntArraySource) super.mainKeySources[1]; + this.mainKeySource1.ensureCapacity(tableSize); + } + + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + + private int alternateNextTableLocation(int tableLocation) { + return (tableLocation + 1) & (alternateTableSize - 1); + } + + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final DoubleChunk keyChunk0 = sourceKeyChunks[0].asDoubleChunk(); + final IntChunk keyChunk1 = sourceKeyChunks[1].asIntChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final double k0 = keyChunk0.get(chunkPosition); + final int k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void buildForUpdate(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk reincarnatedPositions) { + final DoubleChunk keyChunk0 = sourceKeyChunks[0].asDoubleChunk(); + final IntChunk keyChunk1 = sourceKeyChunks[1].asIntChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final double k0 = keyChunk0.get(chunkPosition); + final int k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void doRemoveProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk emptiedPositions) { + final DoubleChunk keyChunk0 = sourceKeyChunks[0].asDoubleChunk(); + final IntChunk keyChunk1 = sourceKeyChunks[1].asIntChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final double k0 = keyChunk0.get(chunkPosition); + final int k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + protected void doModifyProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final DoubleChunk keyChunk0 = sourceKeyChunks[0].asDoubleChunk(); + final IntChunk keyChunk1 = sourceKeyChunks[1].asIntChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final double k0 = keyChunk0.get(chunkPosition); + final int k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + private static int hash(double k0, int k1) { + int hash = DoubleChunkHasher.hashInitialSingle(k0); + hash = IntChunkHasher.hashUpdateSingle(hash, k1); + return hash; + } + + private boolean migrateOneLocation(int locationToMigrate) { + final int currentStateValue = alternateOutputPosition.getUnsafe(locationToMigrate); + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + return false; + } + final double k0 = alternateKeySource0.getUnsafe(locationToMigrate); + final int k1 = alternateKeySource1.getUnsafe(locationToMigrate); + final int hash = hash(k0, k1); + int destinationTableLocation = hashToTableLocation(hash); + while (mainOutputPosition.getUnsafe(destinationTableLocation) != EMPTY_OUTPUT_POSITION) { + destinationTableLocation = nextTableLocation(destinationTableLocation); + } + mainKeySource0.set(destinationTableLocation, k0); + mainKeySource1.set(destinationTableLocation, k1); + mainOutputPosition.set(destinationTableLocation, currentStateValue); + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + alternateOutputPosition.set(locationToMigrate, EMPTY_OUTPUT_POSITION); + return true; + } + + @Override + protected int rehashInternalPartial(int entriesToRehash) { + int rehashedEntries = 0; + while (rehashPointer > 0 && rehashedEntries < entriesToRehash) { + if (migrateOneLocation(--rehashPointer)) { + rehashedEntries++; + } + } + return rehashedEntries; + } + + @Override + protected void newAlternate() { + super.newAlternate(); + this.mainKeySource0 = (ImmutableDoubleArraySource)super.mainKeySources[0]; + this.alternateKeySource0 = (ImmutableDoubleArraySource)super.alternateKeySources[0]; + this.mainKeySource1 = (ImmutableIntArraySource)super.mainKeySources[1]; + this.alternateKeySource1 = (ImmutableIntArraySource)super.alternateKeySources[1]; + } + + @Override + protected void clearAlternate() { + super.clearAlternate(); + this.alternateKeySource0 = null; + this.alternateKeySource1 = null; + } + + @Override + protected void migrateFront() { + int location = 0; + while (migrateOneLocation(location++)); + } + + @Override + protected void rehashInternalFull(final int oldSize) { + final double[] destKeyArray0 = new double[tableSize]; + final int[] destKeyArray1 = new int[tableSize]; + final int[] destState = new int[tableSize]; + Arrays.fill(destState, EMPTY_OUTPUT_POSITION); + final double [] originalKeyArray0 = mainKeySource0.getArray(); + mainKeySource0.setArray(destKeyArray0); + final int [] originalKeyArray1 = mainKeySource1.getArray(); + mainKeySource1.setArray(destKeyArray1); + final int [] originalStateArray = mainOutputPosition.getArray(); + mainOutputPosition.setArray(destState); + for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + continue; + } + final double k0 = originalKeyArray0[sourceBucket]; + final int k1 = originalKeyArray1[sourceBucket]; + final int hash = hash(k0, k1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; + while (true) { + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + break; + } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); + } + } + } + + @Override + public int findPositionForKey(Object key) { + final Object [] ka = (Object[])key; + final double k0 = TypeUtils.unbox((Double)ka[0]); + final int k1 = TypeUtils.unbox((Integer)ka[1]); + int hash = hash(k0, k1); + int tableLocation = hashToTableLocation(hash); + final int firstTableLocation = tableLocation; + while (true) { + final int positionValue = mainOutputPosition.getUnsafe(tableLocation); + if (positionValue == EMPTY_OUTPUT_POSITION) { + int alternateTableLocation = hashToTableLocationAlternate(hash); + if (alternateTableLocation >= rehashPointer) { + return -1; + } + final int firstAlternateTableLocation = alternateTableLocation; + while (true) { + final int alternatePositionValue = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (alternatePositionValue == EMPTY_OUTPUT_POSITION) { + return -1; + } + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + return alternatePositionValue; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + return positionValue; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherDoubleLong.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherDoubleLong.java new file mode 100644 index 00000000000..b2abf477cf1 --- /dev/null +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherDoubleLong.java @@ -0,0 +1,390 @@ +// DO NOT EDIT THIS CLASS, AUTOMATICALLY GENERATED BY io.deephaven.engine.table.impl.by.typed.TypedHasherFactory +// Copyright (c) 2016-2022 Deephaven Data Labs and Patent Pending +// +package io.deephaven.engine.table.impl.by.typed.incopenagg.gen; + +import static io.deephaven.util.compare.DoubleComparisons.eq; +import static io.deephaven.util.compare.LongComparisons.eq; + +import io.deephaven.base.verify.Assert; +import io.deephaven.chunk.Chunk; +import io.deephaven.chunk.DoubleChunk; +import io.deephaven.chunk.LongChunk; +import io.deephaven.chunk.WritableIntChunk; +import io.deephaven.chunk.attributes.Values; +import io.deephaven.chunk.util.hashing.DoubleChunkHasher; +import io.deephaven.chunk.util.hashing.LongChunkHasher; +import io.deephaven.engine.rowset.RowSequence; +import io.deephaven.engine.rowset.chunkattributes.RowKeys; +import io.deephaven.engine.table.ColumnSource; +import io.deephaven.engine.table.impl.by.IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableDoubleArraySource; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableLongArraySource; +import io.deephaven.util.type.TypeUtils; +import java.lang.Double; +import java.lang.Long; +import java.lang.Object; +import java.lang.Override; +import java.util.Arrays; + +final class IncrementalAggOpenHasherDoubleLong extends IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase { + private ImmutableDoubleArraySource mainKeySource0; + + private ImmutableDoubleArraySource alternateKeySource0; + + private ImmutableLongArraySource mainKeySource1; + + private ImmutableLongArraySource alternateKeySource1; + + public IncrementalAggOpenHasherDoubleLong(ColumnSource[] tableKeySources, int tableSize, + double maximumLoadFactor, double targetLoadFactor) { + super(tableKeySources, tableSize, maximumLoadFactor); + this.mainKeySource0 = (ImmutableDoubleArraySource) super.mainKeySources[0]; + this.mainKeySource0.ensureCapacity(tableSize); + this.mainKeySource1 = (ImmutableLongArraySource) super.mainKeySources[1]; + this.mainKeySource1.ensureCapacity(tableSize); + } + + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + + private int alternateNextTableLocation(int tableLocation) { + return (tableLocation + 1) & (alternateTableSize - 1); + } + + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final DoubleChunk keyChunk0 = sourceKeyChunks[0].asDoubleChunk(); + final LongChunk keyChunk1 = sourceKeyChunks[1].asLongChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final double k0 = keyChunk0.get(chunkPosition); + final long k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void buildForUpdate(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk reincarnatedPositions) { + final DoubleChunk keyChunk0 = sourceKeyChunks[0].asDoubleChunk(); + final LongChunk keyChunk1 = sourceKeyChunks[1].asLongChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final double k0 = keyChunk0.get(chunkPosition); + final long k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void doRemoveProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk emptiedPositions) { + final DoubleChunk keyChunk0 = sourceKeyChunks[0].asDoubleChunk(); + final LongChunk keyChunk1 = sourceKeyChunks[1].asLongChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final double k0 = keyChunk0.get(chunkPosition); + final long k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + protected void doModifyProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final DoubleChunk keyChunk0 = sourceKeyChunks[0].asDoubleChunk(); + final LongChunk keyChunk1 = sourceKeyChunks[1].asLongChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final double k0 = keyChunk0.get(chunkPosition); + final long k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + private static int hash(double k0, long k1) { + int hash = DoubleChunkHasher.hashInitialSingle(k0); + hash = LongChunkHasher.hashUpdateSingle(hash, k1); + return hash; + } + + private boolean migrateOneLocation(int locationToMigrate) { + final int currentStateValue = alternateOutputPosition.getUnsafe(locationToMigrate); + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + return false; + } + final double k0 = alternateKeySource0.getUnsafe(locationToMigrate); + final long k1 = alternateKeySource1.getUnsafe(locationToMigrate); + final int hash = hash(k0, k1); + int destinationTableLocation = hashToTableLocation(hash); + while (mainOutputPosition.getUnsafe(destinationTableLocation) != EMPTY_OUTPUT_POSITION) { + destinationTableLocation = nextTableLocation(destinationTableLocation); + } + mainKeySource0.set(destinationTableLocation, k0); + mainKeySource1.set(destinationTableLocation, k1); + mainOutputPosition.set(destinationTableLocation, currentStateValue); + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + alternateOutputPosition.set(locationToMigrate, EMPTY_OUTPUT_POSITION); + return true; + } + + @Override + protected int rehashInternalPartial(int entriesToRehash) { + int rehashedEntries = 0; + while (rehashPointer > 0 && rehashedEntries < entriesToRehash) { + if (migrateOneLocation(--rehashPointer)) { + rehashedEntries++; + } + } + return rehashedEntries; + } + + @Override + protected void newAlternate() { + super.newAlternate(); + this.mainKeySource0 = (ImmutableDoubleArraySource)super.mainKeySources[0]; + this.alternateKeySource0 = (ImmutableDoubleArraySource)super.alternateKeySources[0]; + this.mainKeySource1 = (ImmutableLongArraySource)super.mainKeySources[1]; + this.alternateKeySource1 = (ImmutableLongArraySource)super.alternateKeySources[1]; + } + + @Override + protected void clearAlternate() { + super.clearAlternate(); + this.alternateKeySource0 = null; + this.alternateKeySource1 = null; + } + + @Override + protected void migrateFront() { + int location = 0; + while (migrateOneLocation(location++)); + } + + @Override + protected void rehashInternalFull(final int oldSize) { + final double[] destKeyArray0 = new double[tableSize]; + final long[] destKeyArray1 = new long[tableSize]; + final int[] destState = new int[tableSize]; + Arrays.fill(destState, EMPTY_OUTPUT_POSITION); + final double [] originalKeyArray0 = mainKeySource0.getArray(); + mainKeySource0.setArray(destKeyArray0); + final long [] originalKeyArray1 = mainKeySource1.getArray(); + mainKeySource1.setArray(destKeyArray1); + final int [] originalStateArray = mainOutputPosition.getArray(); + mainOutputPosition.setArray(destState); + for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + continue; + } + final double k0 = originalKeyArray0[sourceBucket]; + final long k1 = originalKeyArray1[sourceBucket]; + final int hash = hash(k0, k1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; + while (true) { + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + break; + } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); + } + } + } + + @Override + public int findPositionForKey(Object key) { + final Object [] ka = (Object[])key; + final double k0 = TypeUtils.unbox((Double)ka[0]); + final long k1 = TypeUtils.unbox((Long)ka[1]); + int hash = hash(k0, k1); + int tableLocation = hashToTableLocation(hash); + final int firstTableLocation = tableLocation; + while (true) { + final int positionValue = mainOutputPosition.getUnsafe(tableLocation); + if (positionValue == EMPTY_OUTPUT_POSITION) { + int alternateTableLocation = hashToTableLocationAlternate(hash); + if (alternateTableLocation >= rehashPointer) { + return -1; + } + final int firstAlternateTableLocation = alternateTableLocation; + while (true) { + final int alternatePositionValue = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (alternatePositionValue == EMPTY_OUTPUT_POSITION) { + return -1; + } + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + return alternatePositionValue; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + return positionValue; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherDoubleObject.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherDoubleObject.java new file mode 100644 index 00000000000..3c5832a7674 --- /dev/null +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherDoubleObject.java @@ -0,0 +1,390 @@ +// DO NOT EDIT THIS CLASS, AUTOMATICALLY GENERATED BY io.deephaven.engine.table.impl.by.typed.TypedHasherFactory +// Copyright (c) 2016-2022 Deephaven Data Labs and Patent Pending +// +package io.deephaven.engine.table.impl.by.typed.incopenagg.gen; + +import static io.deephaven.util.compare.DoubleComparisons.eq; +import static io.deephaven.util.compare.ObjectComparisons.eq; + +import io.deephaven.base.verify.Assert; +import io.deephaven.chunk.Chunk; +import io.deephaven.chunk.DoubleChunk; +import io.deephaven.chunk.ObjectChunk; +import io.deephaven.chunk.WritableIntChunk; +import io.deephaven.chunk.attributes.Values; +import io.deephaven.chunk.util.hashing.DoubleChunkHasher; +import io.deephaven.chunk.util.hashing.ObjectChunkHasher; +import io.deephaven.engine.rowset.RowSequence; +import io.deephaven.engine.rowset.chunkattributes.RowKeys; +import io.deephaven.engine.table.ColumnSource; +import io.deephaven.engine.table.impl.by.IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableDoubleArraySource; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableObjectArraySource; +import io.deephaven.util.type.TypeUtils; +import java.lang.Double; +import java.lang.Object; +import java.lang.Override; +import java.util.Arrays; + +final class IncrementalAggOpenHasherDoubleObject extends IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase { + private ImmutableDoubleArraySource mainKeySource0; + + private ImmutableDoubleArraySource alternateKeySource0; + + private ImmutableObjectArraySource mainKeySource1; + + private ImmutableObjectArraySource alternateKeySource1; + + public IncrementalAggOpenHasherDoubleObject(ColumnSource[] tableKeySources, int tableSize, + double maximumLoadFactor, double targetLoadFactor) { + super(tableKeySources, tableSize, maximumLoadFactor); + this.mainKeySource0 = (ImmutableDoubleArraySource) super.mainKeySources[0]; + this.mainKeySource0.ensureCapacity(tableSize); + this.mainKeySource1 = (ImmutableObjectArraySource) super.mainKeySources[1]; + this.mainKeySource1.ensureCapacity(tableSize); + } + + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + + private int alternateNextTableLocation(int tableLocation) { + return (tableLocation + 1) & (alternateTableSize - 1); + } + + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final DoubleChunk keyChunk0 = sourceKeyChunks[0].asDoubleChunk(); + final ObjectChunk keyChunk1 = sourceKeyChunks[1].asObjectChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final double k0 = keyChunk0.get(chunkPosition); + final Object k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void buildForUpdate(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk reincarnatedPositions) { + final DoubleChunk keyChunk0 = sourceKeyChunks[0].asDoubleChunk(); + final ObjectChunk keyChunk1 = sourceKeyChunks[1].asObjectChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final double k0 = keyChunk0.get(chunkPosition); + final Object k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void doRemoveProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk emptiedPositions) { + final DoubleChunk keyChunk0 = sourceKeyChunks[0].asDoubleChunk(); + final ObjectChunk keyChunk1 = sourceKeyChunks[1].asObjectChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final double k0 = keyChunk0.get(chunkPosition); + final Object k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + protected void doModifyProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final DoubleChunk keyChunk0 = sourceKeyChunks[0].asDoubleChunk(); + final ObjectChunk keyChunk1 = sourceKeyChunks[1].asObjectChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final double k0 = keyChunk0.get(chunkPosition); + final Object k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + private static int hash(double k0, Object k1) { + int hash = DoubleChunkHasher.hashInitialSingle(k0); + hash = ObjectChunkHasher.hashUpdateSingle(hash, k1); + return hash; + } + + private boolean migrateOneLocation(int locationToMigrate) { + final int currentStateValue = alternateOutputPosition.getUnsafe(locationToMigrate); + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + return false; + } + final double k0 = alternateKeySource0.getUnsafe(locationToMigrate); + final Object k1 = alternateKeySource1.getUnsafe(locationToMigrate); + final int hash = hash(k0, k1); + int destinationTableLocation = hashToTableLocation(hash); + while (mainOutputPosition.getUnsafe(destinationTableLocation) != EMPTY_OUTPUT_POSITION) { + destinationTableLocation = nextTableLocation(destinationTableLocation); + } + mainKeySource0.set(destinationTableLocation, k0); + mainKeySource1.set(destinationTableLocation, k1); + alternateKeySource1.set(locationToMigrate, null); + mainOutputPosition.set(destinationTableLocation, currentStateValue); + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + alternateOutputPosition.set(locationToMigrate, EMPTY_OUTPUT_POSITION); + return true; + } + + @Override + protected int rehashInternalPartial(int entriesToRehash) { + int rehashedEntries = 0; + while (rehashPointer > 0 && rehashedEntries < entriesToRehash) { + if (migrateOneLocation(--rehashPointer)) { + rehashedEntries++; + } + } + return rehashedEntries; + } + + @Override + protected void newAlternate() { + super.newAlternate(); + this.mainKeySource0 = (ImmutableDoubleArraySource)super.mainKeySources[0]; + this.alternateKeySource0 = (ImmutableDoubleArraySource)super.alternateKeySources[0]; + this.mainKeySource1 = (ImmutableObjectArraySource)super.mainKeySources[1]; + this.alternateKeySource1 = (ImmutableObjectArraySource)super.alternateKeySources[1]; + } + + @Override + protected void clearAlternate() { + super.clearAlternate(); + this.alternateKeySource0 = null; + this.alternateKeySource1 = null; + } + + @Override + protected void migrateFront() { + int location = 0; + while (migrateOneLocation(location++)); + } + + @Override + protected void rehashInternalFull(final int oldSize) { + final double[] destKeyArray0 = new double[tableSize]; + final Object[] destKeyArray1 = new Object[tableSize]; + final int[] destState = new int[tableSize]; + Arrays.fill(destState, EMPTY_OUTPUT_POSITION); + final double [] originalKeyArray0 = mainKeySource0.getArray(); + mainKeySource0.setArray(destKeyArray0); + final Object [] originalKeyArray1 = mainKeySource1.getArray(); + mainKeySource1.setArray(destKeyArray1); + final int [] originalStateArray = mainOutputPosition.getArray(); + mainOutputPosition.setArray(destState); + for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + continue; + } + final double k0 = originalKeyArray0[sourceBucket]; + final Object k1 = originalKeyArray1[sourceBucket]; + final int hash = hash(k0, k1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; + while (true) { + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + break; + } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); + } + } + } + + @Override + public int findPositionForKey(Object key) { + final Object [] ka = (Object[])key; + final double k0 = TypeUtils.unbox((Double)ka[0]); + final Object k1 = ka[1]; + int hash = hash(k0, k1); + int tableLocation = hashToTableLocation(hash); + final int firstTableLocation = tableLocation; + while (true) { + final int positionValue = mainOutputPosition.getUnsafe(tableLocation); + if (positionValue == EMPTY_OUTPUT_POSITION) { + int alternateTableLocation = hashToTableLocationAlternate(hash); + if (alternateTableLocation >= rehashPointer) { + return -1; + } + final int firstAlternateTableLocation = alternateTableLocation; + while (true) { + final int alternatePositionValue = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (alternatePositionValue == EMPTY_OUTPUT_POSITION) { + return -1; + } + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + return alternatePositionValue; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + return positionValue; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherDoubleShort.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherDoubleShort.java new file mode 100644 index 00000000000..8acc647d1c3 --- /dev/null +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherDoubleShort.java @@ -0,0 +1,390 @@ +// DO NOT EDIT THIS CLASS, AUTOMATICALLY GENERATED BY io.deephaven.engine.table.impl.by.typed.TypedHasherFactory +// Copyright (c) 2016-2022 Deephaven Data Labs and Patent Pending +// +package io.deephaven.engine.table.impl.by.typed.incopenagg.gen; + +import static io.deephaven.util.compare.DoubleComparisons.eq; +import static io.deephaven.util.compare.ShortComparisons.eq; + +import io.deephaven.base.verify.Assert; +import io.deephaven.chunk.Chunk; +import io.deephaven.chunk.DoubleChunk; +import io.deephaven.chunk.ShortChunk; +import io.deephaven.chunk.WritableIntChunk; +import io.deephaven.chunk.attributes.Values; +import io.deephaven.chunk.util.hashing.DoubleChunkHasher; +import io.deephaven.chunk.util.hashing.ShortChunkHasher; +import io.deephaven.engine.rowset.RowSequence; +import io.deephaven.engine.rowset.chunkattributes.RowKeys; +import io.deephaven.engine.table.ColumnSource; +import io.deephaven.engine.table.impl.by.IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableDoubleArraySource; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableShortArraySource; +import io.deephaven.util.type.TypeUtils; +import java.lang.Double; +import java.lang.Object; +import java.lang.Override; +import java.lang.Short; +import java.util.Arrays; + +final class IncrementalAggOpenHasherDoubleShort extends IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase { + private ImmutableDoubleArraySource mainKeySource0; + + private ImmutableDoubleArraySource alternateKeySource0; + + private ImmutableShortArraySource mainKeySource1; + + private ImmutableShortArraySource alternateKeySource1; + + public IncrementalAggOpenHasherDoubleShort(ColumnSource[] tableKeySources, int tableSize, + double maximumLoadFactor, double targetLoadFactor) { + super(tableKeySources, tableSize, maximumLoadFactor); + this.mainKeySource0 = (ImmutableDoubleArraySource) super.mainKeySources[0]; + this.mainKeySource0.ensureCapacity(tableSize); + this.mainKeySource1 = (ImmutableShortArraySource) super.mainKeySources[1]; + this.mainKeySource1.ensureCapacity(tableSize); + } + + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + + private int alternateNextTableLocation(int tableLocation) { + return (tableLocation + 1) & (alternateTableSize - 1); + } + + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final DoubleChunk keyChunk0 = sourceKeyChunks[0].asDoubleChunk(); + final ShortChunk keyChunk1 = sourceKeyChunks[1].asShortChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final double k0 = keyChunk0.get(chunkPosition); + final short k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void buildForUpdate(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk reincarnatedPositions) { + final DoubleChunk keyChunk0 = sourceKeyChunks[0].asDoubleChunk(); + final ShortChunk keyChunk1 = sourceKeyChunks[1].asShortChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final double k0 = keyChunk0.get(chunkPosition); + final short k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void doRemoveProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk emptiedPositions) { + final DoubleChunk keyChunk0 = sourceKeyChunks[0].asDoubleChunk(); + final ShortChunk keyChunk1 = sourceKeyChunks[1].asShortChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final double k0 = keyChunk0.get(chunkPosition); + final short k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + protected void doModifyProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final DoubleChunk keyChunk0 = sourceKeyChunks[0].asDoubleChunk(); + final ShortChunk keyChunk1 = sourceKeyChunks[1].asShortChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final double k0 = keyChunk0.get(chunkPosition); + final short k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + private static int hash(double k0, short k1) { + int hash = DoubleChunkHasher.hashInitialSingle(k0); + hash = ShortChunkHasher.hashUpdateSingle(hash, k1); + return hash; + } + + private boolean migrateOneLocation(int locationToMigrate) { + final int currentStateValue = alternateOutputPosition.getUnsafe(locationToMigrate); + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + return false; + } + final double k0 = alternateKeySource0.getUnsafe(locationToMigrate); + final short k1 = alternateKeySource1.getUnsafe(locationToMigrate); + final int hash = hash(k0, k1); + int destinationTableLocation = hashToTableLocation(hash); + while (mainOutputPosition.getUnsafe(destinationTableLocation) != EMPTY_OUTPUT_POSITION) { + destinationTableLocation = nextTableLocation(destinationTableLocation); + } + mainKeySource0.set(destinationTableLocation, k0); + mainKeySource1.set(destinationTableLocation, k1); + mainOutputPosition.set(destinationTableLocation, currentStateValue); + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + alternateOutputPosition.set(locationToMigrate, EMPTY_OUTPUT_POSITION); + return true; + } + + @Override + protected int rehashInternalPartial(int entriesToRehash) { + int rehashedEntries = 0; + while (rehashPointer > 0 && rehashedEntries < entriesToRehash) { + if (migrateOneLocation(--rehashPointer)) { + rehashedEntries++; + } + } + return rehashedEntries; + } + + @Override + protected void newAlternate() { + super.newAlternate(); + this.mainKeySource0 = (ImmutableDoubleArraySource)super.mainKeySources[0]; + this.alternateKeySource0 = (ImmutableDoubleArraySource)super.alternateKeySources[0]; + this.mainKeySource1 = (ImmutableShortArraySource)super.mainKeySources[1]; + this.alternateKeySource1 = (ImmutableShortArraySource)super.alternateKeySources[1]; + } + + @Override + protected void clearAlternate() { + super.clearAlternate(); + this.alternateKeySource0 = null; + this.alternateKeySource1 = null; + } + + @Override + protected void migrateFront() { + int location = 0; + while (migrateOneLocation(location++)); + } + + @Override + protected void rehashInternalFull(final int oldSize) { + final double[] destKeyArray0 = new double[tableSize]; + final short[] destKeyArray1 = new short[tableSize]; + final int[] destState = new int[tableSize]; + Arrays.fill(destState, EMPTY_OUTPUT_POSITION); + final double [] originalKeyArray0 = mainKeySource0.getArray(); + mainKeySource0.setArray(destKeyArray0); + final short [] originalKeyArray1 = mainKeySource1.getArray(); + mainKeySource1.setArray(destKeyArray1); + final int [] originalStateArray = mainOutputPosition.getArray(); + mainOutputPosition.setArray(destState); + for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + continue; + } + final double k0 = originalKeyArray0[sourceBucket]; + final short k1 = originalKeyArray1[sourceBucket]; + final int hash = hash(k0, k1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; + while (true) { + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + break; + } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); + } + } + } + + @Override + public int findPositionForKey(Object key) { + final Object [] ka = (Object[])key; + final double k0 = TypeUtils.unbox((Double)ka[0]); + final short k1 = TypeUtils.unbox((Short)ka[1]); + int hash = hash(k0, k1); + int tableLocation = hashToTableLocation(hash); + final int firstTableLocation = tableLocation; + while (true) { + final int positionValue = mainOutputPosition.getUnsafe(tableLocation); + if (positionValue == EMPTY_OUTPUT_POSITION) { + int alternateTableLocation = hashToTableLocationAlternate(hash); + if (alternateTableLocation >= rehashPointer) { + return -1; + } + final int firstAlternateTableLocation = alternateTableLocation; + while (true) { + final int alternatePositionValue = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (alternatePositionValue == EMPTY_OUTPUT_POSITION) { + return -1; + } + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + return alternatePositionValue; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + return positionValue; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherFloat.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherFloat.java new file mode 100644 index 00000000000..5f61903d12e --- /dev/null +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherFloat.java @@ -0,0 +1,356 @@ +// DO NOT EDIT THIS CLASS, AUTOMATICALLY GENERATED BY io.deephaven.engine.table.impl.by.typed.TypedHasherFactory +// Copyright (c) 2016-2022 Deephaven Data Labs and Patent Pending +// +package io.deephaven.engine.table.impl.by.typed.incopenagg.gen; + +import static io.deephaven.util.compare.FloatComparisons.eq; + +import io.deephaven.base.verify.Assert; +import io.deephaven.chunk.Chunk; +import io.deephaven.chunk.FloatChunk; +import io.deephaven.chunk.WritableIntChunk; +import io.deephaven.chunk.attributes.Values; +import io.deephaven.chunk.util.hashing.FloatChunkHasher; +import io.deephaven.engine.rowset.RowSequence; +import io.deephaven.engine.rowset.chunkattributes.RowKeys; +import io.deephaven.engine.table.ColumnSource; +import io.deephaven.engine.table.impl.by.IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableFloatArraySource; +import io.deephaven.util.type.TypeUtils; +import java.lang.Float; +import java.lang.Object; +import java.lang.Override; +import java.util.Arrays; + +final class IncrementalAggOpenHasherFloat extends IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase { + private ImmutableFloatArraySource mainKeySource0; + + private ImmutableFloatArraySource alternateKeySource0; + + public IncrementalAggOpenHasherFloat(ColumnSource[] tableKeySources, int tableSize, + double maximumLoadFactor, double targetLoadFactor) { + super(tableKeySources, tableSize, maximumLoadFactor); + this.mainKeySource0 = (ImmutableFloatArraySource) super.mainKeySources[0]; + this.mainKeySource0.ensureCapacity(tableSize); + } + + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + + private int alternateNextTableLocation(int tableLocation) { + return (tableLocation + 1) & (alternateTableSize - 1); + } + + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final FloatChunk keyChunk0 = sourceKeyChunks[0].asFloatChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final float k0 = keyChunk0.get(chunkPosition); + final int hash = hash(k0); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void buildForUpdate(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk reincarnatedPositions) { + final FloatChunk keyChunk0 = sourceKeyChunks[0].asFloatChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final float k0 = keyChunk0.get(chunkPosition); + final int hash = hash(k0); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void doRemoveProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk emptiedPositions) { + final FloatChunk keyChunk0 = sourceKeyChunks[0].asFloatChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final float k0 = keyChunk0.get(chunkPosition); + final int hash = hash(k0); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + protected void doModifyProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final FloatChunk keyChunk0 = sourceKeyChunks[0].asFloatChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final float k0 = keyChunk0.get(chunkPosition); + final int hash = hash(k0); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0)) { + outputPositions.set(chunkPosition, outputPosition); + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0)) { + outputPositions.set(chunkPosition, outputPosition); + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + private static int hash(float k0) { + int hash = FloatChunkHasher.hashInitialSingle(k0); + return hash; + } + + private boolean migrateOneLocation(int locationToMigrate) { + final int currentStateValue = alternateOutputPosition.getUnsafe(locationToMigrate); + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + return false; + } + final float k0 = alternateKeySource0.getUnsafe(locationToMigrate); + final int hash = hash(k0); + int destinationTableLocation = hashToTableLocation(hash); + while (mainOutputPosition.getUnsafe(destinationTableLocation) != EMPTY_OUTPUT_POSITION) { + destinationTableLocation = nextTableLocation(destinationTableLocation); + } + mainKeySource0.set(destinationTableLocation, k0); + mainOutputPosition.set(destinationTableLocation, currentStateValue); + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + alternateOutputPosition.set(locationToMigrate, EMPTY_OUTPUT_POSITION); + return true; + } + + @Override + protected int rehashInternalPartial(int entriesToRehash) { + int rehashedEntries = 0; + while (rehashPointer > 0 && rehashedEntries < entriesToRehash) { + if (migrateOneLocation(--rehashPointer)) { + rehashedEntries++; + } + } + return rehashedEntries; + } + + @Override + protected void newAlternate() { + super.newAlternate(); + this.mainKeySource0 = (ImmutableFloatArraySource)super.mainKeySources[0]; + this.alternateKeySource0 = (ImmutableFloatArraySource)super.alternateKeySources[0]; + } + + @Override + protected void clearAlternate() { + super.clearAlternate(); + this.alternateKeySource0 = null; + } + + @Override + protected void migrateFront() { + int location = 0; + while (migrateOneLocation(location++)); + } + + @Override + protected void rehashInternalFull(final int oldSize) { + final float[] destKeyArray0 = new float[tableSize]; + final int[] destState = new int[tableSize]; + Arrays.fill(destState, EMPTY_OUTPUT_POSITION); + final float [] originalKeyArray0 = mainKeySource0.getArray(); + mainKeySource0.setArray(destKeyArray0); + final int [] originalStateArray = mainOutputPosition.getArray(); + mainOutputPosition.setArray(destState); + for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + continue; + } + final float k0 = originalKeyArray0[sourceBucket]; + final int hash = hash(k0); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; + while (true) { + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + break; + } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); + } + } + } + + @Override + public int findPositionForKey(Object key) { + final float k0 = TypeUtils.unbox((Float)key); + int hash = hash(k0); + int tableLocation = hashToTableLocation(hash); + final int firstTableLocation = tableLocation; + while (true) { + final int positionValue = mainOutputPosition.getUnsafe(tableLocation); + if (positionValue == EMPTY_OUTPUT_POSITION) { + int alternateTableLocation = hashToTableLocationAlternate(hash); + if (alternateTableLocation >= rehashPointer) { + return -1; + } + final int firstAlternateTableLocation = alternateTableLocation; + while (true) { + final int alternatePositionValue = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (alternatePositionValue == EMPTY_OUTPUT_POSITION) { + return -1; + } + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0)) { + return alternatePositionValue; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (eq(mainKeySource0.getUnsafe(tableLocation), k0)) { + return positionValue; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherFloatByte.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherFloatByte.java new file mode 100644 index 00000000000..4761f8a70e1 --- /dev/null +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherFloatByte.java @@ -0,0 +1,390 @@ +// DO NOT EDIT THIS CLASS, AUTOMATICALLY GENERATED BY io.deephaven.engine.table.impl.by.typed.TypedHasherFactory +// Copyright (c) 2016-2022 Deephaven Data Labs and Patent Pending +// +package io.deephaven.engine.table.impl.by.typed.incopenagg.gen; + +import static io.deephaven.util.compare.ByteComparisons.eq; +import static io.deephaven.util.compare.FloatComparisons.eq; + +import io.deephaven.base.verify.Assert; +import io.deephaven.chunk.ByteChunk; +import io.deephaven.chunk.Chunk; +import io.deephaven.chunk.FloatChunk; +import io.deephaven.chunk.WritableIntChunk; +import io.deephaven.chunk.attributes.Values; +import io.deephaven.chunk.util.hashing.ByteChunkHasher; +import io.deephaven.chunk.util.hashing.FloatChunkHasher; +import io.deephaven.engine.rowset.RowSequence; +import io.deephaven.engine.rowset.chunkattributes.RowKeys; +import io.deephaven.engine.table.ColumnSource; +import io.deephaven.engine.table.impl.by.IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableByteArraySource; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableFloatArraySource; +import io.deephaven.util.type.TypeUtils; +import java.lang.Byte; +import java.lang.Float; +import java.lang.Object; +import java.lang.Override; +import java.util.Arrays; + +final class IncrementalAggOpenHasherFloatByte extends IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase { + private ImmutableFloatArraySource mainKeySource0; + + private ImmutableFloatArraySource alternateKeySource0; + + private ImmutableByteArraySource mainKeySource1; + + private ImmutableByteArraySource alternateKeySource1; + + public IncrementalAggOpenHasherFloatByte(ColumnSource[] tableKeySources, int tableSize, + double maximumLoadFactor, double targetLoadFactor) { + super(tableKeySources, tableSize, maximumLoadFactor); + this.mainKeySource0 = (ImmutableFloatArraySource) super.mainKeySources[0]; + this.mainKeySource0.ensureCapacity(tableSize); + this.mainKeySource1 = (ImmutableByteArraySource) super.mainKeySources[1]; + this.mainKeySource1.ensureCapacity(tableSize); + } + + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + + private int alternateNextTableLocation(int tableLocation) { + return (tableLocation + 1) & (alternateTableSize - 1); + } + + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final FloatChunk keyChunk0 = sourceKeyChunks[0].asFloatChunk(); + final ByteChunk keyChunk1 = sourceKeyChunks[1].asByteChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final float k0 = keyChunk0.get(chunkPosition); + final byte k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void buildForUpdate(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk reincarnatedPositions) { + final FloatChunk keyChunk0 = sourceKeyChunks[0].asFloatChunk(); + final ByteChunk keyChunk1 = sourceKeyChunks[1].asByteChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final float k0 = keyChunk0.get(chunkPosition); + final byte k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void doRemoveProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk emptiedPositions) { + final FloatChunk keyChunk0 = sourceKeyChunks[0].asFloatChunk(); + final ByteChunk keyChunk1 = sourceKeyChunks[1].asByteChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final float k0 = keyChunk0.get(chunkPosition); + final byte k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + protected void doModifyProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final FloatChunk keyChunk0 = sourceKeyChunks[0].asFloatChunk(); + final ByteChunk keyChunk1 = sourceKeyChunks[1].asByteChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final float k0 = keyChunk0.get(chunkPosition); + final byte k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + private static int hash(float k0, byte k1) { + int hash = FloatChunkHasher.hashInitialSingle(k0); + hash = ByteChunkHasher.hashUpdateSingle(hash, k1); + return hash; + } + + private boolean migrateOneLocation(int locationToMigrate) { + final int currentStateValue = alternateOutputPosition.getUnsafe(locationToMigrate); + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + return false; + } + final float k0 = alternateKeySource0.getUnsafe(locationToMigrate); + final byte k1 = alternateKeySource1.getUnsafe(locationToMigrate); + final int hash = hash(k0, k1); + int destinationTableLocation = hashToTableLocation(hash); + while (mainOutputPosition.getUnsafe(destinationTableLocation) != EMPTY_OUTPUT_POSITION) { + destinationTableLocation = nextTableLocation(destinationTableLocation); + } + mainKeySource0.set(destinationTableLocation, k0); + mainKeySource1.set(destinationTableLocation, k1); + mainOutputPosition.set(destinationTableLocation, currentStateValue); + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + alternateOutputPosition.set(locationToMigrate, EMPTY_OUTPUT_POSITION); + return true; + } + + @Override + protected int rehashInternalPartial(int entriesToRehash) { + int rehashedEntries = 0; + while (rehashPointer > 0 && rehashedEntries < entriesToRehash) { + if (migrateOneLocation(--rehashPointer)) { + rehashedEntries++; + } + } + return rehashedEntries; + } + + @Override + protected void newAlternate() { + super.newAlternate(); + this.mainKeySource0 = (ImmutableFloatArraySource)super.mainKeySources[0]; + this.alternateKeySource0 = (ImmutableFloatArraySource)super.alternateKeySources[0]; + this.mainKeySource1 = (ImmutableByteArraySource)super.mainKeySources[1]; + this.alternateKeySource1 = (ImmutableByteArraySource)super.alternateKeySources[1]; + } + + @Override + protected void clearAlternate() { + super.clearAlternate(); + this.alternateKeySource0 = null; + this.alternateKeySource1 = null; + } + + @Override + protected void migrateFront() { + int location = 0; + while (migrateOneLocation(location++)); + } + + @Override + protected void rehashInternalFull(final int oldSize) { + final float[] destKeyArray0 = new float[tableSize]; + final byte[] destKeyArray1 = new byte[tableSize]; + final int[] destState = new int[tableSize]; + Arrays.fill(destState, EMPTY_OUTPUT_POSITION); + final float [] originalKeyArray0 = mainKeySource0.getArray(); + mainKeySource0.setArray(destKeyArray0); + final byte [] originalKeyArray1 = mainKeySource1.getArray(); + mainKeySource1.setArray(destKeyArray1); + final int [] originalStateArray = mainOutputPosition.getArray(); + mainOutputPosition.setArray(destState); + for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + continue; + } + final float k0 = originalKeyArray0[sourceBucket]; + final byte k1 = originalKeyArray1[sourceBucket]; + final int hash = hash(k0, k1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; + while (true) { + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + break; + } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); + } + } + } + + @Override + public int findPositionForKey(Object key) { + final Object [] ka = (Object[])key; + final float k0 = TypeUtils.unbox((Float)ka[0]); + final byte k1 = TypeUtils.unbox((Byte)ka[1]); + int hash = hash(k0, k1); + int tableLocation = hashToTableLocation(hash); + final int firstTableLocation = tableLocation; + while (true) { + final int positionValue = mainOutputPosition.getUnsafe(tableLocation); + if (positionValue == EMPTY_OUTPUT_POSITION) { + int alternateTableLocation = hashToTableLocationAlternate(hash); + if (alternateTableLocation >= rehashPointer) { + return -1; + } + final int firstAlternateTableLocation = alternateTableLocation; + while (true) { + final int alternatePositionValue = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (alternatePositionValue == EMPTY_OUTPUT_POSITION) { + return -1; + } + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + return alternatePositionValue; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + return positionValue; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherFloatChar.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherFloatChar.java new file mode 100644 index 00000000000..5707976daa2 --- /dev/null +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherFloatChar.java @@ -0,0 +1,390 @@ +// DO NOT EDIT THIS CLASS, AUTOMATICALLY GENERATED BY io.deephaven.engine.table.impl.by.typed.TypedHasherFactory +// Copyright (c) 2016-2022 Deephaven Data Labs and Patent Pending +// +package io.deephaven.engine.table.impl.by.typed.incopenagg.gen; + +import static io.deephaven.util.compare.CharComparisons.eq; +import static io.deephaven.util.compare.FloatComparisons.eq; + +import io.deephaven.base.verify.Assert; +import io.deephaven.chunk.CharChunk; +import io.deephaven.chunk.Chunk; +import io.deephaven.chunk.FloatChunk; +import io.deephaven.chunk.WritableIntChunk; +import io.deephaven.chunk.attributes.Values; +import io.deephaven.chunk.util.hashing.CharChunkHasher; +import io.deephaven.chunk.util.hashing.FloatChunkHasher; +import io.deephaven.engine.rowset.RowSequence; +import io.deephaven.engine.rowset.chunkattributes.RowKeys; +import io.deephaven.engine.table.ColumnSource; +import io.deephaven.engine.table.impl.by.IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableCharArraySource; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableFloatArraySource; +import io.deephaven.util.type.TypeUtils; +import java.lang.Character; +import java.lang.Float; +import java.lang.Object; +import java.lang.Override; +import java.util.Arrays; + +final class IncrementalAggOpenHasherFloatChar extends IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase { + private ImmutableFloatArraySource mainKeySource0; + + private ImmutableFloatArraySource alternateKeySource0; + + private ImmutableCharArraySource mainKeySource1; + + private ImmutableCharArraySource alternateKeySource1; + + public IncrementalAggOpenHasherFloatChar(ColumnSource[] tableKeySources, int tableSize, + double maximumLoadFactor, double targetLoadFactor) { + super(tableKeySources, tableSize, maximumLoadFactor); + this.mainKeySource0 = (ImmutableFloatArraySource) super.mainKeySources[0]; + this.mainKeySource0.ensureCapacity(tableSize); + this.mainKeySource1 = (ImmutableCharArraySource) super.mainKeySources[1]; + this.mainKeySource1.ensureCapacity(tableSize); + } + + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + + private int alternateNextTableLocation(int tableLocation) { + return (tableLocation + 1) & (alternateTableSize - 1); + } + + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final FloatChunk keyChunk0 = sourceKeyChunks[0].asFloatChunk(); + final CharChunk keyChunk1 = sourceKeyChunks[1].asCharChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final float k0 = keyChunk0.get(chunkPosition); + final char k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void buildForUpdate(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk reincarnatedPositions) { + final FloatChunk keyChunk0 = sourceKeyChunks[0].asFloatChunk(); + final CharChunk keyChunk1 = sourceKeyChunks[1].asCharChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final float k0 = keyChunk0.get(chunkPosition); + final char k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void doRemoveProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk emptiedPositions) { + final FloatChunk keyChunk0 = sourceKeyChunks[0].asFloatChunk(); + final CharChunk keyChunk1 = sourceKeyChunks[1].asCharChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final float k0 = keyChunk0.get(chunkPosition); + final char k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + protected void doModifyProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final FloatChunk keyChunk0 = sourceKeyChunks[0].asFloatChunk(); + final CharChunk keyChunk1 = sourceKeyChunks[1].asCharChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final float k0 = keyChunk0.get(chunkPosition); + final char k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + private static int hash(float k0, char k1) { + int hash = FloatChunkHasher.hashInitialSingle(k0); + hash = CharChunkHasher.hashUpdateSingle(hash, k1); + return hash; + } + + private boolean migrateOneLocation(int locationToMigrate) { + final int currentStateValue = alternateOutputPosition.getUnsafe(locationToMigrate); + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + return false; + } + final float k0 = alternateKeySource0.getUnsafe(locationToMigrate); + final char k1 = alternateKeySource1.getUnsafe(locationToMigrate); + final int hash = hash(k0, k1); + int destinationTableLocation = hashToTableLocation(hash); + while (mainOutputPosition.getUnsafe(destinationTableLocation) != EMPTY_OUTPUT_POSITION) { + destinationTableLocation = nextTableLocation(destinationTableLocation); + } + mainKeySource0.set(destinationTableLocation, k0); + mainKeySource1.set(destinationTableLocation, k1); + mainOutputPosition.set(destinationTableLocation, currentStateValue); + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + alternateOutputPosition.set(locationToMigrate, EMPTY_OUTPUT_POSITION); + return true; + } + + @Override + protected int rehashInternalPartial(int entriesToRehash) { + int rehashedEntries = 0; + while (rehashPointer > 0 && rehashedEntries < entriesToRehash) { + if (migrateOneLocation(--rehashPointer)) { + rehashedEntries++; + } + } + return rehashedEntries; + } + + @Override + protected void newAlternate() { + super.newAlternate(); + this.mainKeySource0 = (ImmutableFloatArraySource)super.mainKeySources[0]; + this.alternateKeySource0 = (ImmutableFloatArraySource)super.alternateKeySources[0]; + this.mainKeySource1 = (ImmutableCharArraySource)super.mainKeySources[1]; + this.alternateKeySource1 = (ImmutableCharArraySource)super.alternateKeySources[1]; + } + + @Override + protected void clearAlternate() { + super.clearAlternate(); + this.alternateKeySource0 = null; + this.alternateKeySource1 = null; + } + + @Override + protected void migrateFront() { + int location = 0; + while (migrateOneLocation(location++)); + } + + @Override + protected void rehashInternalFull(final int oldSize) { + final float[] destKeyArray0 = new float[tableSize]; + final char[] destKeyArray1 = new char[tableSize]; + final int[] destState = new int[tableSize]; + Arrays.fill(destState, EMPTY_OUTPUT_POSITION); + final float [] originalKeyArray0 = mainKeySource0.getArray(); + mainKeySource0.setArray(destKeyArray0); + final char [] originalKeyArray1 = mainKeySource1.getArray(); + mainKeySource1.setArray(destKeyArray1); + final int [] originalStateArray = mainOutputPosition.getArray(); + mainOutputPosition.setArray(destState); + for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + continue; + } + final float k0 = originalKeyArray0[sourceBucket]; + final char k1 = originalKeyArray1[sourceBucket]; + final int hash = hash(k0, k1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; + while (true) { + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + break; + } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); + } + } + } + + @Override + public int findPositionForKey(Object key) { + final Object [] ka = (Object[])key; + final float k0 = TypeUtils.unbox((Float)ka[0]); + final char k1 = TypeUtils.unbox((Character)ka[1]); + int hash = hash(k0, k1); + int tableLocation = hashToTableLocation(hash); + final int firstTableLocation = tableLocation; + while (true) { + final int positionValue = mainOutputPosition.getUnsafe(tableLocation); + if (positionValue == EMPTY_OUTPUT_POSITION) { + int alternateTableLocation = hashToTableLocationAlternate(hash); + if (alternateTableLocation >= rehashPointer) { + return -1; + } + final int firstAlternateTableLocation = alternateTableLocation; + while (true) { + final int alternatePositionValue = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (alternatePositionValue == EMPTY_OUTPUT_POSITION) { + return -1; + } + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + return alternatePositionValue; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + return positionValue; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherFloatDouble.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherFloatDouble.java new file mode 100644 index 00000000000..31bfce92355 --- /dev/null +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherFloatDouble.java @@ -0,0 +1,390 @@ +// DO NOT EDIT THIS CLASS, AUTOMATICALLY GENERATED BY io.deephaven.engine.table.impl.by.typed.TypedHasherFactory +// Copyright (c) 2016-2022 Deephaven Data Labs and Patent Pending +// +package io.deephaven.engine.table.impl.by.typed.incopenagg.gen; + +import static io.deephaven.util.compare.DoubleComparisons.eq; +import static io.deephaven.util.compare.FloatComparisons.eq; + +import io.deephaven.base.verify.Assert; +import io.deephaven.chunk.Chunk; +import io.deephaven.chunk.DoubleChunk; +import io.deephaven.chunk.FloatChunk; +import io.deephaven.chunk.WritableIntChunk; +import io.deephaven.chunk.attributes.Values; +import io.deephaven.chunk.util.hashing.DoubleChunkHasher; +import io.deephaven.chunk.util.hashing.FloatChunkHasher; +import io.deephaven.engine.rowset.RowSequence; +import io.deephaven.engine.rowset.chunkattributes.RowKeys; +import io.deephaven.engine.table.ColumnSource; +import io.deephaven.engine.table.impl.by.IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableDoubleArraySource; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableFloatArraySource; +import io.deephaven.util.type.TypeUtils; +import java.lang.Double; +import java.lang.Float; +import java.lang.Object; +import java.lang.Override; +import java.util.Arrays; + +final class IncrementalAggOpenHasherFloatDouble extends IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase { + private ImmutableFloatArraySource mainKeySource0; + + private ImmutableFloatArraySource alternateKeySource0; + + private ImmutableDoubleArraySource mainKeySource1; + + private ImmutableDoubleArraySource alternateKeySource1; + + public IncrementalAggOpenHasherFloatDouble(ColumnSource[] tableKeySources, int tableSize, + double maximumLoadFactor, double targetLoadFactor) { + super(tableKeySources, tableSize, maximumLoadFactor); + this.mainKeySource0 = (ImmutableFloatArraySource) super.mainKeySources[0]; + this.mainKeySource0.ensureCapacity(tableSize); + this.mainKeySource1 = (ImmutableDoubleArraySource) super.mainKeySources[1]; + this.mainKeySource1.ensureCapacity(tableSize); + } + + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + + private int alternateNextTableLocation(int tableLocation) { + return (tableLocation + 1) & (alternateTableSize - 1); + } + + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final FloatChunk keyChunk0 = sourceKeyChunks[0].asFloatChunk(); + final DoubleChunk keyChunk1 = sourceKeyChunks[1].asDoubleChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final float k0 = keyChunk0.get(chunkPosition); + final double k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void buildForUpdate(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk reincarnatedPositions) { + final FloatChunk keyChunk0 = sourceKeyChunks[0].asFloatChunk(); + final DoubleChunk keyChunk1 = sourceKeyChunks[1].asDoubleChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final float k0 = keyChunk0.get(chunkPosition); + final double k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void doRemoveProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk emptiedPositions) { + final FloatChunk keyChunk0 = sourceKeyChunks[0].asFloatChunk(); + final DoubleChunk keyChunk1 = sourceKeyChunks[1].asDoubleChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final float k0 = keyChunk0.get(chunkPosition); + final double k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + protected void doModifyProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final FloatChunk keyChunk0 = sourceKeyChunks[0].asFloatChunk(); + final DoubleChunk keyChunk1 = sourceKeyChunks[1].asDoubleChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final float k0 = keyChunk0.get(chunkPosition); + final double k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + private static int hash(float k0, double k1) { + int hash = FloatChunkHasher.hashInitialSingle(k0); + hash = DoubleChunkHasher.hashUpdateSingle(hash, k1); + return hash; + } + + private boolean migrateOneLocation(int locationToMigrate) { + final int currentStateValue = alternateOutputPosition.getUnsafe(locationToMigrate); + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + return false; + } + final float k0 = alternateKeySource0.getUnsafe(locationToMigrate); + final double k1 = alternateKeySource1.getUnsafe(locationToMigrate); + final int hash = hash(k0, k1); + int destinationTableLocation = hashToTableLocation(hash); + while (mainOutputPosition.getUnsafe(destinationTableLocation) != EMPTY_OUTPUT_POSITION) { + destinationTableLocation = nextTableLocation(destinationTableLocation); + } + mainKeySource0.set(destinationTableLocation, k0); + mainKeySource1.set(destinationTableLocation, k1); + mainOutputPosition.set(destinationTableLocation, currentStateValue); + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + alternateOutputPosition.set(locationToMigrate, EMPTY_OUTPUT_POSITION); + return true; + } + + @Override + protected int rehashInternalPartial(int entriesToRehash) { + int rehashedEntries = 0; + while (rehashPointer > 0 && rehashedEntries < entriesToRehash) { + if (migrateOneLocation(--rehashPointer)) { + rehashedEntries++; + } + } + return rehashedEntries; + } + + @Override + protected void newAlternate() { + super.newAlternate(); + this.mainKeySource0 = (ImmutableFloatArraySource)super.mainKeySources[0]; + this.alternateKeySource0 = (ImmutableFloatArraySource)super.alternateKeySources[0]; + this.mainKeySource1 = (ImmutableDoubleArraySource)super.mainKeySources[1]; + this.alternateKeySource1 = (ImmutableDoubleArraySource)super.alternateKeySources[1]; + } + + @Override + protected void clearAlternate() { + super.clearAlternate(); + this.alternateKeySource0 = null; + this.alternateKeySource1 = null; + } + + @Override + protected void migrateFront() { + int location = 0; + while (migrateOneLocation(location++)); + } + + @Override + protected void rehashInternalFull(final int oldSize) { + final float[] destKeyArray0 = new float[tableSize]; + final double[] destKeyArray1 = new double[tableSize]; + final int[] destState = new int[tableSize]; + Arrays.fill(destState, EMPTY_OUTPUT_POSITION); + final float [] originalKeyArray0 = mainKeySource0.getArray(); + mainKeySource0.setArray(destKeyArray0); + final double [] originalKeyArray1 = mainKeySource1.getArray(); + mainKeySource1.setArray(destKeyArray1); + final int [] originalStateArray = mainOutputPosition.getArray(); + mainOutputPosition.setArray(destState); + for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + continue; + } + final float k0 = originalKeyArray0[sourceBucket]; + final double k1 = originalKeyArray1[sourceBucket]; + final int hash = hash(k0, k1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; + while (true) { + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + break; + } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); + } + } + } + + @Override + public int findPositionForKey(Object key) { + final Object [] ka = (Object[])key; + final float k0 = TypeUtils.unbox((Float)ka[0]); + final double k1 = TypeUtils.unbox((Double)ka[1]); + int hash = hash(k0, k1); + int tableLocation = hashToTableLocation(hash); + final int firstTableLocation = tableLocation; + while (true) { + final int positionValue = mainOutputPosition.getUnsafe(tableLocation); + if (positionValue == EMPTY_OUTPUT_POSITION) { + int alternateTableLocation = hashToTableLocationAlternate(hash); + if (alternateTableLocation >= rehashPointer) { + return -1; + } + final int firstAlternateTableLocation = alternateTableLocation; + while (true) { + final int alternatePositionValue = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (alternatePositionValue == EMPTY_OUTPUT_POSITION) { + return -1; + } + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + return alternatePositionValue; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + return positionValue; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherFloatFloat.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherFloatFloat.java new file mode 100644 index 00000000000..0b299709128 --- /dev/null +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherFloatFloat.java @@ -0,0 +1,385 @@ +// DO NOT EDIT THIS CLASS, AUTOMATICALLY GENERATED BY io.deephaven.engine.table.impl.by.typed.TypedHasherFactory +// Copyright (c) 2016-2022 Deephaven Data Labs and Patent Pending +// +package io.deephaven.engine.table.impl.by.typed.incopenagg.gen; + +import static io.deephaven.util.compare.FloatComparisons.eq; + +import io.deephaven.base.verify.Assert; +import io.deephaven.chunk.Chunk; +import io.deephaven.chunk.FloatChunk; +import io.deephaven.chunk.WritableIntChunk; +import io.deephaven.chunk.attributes.Values; +import io.deephaven.chunk.util.hashing.FloatChunkHasher; +import io.deephaven.engine.rowset.RowSequence; +import io.deephaven.engine.rowset.chunkattributes.RowKeys; +import io.deephaven.engine.table.ColumnSource; +import io.deephaven.engine.table.impl.by.IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableFloatArraySource; +import io.deephaven.util.type.TypeUtils; +import java.lang.Float; +import java.lang.Object; +import java.lang.Override; +import java.util.Arrays; + +final class IncrementalAggOpenHasherFloatFloat extends IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase { + private ImmutableFloatArraySource mainKeySource0; + + private ImmutableFloatArraySource alternateKeySource0; + + private ImmutableFloatArraySource mainKeySource1; + + private ImmutableFloatArraySource alternateKeySource1; + + public IncrementalAggOpenHasherFloatFloat(ColumnSource[] tableKeySources, int tableSize, + double maximumLoadFactor, double targetLoadFactor) { + super(tableKeySources, tableSize, maximumLoadFactor); + this.mainKeySource0 = (ImmutableFloatArraySource) super.mainKeySources[0]; + this.mainKeySource0.ensureCapacity(tableSize); + this.mainKeySource1 = (ImmutableFloatArraySource) super.mainKeySources[1]; + this.mainKeySource1.ensureCapacity(tableSize); + } + + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + + private int alternateNextTableLocation(int tableLocation) { + return (tableLocation + 1) & (alternateTableSize - 1); + } + + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final FloatChunk keyChunk0 = sourceKeyChunks[0].asFloatChunk(); + final FloatChunk keyChunk1 = sourceKeyChunks[1].asFloatChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final float k0 = keyChunk0.get(chunkPosition); + final float k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void buildForUpdate(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk reincarnatedPositions) { + final FloatChunk keyChunk0 = sourceKeyChunks[0].asFloatChunk(); + final FloatChunk keyChunk1 = sourceKeyChunks[1].asFloatChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final float k0 = keyChunk0.get(chunkPosition); + final float k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void doRemoveProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk emptiedPositions) { + final FloatChunk keyChunk0 = sourceKeyChunks[0].asFloatChunk(); + final FloatChunk keyChunk1 = sourceKeyChunks[1].asFloatChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final float k0 = keyChunk0.get(chunkPosition); + final float k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + protected void doModifyProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final FloatChunk keyChunk0 = sourceKeyChunks[0].asFloatChunk(); + final FloatChunk keyChunk1 = sourceKeyChunks[1].asFloatChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final float k0 = keyChunk0.get(chunkPosition); + final float k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + private static int hash(float k0, float k1) { + int hash = FloatChunkHasher.hashInitialSingle(k0); + hash = FloatChunkHasher.hashUpdateSingle(hash, k1); + return hash; + } + + private boolean migrateOneLocation(int locationToMigrate) { + final int currentStateValue = alternateOutputPosition.getUnsafe(locationToMigrate); + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + return false; + } + final float k0 = alternateKeySource0.getUnsafe(locationToMigrate); + final float k1 = alternateKeySource1.getUnsafe(locationToMigrate); + final int hash = hash(k0, k1); + int destinationTableLocation = hashToTableLocation(hash); + while (mainOutputPosition.getUnsafe(destinationTableLocation) != EMPTY_OUTPUT_POSITION) { + destinationTableLocation = nextTableLocation(destinationTableLocation); + } + mainKeySource0.set(destinationTableLocation, k0); + mainKeySource1.set(destinationTableLocation, k1); + mainOutputPosition.set(destinationTableLocation, currentStateValue); + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + alternateOutputPosition.set(locationToMigrate, EMPTY_OUTPUT_POSITION); + return true; + } + + @Override + protected int rehashInternalPartial(int entriesToRehash) { + int rehashedEntries = 0; + while (rehashPointer > 0 && rehashedEntries < entriesToRehash) { + if (migrateOneLocation(--rehashPointer)) { + rehashedEntries++; + } + } + return rehashedEntries; + } + + @Override + protected void newAlternate() { + super.newAlternate(); + this.mainKeySource0 = (ImmutableFloatArraySource)super.mainKeySources[0]; + this.alternateKeySource0 = (ImmutableFloatArraySource)super.alternateKeySources[0]; + this.mainKeySource1 = (ImmutableFloatArraySource)super.mainKeySources[1]; + this.alternateKeySource1 = (ImmutableFloatArraySource)super.alternateKeySources[1]; + } + + @Override + protected void clearAlternate() { + super.clearAlternate(); + this.alternateKeySource0 = null; + this.alternateKeySource1 = null; + } + + @Override + protected void migrateFront() { + int location = 0; + while (migrateOneLocation(location++)); + } + + @Override + protected void rehashInternalFull(final int oldSize) { + final float[] destKeyArray0 = new float[tableSize]; + final float[] destKeyArray1 = new float[tableSize]; + final int[] destState = new int[tableSize]; + Arrays.fill(destState, EMPTY_OUTPUT_POSITION); + final float [] originalKeyArray0 = mainKeySource0.getArray(); + mainKeySource0.setArray(destKeyArray0); + final float [] originalKeyArray1 = mainKeySource1.getArray(); + mainKeySource1.setArray(destKeyArray1); + final int [] originalStateArray = mainOutputPosition.getArray(); + mainOutputPosition.setArray(destState); + for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + continue; + } + final float k0 = originalKeyArray0[sourceBucket]; + final float k1 = originalKeyArray1[sourceBucket]; + final int hash = hash(k0, k1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; + while (true) { + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + break; + } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); + } + } + } + + @Override + public int findPositionForKey(Object key) { + final Object [] ka = (Object[])key; + final float k0 = TypeUtils.unbox((Float)ka[0]); + final float k1 = TypeUtils.unbox((Float)ka[1]); + int hash = hash(k0, k1); + int tableLocation = hashToTableLocation(hash); + final int firstTableLocation = tableLocation; + while (true) { + final int positionValue = mainOutputPosition.getUnsafe(tableLocation); + if (positionValue == EMPTY_OUTPUT_POSITION) { + int alternateTableLocation = hashToTableLocationAlternate(hash); + if (alternateTableLocation >= rehashPointer) { + return -1; + } + final int firstAlternateTableLocation = alternateTableLocation; + while (true) { + final int alternatePositionValue = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (alternatePositionValue == EMPTY_OUTPUT_POSITION) { + return -1; + } + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + return alternatePositionValue; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + return positionValue; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherFloatInt.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherFloatInt.java new file mode 100644 index 00000000000..7546e7e6f71 --- /dev/null +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherFloatInt.java @@ -0,0 +1,390 @@ +// DO NOT EDIT THIS CLASS, AUTOMATICALLY GENERATED BY io.deephaven.engine.table.impl.by.typed.TypedHasherFactory +// Copyright (c) 2016-2022 Deephaven Data Labs and Patent Pending +// +package io.deephaven.engine.table.impl.by.typed.incopenagg.gen; + +import static io.deephaven.util.compare.FloatComparisons.eq; +import static io.deephaven.util.compare.IntComparisons.eq; + +import io.deephaven.base.verify.Assert; +import io.deephaven.chunk.Chunk; +import io.deephaven.chunk.FloatChunk; +import io.deephaven.chunk.IntChunk; +import io.deephaven.chunk.WritableIntChunk; +import io.deephaven.chunk.attributes.Values; +import io.deephaven.chunk.util.hashing.FloatChunkHasher; +import io.deephaven.chunk.util.hashing.IntChunkHasher; +import io.deephaven.engine.rowset.RowSequence; +import io.deephaven.engine.rowset.chunkattributes.RowKeys; +import io.deephaven.engine.table.ColumnSource; +import io.deephaven.engine.table.impl.by.IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableFloatArraySource; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableIntArraySource; +import io.deephaven.util.type.TypeUtils; +import java.lang.Float; +import java.lang.Integer; +import java.lang.Object; +import java.lang.Override; +import java.util.Arrays; + +final class IncrementalAggOpenHasherFloatInt extends IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase { + private ImmutableFloatArraySource mainKeySource0; + + private ImmutableFloatArraySource alternateKeySource0; + + private ImmutableIntArraySource mainKeySource1; + + private ImmutableIntArraySource alternateKeySource1; + + public IncrementalAggOpenHasherFloatInt(ColumnSource[] tableKeySources, int tableSize, + double maximumLoadFactor, double targetLoadFactor) { + super(tableKeySources, tableSize, maximumLoadFactor); + this.mainKeySource0 = (ImmutableFloatArraySource) super.mainKeySources[0]; + this.mainKeySource0.ensureCapacity(tableSize); + this.mainKeySource1 = (ImmutableIntArraySource) super.mainKeySources[1]; + this.mainKeySource1.ensureCapacity(tableSize); + } + + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + + private int alternateNextTableLocation(int tableLocation) { + return (tableLocation + 1) & (alternateTableSize - 1); + } + + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final FloatChunk keyChunk0 = sourceKeyChunks[0].asFloatChunk(); + final IntChunk keyChunk1 = sourceKeyChunks[1].asIntChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final float k0 = keyChunk0.get(chunkPosition); + final int k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void buildForUpdate(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk reincarnatedPositions) { + final FloatChunk keyChunk0 = sourceKeyChunks[0].asFloatChunk(); + final IntChunk keyChunk1 = sourceKeyChunks[1].asIntChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final float k0 = keyChunk0.get(chunkPosition); + final int k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void doRemoveProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk emptiedPositions) { + final FloatChunk keyChunk0 = sourceKeyChunks[0].asFloatChunk(); + final IntChunk keyChunk1 = sourceKeyChunks[1].asIntChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final float k0 = keyChunk0.get(chunkPosition); + final int k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + protected void doModifyProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final FloatChunk keyChunk0 = sourceKeyChunks[0].asFloatChunk(); + final IntChunk keyChunk1 = sourceKeyChunks[1].asIntChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final float k0 = keyChunk0.get(chunkPosition); + final int k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + private static int hash(float k0, int k1) { + int hash = FloatChunkHasher.hashInitialSingle(k0); + hash = IntChunkHasher.hashUpdateSingle(hash, k1); + return hash; + } + + private boolean migrateOneLocation(int locationToMigrate) { + final int currentStateValue = alternateOutputPosition.getUnsafe(locationToMigrate); + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + return false; + } + final float k0 = alternateKeySource0.getUnsafe(locationToMigrate); + final int k1 = alternateKeySource1.getUnsafe(locationToMigrate); + final int hash = hash(k0, k1); + int destinationTableLocation = hashToTableLocation(hash); + while (mainOutputPosition.getUnsafe(destinationTableLocation) != EMPTY_OUTPUT_POSITION) { + destinationTableLocation = nextTableLocation(destinationTableLocation); + } + mainKeySource0.set(destinationTableLocation, k0); + mainKeySource1.set(destinationTableLocation, k1); + mainOutputPosition.set(destinationTableLocation, currentStateValue); + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + alternateOutputPosition.set(locationToMigrate, EMPTY_OUTPUT_POSITION); + return true; + } + + @Override + protected int rehashInternalPartial(int entriesToRehash) { + int rehashedEntries = 0; + while (rehashPointer > 0 && rehashedEntries < entriesToRehash) { + if (migrateOneLocation(--rehashPointer)) { + rehashedEntries++; + } + } + return rehashedEntries; + } + + @Override + protected void newAlternate() { + super.newAlternate(); + this.mainKeySource0 = (ImmutableFloatArraySource)super.mainKeySources[0]; + this.alternateKeySource0 = (ImmutableFloatArraySource)super.alternateKeySources[0]; + this.mainKeySource1 = (ImmutableIntArraySource)super.mainKeySources[1]; + this.alternateKeySource1 = (ImmutableIntArraySource)super.alternateKeySources[1]; + } + + @Override + protected void clearAlternate() { + super.clearAlternate(); + this.alternateKeySource0 = null; + this.alternateKeySource1 = null; + } + + @Override + protected void migrateFront() { + int location = 0; + while (migrateOneLocation(location++)); + } + + @Override + protected void rehashInternalFull(final int oldSize) { + final float[] destKeyArray0 = new float[tableSize]; + final int[] destKeyArray1 = new int[tableSize]; + final int[] destState = new int[tableSize]; + Arrays.fill(destState, EMPTY_OUTPUT_POSITION); + final float [] originalKeyArray0 = mainKeySource0.getArray(); + mainKeySource0.setArray(destKeyArray0); + final int [] originalKeyArray1 = mainKeySource1.getArray(); + mainKeySource1.setArray(destKeyArray1); + final int [] originalStateArray = mainOutputPosition.getArray(); + mainOutputPosition.setArray(destState); + for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + continue; + } + final float k0 = originalKeyArray0[sourceBucket]; + final int k1 = originalKeyArray1[sourceBucket]; + final int hash = hash(k0, k1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; + while (true) { + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + break; + } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); + } + } + } + + @Override + public int findPositionForKey(Object key) { + final Object [] ka = (Object[])key; + final float k0 = TypeUtils.unbox((Float)ka[0]); + final int k1 = TypeUtils.unbox((Integer)ka[1]); + int hash = hash(k0, k1); + int tableLocation = hashToTableLocation(hash); + final int firstTableLocation = tableLocation; + while (true) { + final int positionValue = mainOutputPosition.getUnsafe(tableLocation); + if (positionValue == EMPTY_OUTPUT_POSITION) { + int alternateTableLocation = hashToTableLocationAlternate(hash); + if (alternateTableLocation >= rehashPointer) { + return -1; + } + final int firstAlternateTableLocation = alternateTableLocation; + while (true) { + final int alternatePositionValue = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (alternatePositionValue == EMPTY_OUTPUT_POSITION) { + return -1; + } + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + return alternatePositionValue; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + return positionValue; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherFloatLong.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherFloatLong.java new file mode 100644 index 00000000000..80899a32d4e --- /dev/null +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherFloatLong.java @@ -0,0 +1,390 @@ +// DO NOT EDIT THIS CLASS, AUTOMATICALLY GENERATED BY io.deephaven.engine.table.impl.by.typed.TypedHasherFactory +// Copyright (c) 2016-2022 Deephaven Data Labs and Patent Pending +// +package io.deephaven.engine.table.impl.by.typed.incopenagg.gen; + +import static io.deephaven.util.compare.FloatComparisons.eq; +import static io.deephaven.util.compare.LongComparisons.eq; + +import io.deephaven.base.verify.Assert; +import io.deephaven.chunk.Chunk; +import io.deephaven.chunk.FloatChunk; +import io.deephaven.chunk.LongChunk; +import io.deephaven.chunk.WritableIntChunk; +import io.deephaven.chunk.attributes.Values; +import io.deephaven.chunk.util.hashing.FloatChunkHasher; +import io.deephaven.chunk.util.hashing.LongChunkHasher; +import io.deephaven.engine.rowset.RowSequence; +import io.deephaven.engine.rowset.chunkattributes.RowKeys; +import io.deephaven.engine.table.ColumnSource; +import io.deephaven.engine.table.impl.by.IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableFloatArraySource; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableLongArraySource; +import io.deephaven.util.type.TypeUtils; +import java.lang.Float; +import java.lang.Long; +import java.lang.Object; +import java.lang.Override; +import java.util.Arrays; + +final class IncrementalAggOpenHasherFloatLong extends IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase { + private ImmutableFloatArraySource mainKeySource0; + + private ImmutableFloatArraySource alternateKeySource0; + + private ImmutableLongArraySource mainKeySource1; + + private ImmutableLongArraySource alternateKeySource1; + + public IncrementalAggOpenHasherFloatLong(ColumnSource[] tableKeySources, int tableSize, + double maximumLoadFactor, double targetLoadFactor) { + super(tableKeySources, tableSize, maximumLoadFactor); + this.mainKeySource0 = (ImmutableFloatArraySource) super.mainKeySources[0]; + this.mainKeySource0.ensureCapacity(tableSize); + this.mainKeySource1 = (ImmutableLongArraySource) super.mainKeySources[1]; + this.mainKeySource1.ensureCapacity(tableSize); + } + + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + + private int alternateNextTableLocation(int tableLocation) { + return (tableLocation + 1) & (alternateTableSize - 1); + } + + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final FloatChunk keyChunk0 = sourceKeyChunks[0].asFloatChunk(); + final LongChunk keyChunk1 = sourceKeyChunks[1].asLongChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final float k0 = keyChunk0.get(chunkPosition); + final long k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void buildForUpdate(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk reincarnatedPositions) { + final FloatChunk keyChunk0 = sourceKeyChunks[0].asFloatChunk(); + final LongChunk keyChunk1 = sourceKeyChunks[1].asLongChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final float k0 = keyChunk0.get(chunkPosition); + final long k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void doRemoveProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk emptiedPositions) { + final FloatChunk keyChunk0 = sourceKeyChunks[0].asFloatChunk(); + final LongChunk keyChunk1 = sourceKeyChunks[1].asLongChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final float k0 = keyChunk0.get(chunkPosition); + final long k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + protected void doModifyProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final FloatChunk keyChunk0 = sourceKeyChunks[0].asFloatChunk(); + final LongChunk keyChunk1 = sourceKeyChunks[1].asLongChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final float k0 = keyChunk0.get(chunkPosition); + final long k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + private static int hash(float k0, long k1) { + int hash = FloatChunkHasher.hashInitialSingle(k0); + hash = LongChunkHasher.hashUpdateSingle(hash, k1); + return hash; + } + + private boolean migrateOneLocation(int locationToMigrate) { + final int currentStateValue = alternateOutputPosition.getUnsafe(locationToMigrate); + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + return false; + } + final float k0 = alternateKeySource0.getUnsafe(locationToMigrate); + final long k1 = alternateKeySource1.getUnsafe(locationToMigrate); + final int hash = hash(k0, k1); + int destinationTableLocation = hashToTableLocation(hash); + while (mainOutputPosition.getUnsafe(destinationTableLocation) != EMPTY_OUTPUT_POSITION) { + destinationTableLocation = nextTableLocation(destinationTableLocation); + } + mainKeySource0.set(destinationTableLocation, k0); + mainKeySource1.set(destinationTableLocation, k1); + mainOutputPosition.set(destinationTableLocation, currentStateValue); + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + alternateOutputPosition.set(locationToMigrate, EMPTY_OUTPUT_POSITION); + return true; + } + + @Override + protected int rehashInternalPartial(int entriesToRehash) { + int rehashedEntries = 0; + while (rehashPointer > 0 && rehashedEntries < entriesToRehash) { + if (migrateOneLocation(--rehashPointer)) { + rehashedEntries++; + } + } + return rehashedEntries; + } + + @Override + protected void newAlternate() { + super.newAlternate(); + this.mainKeySource0 = (ImmutableFloatArraySource)super.mainKeySources[0]; + this.alternateKeySource0 = (ImmutableFloatArraySource)super.alternateKeySources[0]; + this.mainKeySource1 = (ImmutableLongArraySource)super.mainKeySources[1]; + this.alternateKeySource1 = (ImmutableLongArraySource)super.alternateKeySources[1]; + } + + @Override + protected void clearAlternate() { + super.clearAlternate(); + this.alternateKeySource0 = null; + this.alternateKeySource1 = null; + } + + @Override + protected void migrateFront() { + int location = 0; + while (migrateOneLocation(location++)); + } + + @Override + protected void rehashInternalFull(final int oldSize) { + final float[] destKeyArray0 = new float[tableSize]; + final long[] destKeyArray1 = new long[tableSize]; + final int[] destState = new int[tableSize]; + Arrays.fill(destState, EMPTY_OUTPUT_POSITION); + final float [] originalKeyArray0 = mainKeySource0.getArray(); + mainKeySource0.setArray(destKeyArray0); + final long [] originalKeyArray1 = mainKeySource1.getArray(); + mainKeySource1.setArray(destKeyArray1); + final int [] originalStateArray = mainOutputPosition.getArray(); + mainOutputPosition.setArray(destState); + for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + continue; + } + final float k0 = originalKeyArray0[sourceBucket]; + final long k1 = originalKeyArray1[sourceBucket]; + final int hash = hash(k0, k1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; + while (true) { + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + break; + } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); + } + } + } + + @Override + public int findPositionForKey(Object key) { + final Object [] ka = (Object[])key; + final float k0 = TypeUtils.unbox((Float)ka[0]); + final long k1 = TypeUtils.unbox((Long)ka[1]); + int hash = hash(k0, k1); + int tableLocation = hashToTableLocation(hash); + final int firstTableLocation = tableLocation; + while (true) { + final int positionValue = mainOutputPosition.getUnsafe(tableLocation); + if (positionValue == EMPTY_OUTPUT_POSITION) { + int alternateTableLocation = hashToTableLocationAlternate(hash); + if (alternateTableLocation >= rehashPointer) { + return -1; + } + final int firstAlternateTableLocation = alternateTableLocation; + while (true) { + final int alternatePositionValue = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (alternatePositionValue == EMPTY_OUTPUT_POSITION) { + return -1; + } + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + return alternatePositionValue; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + return positionValue; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherFloatObject.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherFloatObject.java new file mode 100644 index 00000000000..79d341903e5 --- /dev/null +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherFloatObject.java @@ -0,0 +1,390 @@ +// DO NOT EDIT THIS CLASS, AUTOMATICALLY GENERATED BY io.deephaven.engine.table.impl.by.typed.TypedHasherFactory +// Copyright (c) 2016-2022 Deephaven Data Labs and Patent Pending +// +package io.deephaven.engine.table.impl.by.typed.incopenagg.gen; + +import static io.deephaven.util.compare.FloatComparisons.eq; +import static io.deephaven.util.compare.ObjectComparisons.eq; + +import io.deephaven.base.verify.Assert; +import io.deephaven.chunk.Chunk; +import io.deephaven.chunk.FloatChunk; +import io.deephaven.chunk.ObjectChunk; +import io.deephaven.chunk.WritableIntChunk; +import io.deephaven.chunk.attributes.Values; +import io.deephaven.chunk.util.hashing.FloatChunkHasher; +import io.deephaven.chunk.util.hashing.ObjectChunkHasher; +import io.deephaven.engine.rowset.RowSequence; +import io.deephaven.engine.rowset.chunkattributes.RowKeys; +import io.deephaven.engine.table.ColumnSource; +import io.deephaven.engine.table.impl.by.IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableFloatArraySource; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableObjectArraySource; +import io.deephaven.util.type.TypeUtils; +import java.lang.Float; +import java.lang.Object; +import java.lang.Override; +import java.util.Arrays; + +final class IncrementalAggOpenHasherFloatObject extends IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase { + private ImmutableFloatArraySource mainKeySource0; + + private ImmutableFloatArraySource alternateKeySource0; + + private ImmutableObjectArraySource mainKeySource1; + + private ImmutableObjectArraySource alternateKeySource1; + + public IncrementalAggOpenHasherFloatObject(ColumnSource[] tableKeySources, int tableSize, + double maximumLoadFactor, double targetLoadFactor) { + super(tableKeySources, tableSize, maximumLoadFactor); + this.mainKeySource0 = (ImmutableFloatArraySource) super.mainKeySources[0]; + this.mainKeySource0.ensureCapacity(tableSize); + this.mainKeySource1 = (ImmutableObjectArraySource) super.mainKeySources[1]; + this.mainKeySource1.ensureCapacity(tableSize); + } + + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + + private int alternateNextTableLocation(int tableLocation) { + return (tableLocation + 1) & (alternateTableSize - 1); + } + + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final FloatChunk keyChunk0 = sourceKeyChunks[0].asFloatChunk(); + final ObjectChunk keyChunk1 = sourceKeyChunks[1].asObjectChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final float k0 = keyChunk0.get(chunkPosition); + final Object k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void buildForUpdate(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk reincarnatedPositions) { + final FloatChunk keyChunk0 = sourceKeyChunks[0].asFloatChunk(); + final ObjectChunk keyChunk1 = sourceKeyChunks[1].asObjectChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final float k0 = keyChunk0.get(chunkPosition); + final Object k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void doRemoveProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk emptiedPositions) { + final FloatChunk keyChunk0 = sourceKeyChunks[0].asFloatChunk(); + final ObjectChunk keyChunk1 = sourceKeyChunks[1].asObjectChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final float k0 = keyChunk0.get(chunkPosition); + final Object k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + protected void doModifyProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final FloatChunk keyChunk0 = sourceKeyChunks[0].asFloatChunk(); + final ObjectChunk keyChunk1 = sourceKeyChunks[1].asObjectChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final float k0 = keyChunk0.get(chunkPosition); + final Object k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + private static int hash(float k0, Object k1) { + int hash = FloatChunkHasher.hashInitialSingle(k0); + hash = ObjectChunkHasher.hashUpdateSingle(hash, k1); + return hash; + } + + private boolean migrateOneLocation(int locationToMigrate) { + final int currentStateValue = alternateOutputPosition.getUnsafe(locationToMigrate); + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + return false; + } + final float k0 = alternateKeySource0.getUnsafe(locationToMigrate); + final Object k1 = alternateKeySource1.getUnsafe(locationToMigrate); + final int hash = hash(k0, k1); + int destinationTableLocation = hashToTableLocation(hash); + while (mainOutputPosition.getUnsafe(destinationTableLocation) != EMPTY_OUTPUT_POSITION) { + destinationTableLocation = nextTableLocation(destinationTableLocation); + } + mainKeySource0.set(destinationTableLocation, k0); + mainKeySource1.set(destinationTableLocation, k1); + alternateKeySource1.set(locationToMigrate, null); + mainOutputPosition.set(destinationTableLocation, currentStateValue); + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + alternateOutputPosition.set(locationToMigrate, EMPTY_OUTPUT_POSITION); + return true; + } + + @Override + protected int rehashInternalPartial(int entriesToRehash) { + int rehashedEntries = 0; + while (rehashPointer > 0 && rehashedEntries < entriesToRehash) { + if (migrateOneLocation(--rehashPointer)) { + rehashedEntries++; + } + } + return rehashedEntries; + } + + @Override + protected void newAlternate() { + super.newAlternate(); + this.mainKeySource0 = (ImmutableFloatArraySource)super.mainKeySources[0]; + this.alternateKeySource0 = (ImmutableFloatArraySource)super.alternateKeySources[0]; + this.mainKeySource1 = (ImmutableObjectArraySource)super.mainKeySources[1]; + this.alternateKeySource1 = (ImmutableObjectArraySource)super.alternateKeySources[1]; + } + + @Override + protected void clearAlternate() { + super.clearAlternate(); + this.alternateKeySource0 = null; + this.alternateKeySource1 = null; + } + + @Override + protected void migrateFront() { + int location = 0; + while (migrateOneLocation(location++)); + } + + @Override + protected void rehashInternalFull(final int oldSize) { + final float[] destKeyArray0 = new float[tableSize]; + final Object[] destKeyArray1 = new Object[tableSize]; + final int[] destState = new int[tableSize]; + Arrays.fill(destState, EMPTY_OUTPUT_POSITION); + final float [] originalKeyArray0 = mainKeySource0.getArray(); + mainKeySource0.setArray(destKeyArray0); + final Object [] originalKeyArray1 = mainKeySource1.getArray(); + mainKeySource1.setArray(destKeyArray1); + final int [] originalStateArray = mainOutputPosition.getArray(); + mainOutputPosition.setArray(destState); + for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + continue; + } + final float k0 = originalKeyArray0[sourceBucket]; + final Object k1 = originalKeyArray1[sourceBucket]; + final int hash = hash(k0, k1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; + while (true) { + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + break; + } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); + } + } + } + + @Override + public int findPositionForKey(Object key) { + final Object [] ka = (Object[])key; + final float k0 = TypeUtils.unbox((Float)ka[0]); + final Object k1 = ka[1]; + int hash = hash(k0, k1); + int tableLocation = hashToTableLocation(hash); + final int firstTableLocation = tableLocation; + while (true) { + final int positionValue = mainOutputPosition.getUnsafe(tableLocation); + if (positionValue == EMPTY_OUTPUT_POSITION) { + int alternateTableLocation = hashToTableLocationAlternate(hash); + if (alternateTableLocation >= rehashPointer) { + return -1; + } + final int firstAlternateTableLocation = alternateTableLocation; + while (true) { + final int alternatePositionValue = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (alternatePositionValue == EMPTY_OUTPUT_POSITION) { + return -1; + } + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + return alternatePositionValue; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + return positionValue; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherFloatShort.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherFloatShort.java new file mode 100644 index 00000000000..d992606cc66 --- /dev/null +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherFloatShort.java @@ -0,0 +1,390 @@ +// DO NOT EDIT THIS CLASS, AUTOMATICALLY GENERATED BY io.deephaven.engine.table.impl.by.typed.TypedHasherFactory +// Copyright (c) 2016-2022 Deephaven Data Labs and Patent Pending +// +package io.deephaven.engine.table.impl.by.typed.incopenagg.gen; + +import static io.deephaven.util.compare.FloatComparisons.eq; +import static io.deephaven.util.compare.ShortComparisons.eq; + +import io.deephaven.base.verify.Assert; +import io.deephaven.chunk.Chunk; +import io.deephaven.chunk.FloatChunk; +import io.deephaven.chunk.ShortChunk; +import io.deephaven.chunk.WritableIntChunk; +import io.deephaven.chunk.attributes.Values; +import io.deephaven.chunk.util.hashing.FloatChunkHasher; +import io.deephaven.chunk.util.hashing.ShortChunkHasher; +import io.deephaven.engine.rowset.RowSequence; +import io.deephaven.engine.rowset.chunkattributes.RowKeys; +import io.deephaven.engine.table.ColumnSource; +import io.deephaven.engine.table.impl.by.IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableFloatArraySource; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableShortArraySource; +import io.deephaven.util.type.TypeUtils; +import java.lang.Float; +import java.lang.Object; +import java.lang.Override; +import java.lang.Short; +import java.util.Arrays; + +final class IncrementalAggOpenHasherFloatShort extends IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase { + private ImmutableFloatArraySource mainKeySource0; + + private ImmutableFloatArraySource alternateKeySource0; + + private ImmutableShortArraySource mainKeySource1; + + private ImmutableShortArraySource alternateKeySource1; + + public IncrementalAggOpenHasherFloatShort(ColumnSource[] tableKeySources, int tableSize, + double maximumLoadFactor, double targetLoadFactor) { + super(tableKeySources, tableSize, maximumLoadFactor); + this.mainKeySource0 = (ImmutableFloatArraySource) super.mainKeySources[0]; + this.mainKeySource0.ensureCapacity(tableSize); + this.mainKeySource1 = (ImmutableShortArraySource) super.mainKeySources[1]; + this.mainKeySource1.ensureCapacity(tableSize); + } + + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + + private int alternateNextTableLocation(int tableLocation) { + return (tableLocation + 1) & (alternateTableSize - 1); + } + + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final FloatChunk keyChunk0 = sourceKeyChunks[0].asFloatChunk(); + final ShortChunk keyChunk1 = sourceKeyChunks[1].asShortChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final float k0 = keyChunk0.get(chunkPosition); + final short k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void buildForUpdate(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk reincarnatedPositions) { + final FloatChunk keyChunk0 = sourceKeyChunks[0].asFloatChunk(); + final ShortChunk keyChunk1 = sourceKeyChunks[1].asShortChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final float k0 = keyChunk0.get(chunkPosition); + final short k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void doRemoveProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk emptiedPositions) { + final FloatChunk keyChunk0 = sourceKeyChunks[0].asFloatChunk(); + final ShortChunk keyChunk1 = sourceKeyChunks[1].asShortChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final float k0 = keyChunk0.get(chunkPosition); + final short k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + protected void doModifyProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final FloatChunk keyChunk0 = sourceKeyChunks[0].asFloatChunk(); + final ShortChunk keyChunk1 = sourceKeyChunks[1].asShortChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final float k0 = keyChunk0.get(chunkPosition); + final short k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + private static int hash(float k0, short k1) { + int hash = FloatChunkHasher.hashInitialSingle(k0); + hash = ShortChunkHasher.hashUpdateSingle(hash, k1); + return hash; + } + + private boolean migrateOneLocation(int locationToMigrate) { + final int currentStateValue = alternateOutputPosition.getUnsafe(locationToMigrate); + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + return false; + } + final float k0 = alternateKeySource0.getUnsafe(locationToMigrate); + final short k1 = alternateKeySource1.getUnsafe(locationToMigrate); + final int hash = hash(k0, k1); + int destinationTableLocation = hashToTableLocation(hash); + while (mainOutputPosition.getUnsafe(destinationTableLocation) != EMPTY_OUTPUT_POSITION) { + destinationTableLocation = nextTableLocation(destinationTableLocation); + } + mainKeySource0.set(destinationTableLocation, k0); + mainKeySource1.set(destinationTableLocation, k1); + mainOutputPosition.set(destinationTableLocation, currentStateValue); + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + alternateOutputPosition.set(locationToMigrate, EMPTY_OUTPUT_POSITION); + return true; + } + + @Override + protected int rehashInternalPartial(int entriesToRehash) { + int rehashedEntries = 0; + while (rehashPointer > 0 && rehashedEntries < entriesToRehash) { + if (migrateOneLocation(--rehashPointer)) { + rehashedEntries++; + } + } + return rehashedEntries; + } + + @Override + protected void newAlternate() { + super.newAlternate(); + this.mainKeySource0 = (ImmutableFloatArraySource)super.mainKeySources[0]; + this.alternateKeySource0 = (ImmutableFloatArraySource)super.alternateKeySources[0]; + this.mainKeySource1 = (ImmutableShortArraySource)super.mainKeySources[1]; + this.alternateKeySource1 = (ImmutableShortArraySource)super.alternateKeySources[1]; + } + + @Override + protected void clearAlternate() { + super.clearAlternate(); + this.alternateKeySource0 = null; + this.alternateKeySource1 = null; + } + + @Override + protected void migrateFront() { + int location = 0; + while (migrateOneLocation(location++)); + } + + @Override + protected void rehashInternalFull(final int oldSize) { + final float[] destKeyArray0 = new float[tableSize]; + final short[] destKeyArray1 = new short[tableSize]; + final int[] destState = new int[tableSize]; + Arrays.fill(destState, EMPTY_OUTPUT_POSITION); + final float [] originalKeyArray0 = mainKeySource0.getArray(); + mainKeySource0.setArray(destKeyArray0); + final short [] originalKeyArray1 = mainKeySource1.getArray(); + mainKeySource1.setArray(destKeyArray1); + final int [] originalStateArray = mainOutputPosition.getArray(); + mainOutputPosition.setArray(destState); + for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + continue; + } + final float k0 = originalKeyArray0[sourceBucket]; + final short k1 = originalKeyArray1[sourceBucket]; + final int hash = hash(k0, k1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; + while (true) { + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + break; + } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); + } + } + } + + @Override + public int findPositionForKey(Object key) { + final Object [] ka = (Object[])key; + final float k0 = TypeUtils.unbox((Float)ka[0]); + final short k1 = TypeUtils.unbox((Short)ka[1]); + int hash = hash(k0, k1); + int tableLocation = hashToTableLocation(hash); + final int firstTableLocation = tableLocation; + while (true) { + final int positionValue = mainOutputPosition.getUnsafe(tableLocation); + if (positionValue == EMPTY_OUTPUT_POSITION) { + int alternateTableLocation = hashToTableLocationAlternate(hash); + if (alternateTableLocation >= rehashPointer) { + return -1; + } + final int firstAlternateTableLocation = alternateTableLocation; + while (true) { + final int alternatePositionValue = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (alternatePositionValue == EMPTY_OUTPUT_POSITION) { + return -1; + } + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + return alternatePositionValue; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + return positionValue; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherInt.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherInt.java new file mode 100644 index 00000000000..4e016c44fcf --- /dev/null +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherInt.java @@ -0,0 +1,356 @@ +// DO NOT EDIT THIS CLASS, AUTOMATICALLY GENERATED BY io.deephaven.engine.table.impl.by.typed.TypedHasherFactory +// Copyright (c) 2016-2022 Deephaven Data Labs and Patent Pending +// +package io.deephaven.engine.table.impl.by.typed.incopenagg.gen; + +import static io.deephaven.util.compare.IntComparisons.eq; + +import io.deephaven.base.verify.Assert; +import io.deephaven.chunk.Chunk; +import io.deephaven.chunk.IntChunk; +import io.deephaven.chunk.WritableIntChunk; +import io.deephaven.chunk.attributes.Values; +import io.deephaven.chunk.util.hashing.IntChunkHasher; +import io.deephaven.engine.rowset.RowSequence; +import io.deephaven.engine.rowset.chunkattributes.RowKeys; +import io.deephaven.engine.table.ColumnSource; +import io.deephaven.engine.table.impl.by.IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableIntArraySource; +import io.deephaven.util.type.TypeUtils; +import java.lang.Integer; +import java.lang.Object; +import java.lang.Override; +import java.util.Arrays; + +final class IncrementalAggOpenHasherInt extends IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase { + private ImmutableIntArraySource mainKeySource0; + + private ImmutableIntArraySource alternateKeySource0; + + public IncrementalAggOpenHasherInt(ColumnSource[] tableKeySources, int tableSize, + double maximumLoadFactor, double targetLoadFactor) { + super(tableKeySources, tableSize, maximumLoadFactor); + this.mainKeySource0 = (ImmutableIntArraySource) super.mainKeySources[0]; + this.mainKeySource0.ensureCapacity(tableSize); + } + + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + + private int alternateNextTableLocation(int tableLocation) { + return (tableLocation + 1) & (alternateTableSize - 1); + } + + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final IntChunk keyChunk0 = sourceKeyChunks[0].asIntChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final int k0 = keyChunk0.get(chunkPosition); + final int hash = hash(k0); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void buildForUpdate(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk reincarnatedPositions) { + final IntChunk keyChunk0 = sourceKeyChunks[0].asIntChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final int k0 = keyChunk0.get(chunkPosition); + final int hash = hash(k0); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void doRemoveProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk emptiedPositions) { + final IntChunk keyChunk0 = sourceKeyChunks[0].asIntChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final int k0 = keyChunk0.get(chunkPosition); + final int hash = hash(k0); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + protected void doModifyProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final IntChunk keyChunk0 = sourceKeyChunks[0].asIntChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final int k0 = keyChunk0.get(chunkPosition); + final int hash = hash(k0); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0)) { + outputPositions.set(chunkPosition, outputPosition); + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0)) { + outputPositions.set(chunkPosition, outputPosition); + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + private static int hash(int k0) { + int hash = IntChunkHasher.hashInitialSingle(k0); + return hash; + } + + private boolean migrateOneLocation(int locationToMigrate) { + final int currentStateValue = alternateOutputPosition.getUnsafe(locationToMigrate); + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + return false; + } + final int k0 = alternateKeySource0.getUnsafe(locationToMigrate); + final int hash = hash(k0); + int destinationTableLocation = hashToTableLocation(hash); + while (mainOutputPosition.getUnsafe(destinationTableLocation) != EMPTY_OUTPUT_POSITION) { + destinationTableLocation = nextTableLocation(destinationTableLocation); + } + mainKeySource0.set(destinationTableLocation, k0); + mainOutputPosition.set(destinationTableLocation, currentStateValue); + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + alternateOutputPosition.set(locationToMigrate, EMPTY_OUTPUT_POSITION); + return true; + } + + @Override + protected int rehashInternalPartial(int entriesToRehash) { + int rehashedEntries = 0; + while (rehashPointer > 0 && rehashedEntries < entriesToRehash) { + if (migrateOneLocation(--rehashPointer)) { + rehashedEntries++; + } + } + return rehashedEntries; + } + + @Override + protected void newAlternate() { + super.newAlternate(); + this.mainKeySource0 = (ImmutableIntArraySource)super.mainKeySources[0]; + this.alternateKeySource0 = (ImmutableIntArraySource)super.alternateKeySources[0]; + } + + @Override + protected void clearAlternate() { + super.clearAlternate(); + this.alternateKeySource0 = null; + } + + @Override + protected void migrateFront() { + int location = 0; + while (migrateOneLocation(location++)); + } + + @Override + protected void rehashInternalFull(final int oldSize) { + final int[] destKeyArray0 = new int[tableSize]; + final int[] destState = new int[tableSize]; + Arrays.fill(destState, EMPTY_OUTPUT_POSITION); + final int [] originalKeyArray0 = mainKeySource0.getArray(); + mainKeySource0.setArray(destKeyArray0); + final int [] originalStateArray = mainOutputPosition.getArray(); + mainOutputPosition.setArray(destState); + for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + continue; + } + final int k0 = originalKeyArray0[sourceBucket]; + final int hash = hash(k0); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; + while (true) { + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + break; + } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); + } + } + } + + @Override + public int findPositionForKey(Object key) { + final int k0 = TypeUtils.unbox((Integer)key); + int hash = hash(k0); + int tableLocation = hashToTableLocation(hash); + final int firstTableLocation = tableLocation; + while (true) { + final int positionValue = mainOutputPosition.getUnsafe(tableLocation); + if (positionValue == EMPTY_OUTPUT_POSITION) { + int alternateTableLocation = hashToTableLocationAlternate(hash); + if (alternateTableLocation >= rehashPointer) { + return -1; + } + final int firstAlternateTableLocation = alternateTableLocation; + while (true) { + final int alternatePositionValue = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (alternatePositionValue == EMPTY_OUTPUT_POSITION) { + return -1; + } + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0)) { + return alternatePositionValue; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (eq(mainKeySource0.getUnsafe(tableLocation), k0)) { + return positionValue; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherIntByte.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherIntByte.java new file mode 100644 index 00000000000..bc8c01e550b --- /dev/null +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherIntByte.java @@ -0,0 +1,390 @@ +// DO NOT EDIT THIS CLASS, AUTOMATICALLY GENERATED BY io.deephaven.engine.table.impl.by.typed.TypedHasherFactory +// Copyright (c) 2016-2022 Deephaven Data Labs and Patent Pending +// +package io.deephaven.engine.table.impl.by.typed.incopenagg.gen; + +import static io.deephaven.util.compare.ByteComparisons.eq; +import static io.deephaven.util.compare.IntComparisons.eq; + +import io.deephaven.base.verify.Assert; +import io.deephaven.chunk.ByteChunk; +import io.deephaven.chunk.Chunk; +import io.deephaven.chunk.IntChunk; +import io.deephaven.chunk.WritableIntChunk; +import io.deephaven.chunk.attributes.Values; +import io.deephaven.chunk.util.hashing.ByteChunkHasher; +import io.deephaven.chunk.util.hashing.IntChunkHasher; +import io.deephaven.engine.rowset.RowSequence; +import io.deephaven.engine.rowset.chunkattributes.RowKeys; +import io.deephaven.engine.table.ColumnSource; +import io.deephaven.engine.table.impl.by.IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableByteArraySource; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableIntArraySource; +import io.deephaven.util.type.TypeUtils; +import java.lang.Byte; +import java.lang.Integer; +import java.lang.Object; +import java.lang.Override; +import java.util.Arrays; + +final class IncrementalAggOpenHasherIntByte extends IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase { + private ImmutableIntArraySource mainKeySource0; + + private ImmutableIntArraySource alternateKeySource0; + + private ImmutableByteArraySource mainKeySource1; + + private ImmutableByteArraySource alternateKeySource1; + + public IncrementalAggOpenHasherIntByte(ColumnSource[] tableKeySources, int tableSize, + double maximumLoadFactor, double targetLoadFactor) { + super(tableKeySources, tableSize, maximumLoadFactor); + this.mainKeySource0 = (ImmutableIntArraySource) super.mainKeySources[0]; + this.mainKeySource0.ensureCapacity(tableSize); + this.mainKeySource1 = (ImmutableByteArraySource) super.mainKeySources[1]; + this.mainKeySource1.ensureCapacity(tableSize); + } + + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + + private int alternateNextTableLocation(int tableLocation) { + return (tableLocation + 1) & (alternateTableSize - 1); + } + + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final IntChunk keyChunk0 = sourceKeyChunks[0].asIntChunk(); + final ByteChunk keyChunk1 = sourceKeyChunks[1].asByteChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final int k0 = keyChunk0.get(chunkPosition); + final byte k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void buildForUpdate(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk reincarnatedPositions) { + final IntChunk keyChunk0 = sourceKeyChunks[0].asIntChunk(); + final ByteChunk keyChunk1 = sourceKeyChunks[1].asByteChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final int k0 = keyChunk0.get(chunkPosition); + final byte k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void doRemoveProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk emptiedPositions) { + final IntChunk keyChunk0 = sourceKeyChunks[0].asIntChunk(); + final ByteChunk keyChunk1 = sourceKeyChunks[1].asByteChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final int k0 = keyChunk0.get(chunkPosition); + final byte k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + protected void doModifyProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final IntChunk keyChunk0 = sourceKeyChunks[0].asIntChunk(); + final ByteChunk keyChunk1 = sourceKeyChunks[1].asByteChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final int k0 = keyChunk0.get(chunkPosition); + final byte k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + private static int hash(int k0, byte k1) { + int hash = IntChunkHasher.hashInitialSingle(k0); + hash = ByteChunkHasher.hashUpdateSingle(hash, k1); + return hash; + } + + private boolean migrateOneLocation(int locationToMigrate) { + final int currentStateValue = alternateOutputPosition.getUnsafe(locationToMigrate); + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + return false; + } + final int k0 = alternateKeySource0.getUnsafe(locationToMigrate); + final byte k1 = alternateKeySource1.getUnsafe(locationToMigrate); + final int hash = hash(k0, k1); + int destinationTableLocation = hashToTableLocation(hash); + while (mainOutputPosition.getUnsafe(destinationTableLocation) != EMPTY_OUTPUT_POSITION) { + destinationTableLocation = nextTableLocation(destinationTableLocation); + } + mainKeySource0.set(destinationTableLocation, k0); + mainKeySource1.set(destinationTableLocation, k1); + mainOutputPosition.set(destinationTableLocation, currentStateValue); + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + alternateOutputPosition.set(locationToMigrate, EMPTY_OUTPUT_POSITION); + return true; + } + + @Override + protected int rehashInternalPartial(int entriesToRehash) { + int rehashedEntries = 0; + while (rehashPointer > 0 && rehashedEntries < entriesToRehash) { + if (migrateOneLocation(--rehashPointer)) { + rehashedEntries++; + } + } + return rehashedEntries; + } + + @Override + protected void newAlternate() { + super.newAlternate(); + this.mainKeySource0 = (ImmutableIntArraySource)super.mainKeySources[0]; + this.alternateKeySource0 = (ImmutableIntArraySource)super.alternateKeySources[0]; + this.mainKeySource1 = (ImmutableByteArraySource)super.mainKeySources[1]; + this.alternateKeySource1 = (ImmutableByteArraySource)super.alternateKeySources[1]; + } + + @Override + protected void clearAlternate() { + super.clearAlternate(); + this.alternateKeySource0 = null; + this.alternateKeySource1 = null; + } + + @Override + protected void migrateFront() { + int location = 0; + while (migrateOneLocation(location++)); + } + + @Override + protected void rehashInternalFull(final int oldSize) { + final int[] destKeyArray0 = new int[tableSize]; + final byte[] destKeyArray1 = new byte[tableSize]; + final int[] destState = new int[tableSize]; + Arrays.fill(destState, EMPTY_OUTPUT_POSITION); + final int [] originalKeyArray0 = mainKeySource0.getArray(); + mainKeySource0.setArray(destKeyArray0); + final byte [] originalKeyArray1 = mainKeySource1.getArray(); + mainKeySource1.setArray(destKeyArray1); + final int [] originalStateArray = mainOutputPosition.getArray(); + mainOutputPosition.setArray(destState); + for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + continue; + } + final int k0 = originalKeyArray0[sourceBucket]; + final byte k1 = originalKeyArray1[sourceBucket]; + final int hash = hash(k0, k1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; + while (true) { + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + break; + } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); + } + } + } + + @Override + public int findPositionForKey(Object key) { + final Object [] ka = (Object[])key; + final int k0 = TypeUtils.unbox((Integer)ka[0]); + final byte k1 = TypeUtils.unbox((Byte)ka[1]); + int hash = hash(k0, k1); + int tableLocation = hashToTableLocation(hash); + final int firstTableLocation = tableLocation; + while (true) { + final int positionValue = mainOutputPosition.getUnsafe(tableLocation); + if (positionValue == EMPTY_OUTPUT_POSITION) { + int alternateTableLocation = hashToTableLocationAlternate(hash); + if (alternateTableLocation >= rehashPointer) { + return -1; + } + final int firstAlternateTableLocation = alternateTableLocation; + while (true) { + final int alternatePositionValue = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (alternatePositionValue == EMPTY_OUTPUT_POSITION) { + return -1; + } + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + return alternatePositionValue; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + return positionValue; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherIntChar.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherIntChar.java new file mode 100644 index 00000000000..4d1133acc39 --- /dev/null +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherIntChar.java @@ -0,0 +1,390 @@ +// DO NOT EDIT THIS CLASS, AUTOMATICALLY GENERATED BY io.deephaven.engine.table.impl.by.typed.TypedHasherFactory +// Copyright (c) 2016-2022 Deephaven Data Labs and Patent Pending +// +package io.deephaven.engine.table.impl.by.typed.incopenagg.gen; + +import static io.deephaven.util.compare.CharComparisons.eq; +import static io.deephaven.util.compare.IntComparisons.eq; + +import io.deephaven.base.verify.Assert; +import io.deephaven.chunk.CharChunk; +import io.deephaven.chunk.Chunk; +import io.deephaven.chunk.IntChunk; +import io.deephaven.chunk.WritableIntChunk; +import io.deephaven.chunk.attributes.Values; +import io.deephaven.chunk.util.hashing.CharChunkHasher; +import io.deephaven.chunk.util.hashing.IntChunkHasher; +import io.deephaven.engine.rowset.RowSequence; +import io.deephaven.engine.rowset.chunkattributes.RowKeys; +import io.deephaven.engine.table.ColumnSource; +import io.deephaven.engine.table.impl.by.IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableCharArraySource; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableIntArraySource; +import io.deephaven.util.type.TypeUtils; +import java.lang.Character; +import java.lang.Integer; +import java.lang.Object; +import java.lang.Override; +import java.util.Arrays; + +final class IncrementalAggOpenHasherIntChar extends IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase { + private ImmutableIntArraySource mainKeySource0; + + private ImmutableIntArraySource alternateKeySource0; + + private ImmutableCharArraySource mainKeySource1; + + private ImmutableCharArraySource alternateKeySource1; + + public IncrementalAggOpenHasherIntChar(ColumnSource[] tableKeySources, int tableSize, + double maximumLoadFactor, double targetLoadFactor) { + super(tableKeySources, tableSize, maximumLoadFactor); + this.mainKeySource0 = (ImmutableIntArraySource) super.mainKeySources[0]; + this.mainKeySource0.ensureCapacity(tableSize); + this.mainKeySource1 = (ImmutableCharArraySource) super.mainKeySources[1]; + this.mainKeySource1.ensureCapacity(tableSize); + } + + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + + private int alternateNextTableLocation(int tableLocation) { + return (tableLocation + 1) & (alternateTableSize - 1); + } + + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final IntChunk keyChunk0 = sourceKeyChunks[0].asIntChunk(); + final CharChunk keyChunk1 = sourceKeyChunks[1].asCharChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final int k0 = keyChunk0.get(chunkPosition); + final char k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void buildForUpdate(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk reincarnatedPositions) { + final IntChunk keyChunk0 = sourceKeyChunks[0].asIntChunk(); + final CharChunk keyChunk1 = sourceKeyChunks[1].asCharChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final int k0 = keyChunk0.get(chunkPosition); + final char k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void doRemoveProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk emptiedPositions) { + final IntChunk keyChunk0 = sourceKeyChunks[0].asIntChunk(); + final CharChunk keyChunk1 = sourceKeyChunks[1].asCharChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final int k0 = keyChunk0.get(chunkPosition); + final char k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + protected void doModifyProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final IntChunk keyChunk0 = sourceKeyChunks[0].asIntChunk(); + final CharChunk keyChunk1 = sourceKeyChunks[1].asCharChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final int k0 = keyChunk0.get(chunkPosition); + final char k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + private static int hash(int k0, char k1) { + int hash = IntChunkHasher.hashInitialSingle(k0); + hash = CharChunkHasher.hashUpdateSingle(hash, k1); + return hash; + } + + private boolean migrateOneLocation(int locationToMigrate) { + final int currentStateValue = alternateOutputPosition.getUnsafe(locationToMigrate); + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + return false; + } + final int k0 = alternateKeySource0.getUnsafe(locationToMigrate); + final char k1 = alternateKeySource1.getUnsafe(locationToMigrate); + final int hash = hash(k0, k1); + int destinationTableLocation = hashToTableLocation(hash); + while (mainOutputPosition.getUnsafe(destinationTableLocation) != EMPTY_OUTPUT_POSITION) { + destinationTableLocation = nextTableLocation(destinationTableLocation); + } + mainKeySource0.set(destinationTableLocation, k0); + mainKeySource1.set(destinationTableLocation, k1); + mainOutputPosition.set(destinationTableLocation, currentStateValue); + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + alternateOutputPosition.set(locationToMigrate, EMPTY_OUTPUT_POSITION); + return true; + } + + @Override + protected int rehashInternalPartial(int entriesToRehash) { + int rehashedEntries = 0; + while (rehashPointer > 0 && rehashedEntries < entriesToRehash) { + if (migrateOneLocation(--rehashPointer)) { + rehashedEntries++; + } + } + return rehashedEntries; + } + + @Override + protected void newAlternate() { + super.newAlternate(); + this.mainKeySource0 = (ImmutableIntArraySource)super.mainKeySources[0]; + this.alternateKeySource0 = (ImmutableIntArraySource)super.alternateKeySources[0]; + this.mainKeySource1 = (ImmutableCharArraySource)super.mainKeySources[1]; + this.alternateKeySource1 = (ImmutableCharArraySource)super.alternateKeySources[1]; + } + + @Override + protected void clearAlternate() { + super.clearAlternate(); + this.alternateKeySource0 = null; + this.alternateKeySource1 = null; + } + + @Override + protected void migrateFront() { + int location = 0; + while (migrateOneLocation(location++)); + } + + @Override + protected void rehashInternalFull(final int oldSize) { + final int[] destKeyArray0 = new int[tableSize]; + final char[] destKeyArray1 = new char[tableSize]; + final int[] destState = new int[tableSize]; + Arrays.fill(destState, EMPTY_OUTPUT_POSITION); + final int [] originalKeyArray0 = mainKeySource0.getArray(); + mainKeySource0.setArray(destKeyArray0); + final char [] originalKeyArray1 = mainKeySource1.getArray(); + mainKeySource1.setArray(destKeyArray1); + final int [] originalStateArray = mainOutputPosition.getArray(); + mainOutputPosition.setArray(destState); + for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + continue; + } + final int k0 = originalKeyArray0[sourceBucket]; + final char k1 = originalKeyArray1[sourceBucket]; + final int hash = hash(k0, k1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; + while (true) { + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + break; + } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); + } + } + } + + @Override + public int findPositionForKey(Object key) { + final Object [] ka = (Object[])key; + final int k0 = TypeUtils.unbox((Integer)ka[0]); + final char k1 = TypeUtils.unbox((Character)ka[1]); + int hash = hash(k0, k1); + int tableLocation = hashToTableLocation(hash); + final int firstTableLocation = tableLocation; + while (true) { + final int positionValue = mainOutputPosition.getUnsafe(tableLocation); + if (positionValue == EMPTY_OUTPUT_POSITION) { + int alternateTableLocation = hashToTableLocationAlternate(hash); + if (alternateTableLocation >= rehashPointer) { + return -1; + } + final int firstAlternateTableLocation = alternateTableLocation; + while (true) { + final int alternatePositionValue = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (alternatePositionValue == EMPTY_OUTPUT_POSITION) { + return -1; + } + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + return alternatePositionValue; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + return positionValue; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherIntDouble.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherIntDouble.java new file mode 100644 index 00000000000..86f48d50524 --- /dev/null +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherIntDouble.java @@ -0,0 +1,390 @@ +// DO NOT EDIT THIS CLASS, AUTOMATICALLY GENERATED BY io.deephaven.engine.table.impl.by.typed.TypedHasherFactory +// Copyright (c) 2016-2022 Deephaven Data Labs and Patent Pending +// +package io.deephaven.engine.table.impl.by.typed.incopenagg.gen; + +import static io.deephaven.util.compare.DoubleComparisons.eq; +import static io.deephaven.util.compare.IntComparisons.eq; + +import io.deephaven.base.verify.Assert; +import io.deephaven.chunk.Chunk; +import io.deephaven.chunk.DoubleChunk; +import io.deephaven.chunk.IntChunk; +import io.deephaven.chunk.WritableIntChunk; +import io.deephaven.chunk.attributes.Values; +import io.deephaven.chunk.util.hashing.DoubleChunkHasher; +import io.deephaven.chunk.util.hashing.IntChunkHasher; +import io.deephaven.engine.rowset.RowSequence; +import io.deephaven.engine.rowset.chunkattributes.RowKeys; +import io.deephaven.engine.table.ColumnSource; +import io.deephaven.engine.table.impl.by.IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableDoubleArraySource; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableIntArraySource; +import io.deephaven.util.type.TypeUtils; +import java.lang.Double; +import java.lang.Integer; +import java.lang.Object; +import java.lang.Override; +import java.util.Arrays; + +final class IncrementalAggOpenHasherIntDouble extends IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase { + private ImmutableIntArraySource mainKeySource0; + + private ImmutableIntArraySource alternateKeySource0; + + private ImmutableDoubleArraySource mainKeySource1; + + private ImmutableDoubleArraySource alternateKeySource1; + + public IncrementalAggOpenHasherIntDouble(ColumnSource[] tableKeySources, int tableSize, + double maximumLoadFactor, double targetLoadFactor) { + super(tableKeySources, tableSize, maximumLoadFactor); + this.mainKeySource0 = (ImmutableIntArraySource) super.mainKeySources[0]; + this.mainKeySource0.ensureCapacity(tableSize); + this.mainKeySource1 = (ImmutableDoubleArraySource) super.mainKeySources[1]; + this.mainKeySource1.ensureCapacity(tableSize); + } + + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + + private int alternateNextTableLocation(int tableLocation) { + return (tableLocation + 1) & (alternateTableSize - 1); + } + + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final IntChunk keyChunk0 = sourceKeyChunks[0].asIntChunk(); + final DoubleChunk keyChunk1 = sourceKeyChunks[1].asDoubleChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final int k0 = keyChunk0.get(chunkPosition); + final double k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void buildForUpdate(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk reincarnatedPositions) { + final IntChunk keyChunk0 = sourceKeyChunks[0].asIntChunk(); + final DoubleChunk keyChunk1 = sourceKeyChunks[1].asDoubleChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final int k0 = keyChunk0.get(chunkPosition); + final double k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void doRemoveProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk emptiedPositions) { + final IntChunk keyChunk0 = sourceKeyChunks[0].asIntChunk(); + final DoubleChunk keyChunk1 = sourceKeyChunks[1].asDoubleChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final int k0 = keyChunk0.get(chunkPosition); + final double k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + protected void doModifyProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final IntChunk keyChunk0 = sourceKeyChunks[0].asIntChunk(); + final DoubleChunk keyChunk1 = sourceKeyChunks[1].asDoubleChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final int k0 = keyChunk0.get(chunkPosition); + final double k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + private static int hash(int k0, double k1) { + int hash = IntChunkHasher.hashInitialSingle(k0); + hash = DoubleChunkHasher.hashUpdateSingle(hash, k1); + return hash; + } + + private boolean migrateOneLocation(int locationToMigrate) { + final int currentStateValue = alternateOutputPosition.getUnsafe(locationToMigrate); + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + return false; + } + final int k0 = alternateKeySource0.getUnsafe(locationToMigrate); + final double k1 = alternateKeySource1.getUnsafe(locationToMigrate); + final int hash = hash(k0, k1); + int destinationTableLocation = hashToTableLocation(hash); + while (mainOutputPosition.getUnsafe(destinationTableLocation) != EMPTY_OUTPUT_POSITION) { + destinationTableLocation = nextTableLocation(destinationTableLocation); + } + mainKeySource0.set(destinationTableLocation, k0); + mainKeySource1.set(destinationTableLocation, k1); + mainOutputPosition.set(destinationTableLocation, currentStateValue); + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + alternateOutputPosition.set(locationToMigrate, EMPTY_OUTPUT_POSITION); + return true; + } + + @Override + protected int rehashInternalPartial(int entriesToRehash) { + int rehashedEntries = 0; + while (rehashPointer > 0 && rehashedEntries < entriesToRehash) { + if (migrateOneLocation(--rehashPointer)) { + rehashedEntries++; + } + } + return rehashedEntries; + } + + @Override + protected void newAlternate() { + super.newAlternate(); + this.mainKeySource0 = (ImmutableIntArraySource)super.mainKeySources[0]; + this.alternateKeySource0 = (ImmutableIntArraySource)super.alternateKeySources[0]; + this.mainKeySource1 = (ImmutableDoubleArraySource)super.mainKeySources[1]; + this.alternateKeySource1 = (ImmutableDoubleArraySource)super.alternateKeySources[1]; + } + + @Override + protected void clearAlternate() { + super.clearAlternate(); + this.alternateKeySource0 = null; + this.alternateKeySource1 = null; + } + + @Override + protected void migrateFront() { + int location = 0; + while (migrateOneLocation(location++)); + } + + @Override + protected void rehashInternalFull(final int oldSize) { + final int[] destKeyArray0 = new int[tableSize]; + final double[] destKeyArray1 = new double[tableSize]; + final int[] destState = new int[tableSize]; + Arrays.fill(destState, EMPTY_OUTPUT_POSITION); + final int [] originalKeyArray0 = mainKeySource0.getArray(); + mainKeySource0.setArray(destKeyArray0); + final double [] originalKeyArray1 = mainKeySource1.getArray(); + mainKeySource1.setArray(destKeyArray1); + final int [] originalStateArray = mainOutputPosition.getArray(); + mainOutputPosition.setArray(destState); + for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + continue; + } + final int k0 = originalKeyArray0[sourceBucket]; + final double k1 = originalKeyArray1[sourceBucket]; + final int hash = hash(k0, k1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; + while (true) { + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + break; + } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); + } + } + } + + @Override + public int findPositionForKey(Object key) { + final Object [] ka = (Object[])key; + final int k0 = TypeUtils.unbox((Integer)ka[0]); + final double k1 = TypeUtils.unbox((Double)ka[1]); + int hash = hash(k0, k1); + int tableLocation = hashToTableLocation(hash); + final int firstTableLocation = tableLocation; + while (true) { + final int positionValue = mainOutputPosition.getUnsafe(tableLocation); + if (positionValue == EMPTY_OUTPUT_POSITION) { + int alternateTableLocation = hashToTableLocationAlternate(hash); + if (alternateTableLocation >= rehashPointer) { + return -1; + } + final int firstAlternateTableLocation = alternateTableLocation; + while (true) { + final int alternatePositionValue = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (alternatePositionValue == EMPTY_OUTPUT_POSITION) { + return -1; + } + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + return alternatePositionValue; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + return positionValue; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherIntFloat.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherIntFloat.java new file mode 100644 index 00000000000..8a21023c94b --- /dev/null +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherIntFloat.java @@ -0,0 +1,390 @@ +// DO NOT EDIT THIS CLASS, AUTOMATICALLY GENERATED BY io.deephaven.engine.table.impl.by.typed.TypedHasherFactory +// Copyright (c) 2016-2022 Deephaven Data Labs and Patent Pending +// +package io.deephaven.engine.table.impl.by.typed.incopenagg.gen; + +import static io.deephaven.util.compare.FloatComparisons.eq; +import static io.deephaven.util.compare.IntComparisons.eq; + +import io.deephaven.base.verify.Assert; +import io.deephaven.chunk.Chunk; +import io.deephaven.chunk.FloatChunk; +import io.deephaven.chunk.IntChunk; +import io.deephaven.chunk.WritableIntChunk; +import io.deephaven.chunk.attributes.Values; +import io.deephaven.chunk.util.hashing.FloatChunkHasher; +import io.deephaven.chunk.util.hashing.IntChunkHasher; +import io.deephaven.engine.rowset.RowSequence; +import io.deephaven.engine.rowset.chunkattributes.RowKeys; +import io.deephaven.engine.table.ColumnSource; +import io.deephaven.engine.table.impl.by.IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableFloatArraySource; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableIntArraySource; +import io.deephaven.util.type.TypeUtils; +import java.lang.Float; +import java.lang.Integer; +import java.lang.Object; +import java.lang.Override; +import java.util.Arrays; + +final class IncrementalAggOpenHasherIntFloat extends IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase { + private ImmutableIntArraySource mainKeySource0; + + private ImmutableIntArraySource alternateKeySource0; + + private ImmutableFloatArraySource mainKeySource1; + + private ImmutableFloatArraySource alternateKeySource1; + + public IncrementalAggOpenHasherIntFloat(ColumnSource[] tableKeySources, int tableSize, + double maximumLoadFactor, double targetLoadFactor) { + super(tableKeySources, tableSize, maximumLoadFactor); + this.mainKeySource0 = (ImmutableIntArraySource) super.mainKeySources[0]; + this.mainKeySource0.ensureCapacity(tableSize); + this.mainKeySource1 = (ImmutableFloatArraySource) super.mainKeySources[1]; + this.mainKeySource1.ensureCapacity(tableSize); + } + + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + + private int alternateNextTableLocation(int tableLocation) { + return (tableLocation + 1) & (alternateTableSize - 1); + } + + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final IntChunk keyChunk0 = sourceKeyChunks[0].asIntChunk(); + final FloatChunk keyChunk1 = sourceKeyChunks[1].asFloatChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final int k0 = keyChunk0.get(chunkPosition); + final float k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void buildForUpdate(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk reincarnatedPositions) { + final IntChunk keyChunk0 = sourceKeyChunks[0].asIntChunk(); + final FloatChunk keyChunk1 = sourceKeyChunks[1].asFloatChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final int k0 = keyChunk0.get(chunkPosition); + final float k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void doRemoveProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk emptiedPositions) { + final IntChunk keyChunk0 = sourceKeyChunks[0].asIntChunk(); + final FloatChunk keyChunk1 = sourceKeyChunks[1].asFloatChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final int k0 = keyChunk0.get(chunkPosition); + final float k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + protected void doModifyProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final IntChunk keyChunk0 = sourceKeyChunks[0].asIntChunk(); + final FloatChunk keyChunk1 = sourceKeyChunks[1].asFloatChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final int k0 = keyChunk0.get(chunkPosition); + final float k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + private static int hash(int k0, float k1) { + int hash = IntChunkHasher.hashInitialSingle(k0); + hash = FloatChunkHasher.hashUpdateSingle(hash, k1); + return hash; + } + + private boolean migrateOneLocation(int locationToMigrate) { + final int currentStateValue = alternateOutputPosition.getUnsafe(locationToMigrate); + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + return false; + } + final int k0 = alternateKeySource0.getUnsafe(locationToMigrate); + final float k1 = alternateKeySource1.getUnsafe(locationToMigrate); + final int hash = hash(k0, k1); + int destinationTableLocation = hashToTableLocation(hash); + while (mainOutputPosition.getUnsafe(destinationTableLocation) != EMPTY_OUTPUT_POSITION) { + destinationTableLocation = nextTableLocation(destinationTableLocation); + } + mainKeySource0.set(destinationTableLocation, k0); + mainKeySource1.set(destinationTableLocation, k1); + mainOutputPosition.set(destinationTableLocation, currentStateValue); + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + alternateOutputPosition.set(locationToMigrate, EMPTY_OUTPUT_POSITION); + return true; + } + + @Override + protected int rehashInternalPartial(int entriesToRehash) { + int rehashedEntries = 0; + while (rehashPointer > 0 && rehashedEntries < entriesToRehash) { + if (migrateOneLocation(--rehashPointer)) { + rehashedEntries++; + } + } + return rehashedEntries; + } + + @Override + protected void newAlternate() { + super.newAlternate(); + this.mainKeySource0 = (ImmutableIntArraySource)super.mainKeySources[0]; + this.alternateKeySource0 = (ImmutableIntArraySource)super.alternateKeySources[0]; + this.mainKeySource1 = (ImmutableFloatArraySource)super.mainKeySources[1]; + this.alternateKeySource1 = (ImmutableFloatArraySource)super.alternateKeySources[1]; + } + + @Override + protected void clearAlternate() { + super.clearAlternate(); + this.alternateKeySource0 = null; + this.alternateKeySource1 = null; + } + + @Override + protected void migrateFront() { + int location = 0; + while (migrateOneLocation(location++)); + } + + @Override + protected void rehashInternalFull(final int oldSize) { + final int[] destKeyArray0 = new int[tableSize]; + final float[] destKeyArray1 = new float[tableSize]; + final int[] destState = new int[tableSize]; + Arrays.fill(destState, EMPTY_OUTPUT_POSITION); + final int [] originalKeyArray0 = mainKeySource0.getArray(); + mainKeySource0.setArray(destKeyArray0); + final float [] originalKeyArray1 = mainKeySource1.getArray(); + mainKeySource1.setArray(destKeyArray1); + final int [] originalStateArray = mainOutputPosition.getArray(); + mainOutputPosition.setArray(destState); + for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + continue; + } + final int k0 = originalKeyArray0[sourceBucket]; + final float k1 = originalKeyArray1[sourceBucket]; + final int hash = hash(k0, k1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; + while (true) { + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + break; + } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); + } + } + } + + @Override + public int findPositionForKey(Object key) { + final Object [] ka = (Object[])key; + final int k0 = TypeUtils.unbox((Integer)ka[0]); + final float k1 = TypeUtils.unbox((Float)ka[1]); + int hash = hash(k0, k1); + int tableLocation = hashToTableLocation(hash); + final int firstTableLocation = tableLocation; + while (true) { + final int positionValue = mainOutputPosition.getUnsafe(tableLocation); + if (positionValue == EMPTY_OUTPUT_POSITION) { + int alternateTableLocation = hashToTableLocationAlternate(hash); + if (alternateTableLocation >= rehashPointer) { + return -1; + } + final int firstAlternateTableLocation = alternateTableLocation; + while (true) { + final int alternatePositionValue = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (alternatePositionValue == EMPTY_OUTPUT_POSITION) { + return -1; + } + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + return alternatePositionValue; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + return positionValue; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherIntInt.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherIntInt.java new file mode 100644 index 00000000000..d3c2cdf4674 --- /dev/null +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherIntInt.java @@ -0,0 +1,385 @@ +// DO NOT EDIT THIS CLASS, AUTOMATICALLY GENERATED BY io.deephaven.engine.table.impl.by.typed.TypedHasherFactory +// Copyright (c) 2016-2022 Deephaven Data Labs and Patent Pending +// +package io.deephaven.engine.table.impl.by.typed.incopenagg.gen; + +import static io.deephaven.util.compare.IntComparisons.eq; + +import io.deephaven.base.verify.Assert; +import io.deephaven.chunk.Chunk; +import io.deephaven.chunk.IntChunk; +import io.deephaven.chunk.WritableIntChunk; +import io.deephaven.chunk.attributes.Values; +import io.deephaven.chunk.util.hashing.IntChunkHasher; +import io.deephaven.engine.rowset.RowSequence; +import io.deephaven.engine.rowset.chunkattributes.RowKeys; +import io.deephaven.engine.table.ColumnSource; +import io.deephaven.engine.table.impl.by.IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableIntArraySource; +import io.deephaven.util.type.TypeUtils; +import java.lang.Integer; +import java.lang.Object; +import java.lang.Override; +import java.util.Arrays; + +final class IncrementalAggOpenHasherIntInt extends IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase { + private ImmutableIntArraySource mainKeySource0; + + private ImmutableIntArraySource alternateKeySource0; + + private ImmutableIntArraySource mainKeySource1; + + private ImmutableIntArraySource alternateKeySource1; + + public IncrementalAggOpenHasherIntInt(ColumnSource[] tableKeySources, int tableSize, + double maximumLoadFactor, double targetLoadFactor) { + super(tableKeySources, tableSize, maximumLoadFactor); + this.mainKeySource0 = (ImmutableIntArraySource) super.mainKeySources[0]; + this.mainKeySource0.ensureCapacity(tableSize); + this.mainKeySource1 = (ImmutableIntArraySource) super.mainKeySources[1]; + this.mainKeySource1.ensureCapacity(tableSize); + } + + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + + private int alternateNextTableLocation(int tableLocation) { + return (tableLocation + 1) & (alternateTableSize - 1); + } + + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final IntChunk keyChunk0 = sourceKeyChunks[0].asIntChunk(); + final IntChunk keyChunk1 = sourceKeyChunks[1].asIntChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final int k0 = keyChunk0.get(chunkPosition); + final int k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void buildForUpdate(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk reincarnatedPositions) { + final IntChunk keyChunk0 = sourceKeyChunks[0].asIntChunk(); + final IntChunk keyChunk1 = sourceKeyChunks[1].asIntChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final int k0 = keyChunk0.get(chunkPosition); + final int k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void doRemoveProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk emptiedPositions) { + final IntChunk keyChunk0 = sourceKeyChunks[0].asIntChunk(); + final IntChunk keyChunk1 = sourceKeyChunks[1].asIntChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final int k0 = keyChunk0.get(chunkPosition); + final int k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + protected void doModifyProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final IntChunk keyChunk0 = sourceKeyChunks[0].asIntChunk(); + final IntChunk keyChunk1 = sourceKeyChunks[1].asIntChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final int k0 = keyChunk0.get(chunkPosition); + final int k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + private static int hash(int k0, int k1) { + int hash = IntChunkHasher.hashInitialSingle(k0); + hash = IntChunkHasher.hashUpdateSingle(hash, k1); + return hash; + } + + private boolean migrateOneLocation(int locationToMigrate) { + final int currentStateValue = alternateOutputPosition.getUnsafe(locationToMigrate); + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + return false; + } + final int k0 = alternateKeySource0.getUnsafe(locationToMigrate); + final int k1 = alternateKeySource1.getUnsafe(locationToMigrate); + final int hash = hash(k0, k1); + int destinationTableLocation = hashToTableLocation(hash); + while (mainOutputPosition.getUnsafe(destinationTableLocation) != EMPTY_OUTPUT_POSITION) { + destinationTableLocation = nextTableLocation(destinationTableLocation); + } + mainKeySource0.set(destinationTableLocation, k0); + mainKeySource1.set(destinationTableLocation, k1); + mainOutputPosition.set(destinationTableLocation, currentStateValue); + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + alternateOutputPosition.set(locationToMigrate, EMPTY_OUTPUT_POSITION); + return true; + } + + @Override + protected int rehashInternalPartial(int entriesToRehash) { + int rehashedEntries = 0; + while (rehashPointer > 0 && rehashedEntries < entriesToRehash) { + if (migrateOneLocation(--rehashPointer)) { + rehashedEntries++; + } + } + return rehashedEntries; + } + + @Override + protected void newAlternate() { + super.newAlternate(); + this.mainKeySource0 = (ImmutableIntArraySource)super.mainKeySources[0]; + this.alternateKeySource0 = (ImmutableIntArraySource)super.alternateKeySources[0]; + this.mainKeySource1 = (ImmutableIntArraySource)super.mainKeySources[1]; + this.alternateKeySource1 = (ImmutableIntArraySource)super.alternateKeySources[1]; + } + + @Override + protected void clearAlternate() { + super.clearAlternate(); + this.alternateKeySource0 = null; + this.alternateKeySource1 = null; + } + + @Override + protected void migrateFront() { + int location = 0; + while (migrateOneLocation(location++)); + } + + @Override + protected void rehashInternalFull(final int oldSize) { + final int[] destKeyArray0 = new int[tableSize]; + final int[] destKeyArray1 = new int[tableSize]; + final int[] destState = new int[tableSize]; + Arrays.fill(destState, EMPTY_OUTPUT_POSITION); + final int [] originalKeyArray0 = mainKeySource0.getArray(); + mainKeySource0.setArray(destKeyArray0); + final int [] originalKeyArray1 = mainKeySource1.getArray(); + mainKeySource1.setArray(destKeyArray1); + final int [] originalStateArray = mainOutputPosition.getArray(); + mainOutputPosition.setArray(destState); + for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + continue; + } + final int k0 = originalKeyArray0[sourceBucket]; + final int k1 = originalKeyArray1[sourceBucket]; + final int hash = hash(k0, k1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; + while (true) { + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + break; + } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); + } + } + } + + @Override + public int findPositionForKey(Object key) { + final Object [] ka = (Object[])key; + final int k0 = TypeUtils.unbox((Integer)ka[0]); + final int k1 = TypeUtils.unbox((Integer)ka[1]); + int hash = hash(k0, k1); + int tableLocation = hashToTableLocation(hash); + final int firstTableLocation = tableLocation; + while (true) { + final int positionValue = mainOutputPosition.getUnsafe(tableLocation); + if (positionValue == EMPTY_OUTPUT_POSITION) { + int alternateTableLocation = hashToTableLocationAlternate(hash); + if (alternateTableLocation >= rehashPointer) { + return -1; + } + final int firstAlternateTableLocation = alternateTableLocation; + while (true) { + final int alternatePositionValue = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (alternatePositionValue == EMPTY_OUTPUT_POSITION) { + return -1; + } + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + return alternatePositionValue; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + return positionValue; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherIntLong.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherIntLong.java new file mode 100644 index 00000000000..94d7b6519f0 --- /dev/null +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherIntLong.java @@ -0,0 +1,390 @@ +// DO NOT EDIT THIS CLASS, AUTOMATICALLY GENERATED BY io.deephaven.engine.table.impl.by.typed.TypedHasherFactory +// Copyright (c) 2016-2022 Deephaven Data Labs and Patent Pending +// +package io.deephaven.engine.table.impl.by.typed.incopenagg.gen; + +import static io.deephaven.util.compare.IntComparisons.eq; +import static io.deephaven.util.compare.LongComparisons.eq; + +import io.deephaven.base.verify.Assert; +import io.deephaven.chunk.Chunk; +import io.deephaven.chunk.IntChunk; +import io.deephaven.chunk.LongChunk; +import io.deephaven.chunk.WritableIntChunk; +import io.deephaven.chunk.attributes.Values; +import io.deephaven.chunk.util.hashing.IntChunkHasher; +import io.deephaven.chunk.util.hashing.LongChunkHasher; +import io.deephaven.engine.rowset.RowSequence; +import io.deephaven.engine.rowset.chunkattributes.RowKeys; +import io.deephaven.engine.table.ColumnSource; +import io.deephaven.engine.table.impl.by.IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableIntArraySource; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableLongArraySource; +import io.deephaven.util.type.TypeUtils; +import java.lang.Integer; +import java.lang.Long; +import java.lang.Object; +import java.lang.Override; +import java.util.Arrays; + +final class IncrementalAggOpenHasherIntLong extends IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase { + private ImmutableIntArraySource mainKeySource0; + + private ImmutableIntArraySource alternateKeySource0; + + private ImmutableLongArraySource mainKeySource1; + + private ImmutableLongArraySource alternateKeySource1; + + public IncrementalAggOpenHasherIntLong(ColumnSource[] tableKeySources, int tableSize, + double maximumLoadFactor, double targetLoadFactor) { + super(tableKeySources, tableSize, maximumLoadFactor); + this.mainKeySource0 = (ImmutableIntArraySource) super.mainKeySources[0]; + this.mainKeySource0.ensureCapacity(tableSize); + this.mainKeySource1 = (ImmutableLongArraySource) super.mainKeySources[1]; + this.mainKeySource1.ensureCapacity(tableSize); + } + + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + + private int alternateNextTableLocation(int tableLocation) { + return (tableLocation + 1) & (alternateTableSize - 1); + } + + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final IntChunk keyChunk0 = sourceKeyChunks[0].asIntChunk(); + final LongChunk keyChunk1 = sourceKeyChunks[1].asLongChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final int k0 = keyChunk0.get(chunkPosition); + final long k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void buildForUpdate(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk reincarnatedPositions) { + final IntChunk keyChunk0 = sourceKeyChunks[0].asIntChunk(); + final LongChunk keyChunk1 = sourceKeyChunks[1].asLongChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final int k0 = keyChunk0.get(chunkPosition); + final long k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void doRemoveProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk emptiedPositions) { + final IntChunk keyChunk0 = sourceKeyChunks[0].asIntChunk(); + final LongChunk keyChunk1 = sourceKeyChunks[1].asLongChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final int k0 = keyChunk0.get(chunkPosition); + final long k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + protected void doModifyProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final IntChunk keyChunk0 = sourceKeyChunks[0].asIntChunk(); + final LongChunk keyChunk1 = sourceKeyChunks[1].asLongChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final int k0 = keyChunk0.get(chunkPosition); + final long k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + private static int hash(int k0, long k1) { + int hash = IntChunkHasher.hashInitialSingle(k0); + hash = LongChunkHasher.hashUpdateSingle(hash, k1); + return hash; + } + + private boolean migrateOneLocation(int locationToMigrate) { + final int currentStateValue = alternateOutputPosition.getUnsafe(locationToMigrate); + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + return false; + } + final int k0 = alternateKeySource0.getUnsafe(locationToMigrate); + final long k1 = alternateKeySource1.getUnsafe(locationToMigrate); + final int hash = hash(k0, k1); + int destinationTableLocation = hashToTableLocation(hash); + while (mainOutputPosition.getUnsafe(destinationTableLocation) != EMPTY_OUTPUT_POSITION) { + destinationTableLocation = nextTableLocation(destinationTableLocation); + } + mainKeySource0.set(destinationTableLocation, k0); + mainKeySource1.set(destinationTableLocation, k1); + mainOutputPosition.set(destinationTableLocation, currentStateValue); + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + alternateOutputPosition.set(locationToMigrate, EMPTY_OUTPUT_POSITION); + return true; + } + + @Override + protected int rehashInternalPartial(int entriesToRehash) { + int rehashedEntries = 0; + while (rehashPointer > 0 && rehashedEntries < entriesToRehash) { + if (migrateOneLocation(--rehashPointer)) { + rehashedEntries++; + } + } + return rehashedEntries; + } + + @Override + protected void newAlternate() { + super.newAlternate(); + this.mainKeySource0 = (ImmutableIntArraySource)super.mainKeySources[0]; + this.alternateKeySource0 = (ImmutableIntArraySource)super.alternateKeySources[0]; + this.mainKeySource1 = (ImmutableLongArraySource)super.mainKeySources[1]; + this.alternateKeySource1 = (ImmutableLongArraySource)super.alternateKeySources[1]; + } + + @Override + protected void clearAlternate() { + super.clearAlternate(); + this.alternateKeySource0 = null; + this.alternateKeySource1 = null; + } + + @Override + protected void migrateFront() { + int location = 0; + while (migrateOneLocation(location++)); + } + + @Override + protected void rehashInternalFull(final int oldSize) { + final int[] destKeyArray0 = new int[tableSize]; + final long[] destKeyArray1 = new long[tableSize]; + final int[] destState = new int[tableSize]; + Arrays.fill(destState, EMPTY_OUTPUT_POSITION); + final int [] originalKeyArray0 = mainKeySource0.getArray(); + mainKeySource0.setArray(destKeyArray0); + final long [] originalKeyArray1 = mainKeySource1.getArray(); + mainKeySource1.setArray(destKeyArray1); + final int [] originalStateArray = mainOutputPosition.getArray(); + mainOutputPosition.setArray(destState); + for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + continue; + } + final int k0 = originalKeyArray0[sourceBucket]; + final long k1 = originalKeyArray1[sourceBucket]; + final int hash = hash(k0, k1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; + while (true) { + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + break; + } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); + } + } + } + + @Override + public int findPositionForKey(Object key) { + final Object [] ka = (Object[])key; + final int k0 = TypeUtils.unbox((Integer)ka[0]); + final long k1 = TypeUtils.unbox((Long)ka[1]); + int hash = hash(k0, k1); + int tableLocation = hashToTableLocation(hash); + final int firstTableLocation = tableLocation; + while (true) { + final int positionValue = mainOutputPosition.getUnsafe(tableLocation); + if (positionValue == EMPTY_OUTPUT_POSITION) { + int alternateTableLocation = hashToTableLocationAlternate(hash); + if (alternateTableLocation >= rehashPointer) { + return -1; + } + final int firstAlternateTableLocation = alternateTableLocation; + while (true) { + final int alternatePositionValue = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (alternatePositionValue == EMPTY_OUTPUT_POSITION) { + return -1; + } + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + return alternatePositionValue; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + return positionValue; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherIntObject.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherIntObject.java new file mode 100644 index 00000000000..063f75f8104 --- /dev/null +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherIntObject.java @@ -0,0 +1,390 @@ +// DO NOT EDIT THIS CLASS, AUTOMATICALLY GENERATED BY io.deephaven.engine.table.impl.by.typed.TypedHasherFactory +// Copyright (c) 2016-2022 Deephaven Data Labs and Patent Pending +// +package io.deephaven.engine.table.impl.by.typed.incopenagg.gen; + +import static io.deephaven.util.compare.IntComparisons.eq; +import static io.deephaven.util.compare.ObjectComparisons.eq; + +import io.deephaven.base.verify.Assert; +import io.deephaven.chunk.Chunk; +import io.deephaven.chunk.IntChunk; +import io.deephaven.chunk.ObjectChunk; +import io.deephaven.chunk.WritableIntChunk; +import io.deephaven.chunk.attributes.Values; +import io.deephaven.chunk.util.hashing.IntChunkHasher; +import io.deephaven.chunk.util.hashing.ObjectChunkHasher; +import io.deephaven.engine.rowset.RowSequence; +import io.deephaven.engine.rowset.chunkattributes.RowKeys; +import io.deephaven.engine.table.ColumnSource; +import io.deephaven.engine.table.impl.by.IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableIntArraySource; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableObjectArraySource; +import io.deephaven.util.type.TypeUtils; +import java.lang.Integer; +import java.lang.Object; +import java.lang.Override; +import java.util.Arrays; + +final class IncrementalAggOpenHasherIntObject extends IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase { + private ImmutableIntArraySource mainKeySource0; + + private ImmutableIntArraySource alternateKeySource0; + + private ImmutableObjectArraySource mainKeySource1; + + private ImmutableObjectArraySource alternateKeySource1; + + public IncrementalAggOpenHasherIntObject(ColumnSource[] tableKeySources, int tableSize, + double maximumLoadFactor, double targetLoadFactor) { + super(tableKeySources, tableSize, maximumLoadFactor); + this.mainKeySource0 = (ImmutableIntArraySource) super.mainKeySources[0]; + this.mainKeySource0.ensureCapacity(tableSize); + this.mainKeySource1 = (ImmutableObjectArraySource) super.mainKeySources[1]; + this.mainKeySource1.ensureCapacity(tableSize); + } + + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + + private int alternateNextTableLocation(int tableLocation) { + return (tableLocation + 1) & (alternateTableSize - 1); + } + + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final IntChunk keyChunk0 = sourceKeyChunks[0].asIntChunk(); + final ObjectChunk keyChunk1 = sourceKeyChunks[1].asObjectChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final int k0 = keyChunk0.get(chunkPosition); + final Object k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void buildForUpdate(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk reincarnatedPositions) { + final IntChunk keyChunk0 = sourceKeyChunks[0].asIntChunk(); + final ObjectChunk keyChunk1 = sourceKeyChunks[1].asObjectChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final int k0 = keyChunk0.get(chunkPosition); + final Object k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void doRemoveProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk emptiedPositions) { + final IntChunk keyChunk0 = sourceKeyChunks[0].asIntChunk(); + final ObjectChunk keyChunk1 = sourceKeyChunks[1].asObjectChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final int k0 = keyChunk0.get(chunkPosition); + final Object k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + protected void doModifyProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final IntChunk keyChunk0 = sourceKeyChunks[0].asIntChunk(); + final ObjectChunk keyChunk1 = sourceKeyChunks[1].asObjectChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final int k0 = keyChunk0.get(chunkPosition); + final Object k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + private static int hash(int k0, Object k1) { + int hash = IntChunkHasher.hashInitialSingle(k0); + hash = ObjectChunkHasher.hashUpdateSingle(hash, k1); + return hash; + } + + private boolean migrateOneLocation(int locationToMigrate) { + final int currentStateValue = alternateOutputPosition.getUnsafe(locationToMigrate); + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + return false; + } + final int k0 = alternateKeySource0.getUnsafe(locationToMigrate); + final Object k1 = alternateKeySource1.getUnsafe(locationToMigrate); + final int hash = hash(k0, k1); + int destinationTableLocation = hashToTableLocation(hash); + while (mainOutputPosition.getUnsafe(destinationTableLocation) != EMPTY_OUTPUT_POSITION) { + destinationTableLocation = nextTableLocation(destinationTableLocation); + } + mainKeySource0.set(destinationTableLocation, k0); + mainKeySource1.set(destinationTableLocation, k1); + alternateKeySource1.set(locationToMigrate, null); + mainOutputPosition.set(destinationTableLocation, currentStateValue); + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + alternateOutputPosition.set(locationToMigrate, EMPTY_OUTPUT_POSITION); + return true; + } + + @Override + protected int rehashInternalPartial(int entriesToRehash) { + int rehashedEntries = 0; + while (rehashPointer > 0 && rehashedEntries < entriesToRehash) { + if (migrateOneLocation(--rehashPointer)) { + rehashedEntries++; + } + } + return rehashedEntries; + } + + @Override + protected void newAlternate() { + super.newAlternate(); + this.mainKeySource0 = (ImmutableIntArraySource)super.mainKeySources[0]; + this.alternateKeySource0 = (ImmutableIntArraySource)super.alternateKeySources[0]; + this.mainKeySource1 = (ImmutableObjectArraySource)super.mainKeySources[1]; + this.alternateKeySource1 = (ImmutableObjectArraySource)super.alternateKeySources[1]; + } + + @Override + protected void clearAlternate() { + super.clearAlternate(); + this.alternateKeySource0 = null; + this.alternateKeySource1 = null; + } + + @Override + protected void migrateFront() { + int location = 0; + while (migrateOneLocation(location++)); + } + + @Override + protected void rehashInternalFull(final int oldSize) { + final int[] destKeyArray0 = new int[tableSize]; + final Object[] destKeyArray1 = new Object[tableSize]; + final int[] destState = new int[tableSize]; + Arrays.fill(destState, EMPTY_OUTPUT_POSITION); + final int [] originalKeyArray0 = mainKeySource0.getArray(); + mainKeySource0.setArray(destKeyArray0); + final Object [] originalKeyArray1 = mainKeySource1.getArray(); + mainKeySource1.setArray(destKeyArray1); + final int [] originalStateArray = mainOutputPosition.getArray(); + mainOutputPosition.setArray(destState); + for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + continue; + } + final int k0 = originalKeyArray0[sourceBucket]; + final Object k1 = originalKeyArray1[sourceBucket]; + final int hash = hash(k0, k1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; + while (true) { + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + break; + } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); + } + } + } + + @Override + public int findPositionForKey(Object key) { + final Object [] ka = (Object[])key; + final int k0 = TypeUtils.unbox((Integer)ka[0]); + final Object k1 = ka[1]; + int hash = hash(k0, k1); + int tableLocation = hashToTableLocation(hash); + final int firstTableLocation = tableLocation; + while (true) { + final int positionValue = mainOutputPosition.getUnsafe(tableLocation); + if (positionValue == EMPTY_OUTPUT_POSITION) { + int alternateTableLocation = hashToTableLocationAlternate(hash); + if (alternateTableLocation >= rehashPointer) { + return -1; + } + final int firstAlternateTableLocation = alternateTableLocation; + while (true) { + final int alternatePositionValue = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (alternatePositionValue == EMPTY_OUTPUT_POSITION) { + return -1; + } + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + return alternatePositionValue; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + return positionValue; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherIntShort.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherIntShort.java new file mode 100644 index 00000000000..7c1caca73d9 --- /dev/null +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherIntShort.java @@ -0,0 +1,390 @@ +// DO NOT EDIT THIS CLASS, AUTOMATICALLY GENERATED BY io.deephaven.engine.table.impl.by.typed.TypedHasherFactory +// Copyright (c) 2016-2022 Deephaven Data Labs and Patent Pending +// +package io.deephaven.engine.table.impl.by.typed.incopenagg.gen; + +import static io.deephaven.util.compare.IntComparisons.eq; +import static io.deephaven.util.compare.ShortComparisons.eq; + +import io.deephaven.base.verify.Assert; +import io.deephaven.chunk.Chunk; +import io.deephaven.chunk.IntChunk; +import io.deephaven.chunk.ShortChunk; +import io.deephaven.chunk.WritableIntChunk; +import io.deephaven.chunk.attributes.Values; +import io.deephaven.chunk.util.hashing.IntChunkHasher; +import io.deephaven.chunk.util.hashing.ShortChunkHasher; +import io.deephaven.engine.rowset.RowSequence; +import io.deephaven.engine.rowset.chunkattributes.RowKeys; +import io.deephaven.engine.table.ColumnSource; +import io.deephaven.engine.table.impl.by.IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableIntArraySource; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableShortArraySource; +import io.deephaven.util.type.TypeUtils; +import java.lang.Integer; +import java.lang.Object; +import java.lang.Override; +import java.lang.Short; +import java.util.Arrays; + +final class IncrementalAggOpenHasherIntShort extends IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase { + private ImmutableIntArraySource mainKeySource0; + + private ImmutableIntArraySource alternateKeySource0; + + private ImmutableShortArraySource mainKeySource1; + + private ImmutableShortArraySource alternateKeySource1; + + public IncrementalAggOpenHasherIntShort(ColumnSource[] tableKeySources, int tableSize, + double maximumLoadFactor, double targetLoadFactor) { + super(tableKeySources, tableSize, maximumLoadFactor); + this.mainKeySource0 = (ImmutableIntArraySource) super.mainKeySources[0]; + this.mainKeySource0.ensureCapacity(tableSize); + this.mainKeySource1 = (ImmutableShortArraySource) super.mainKeySources[1]; + this.mainKeySource1.ensureCapacity(tableSize); + } + + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + + private int alternateNextTableLocation(int tableLocation) { + return (tableLocation + 1) & (alternateTableSize - 1); + } + + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final IntChunk keyChunk0 = sourceKeyChunks[0].asIntChunk(); + final ShortChunk keyChunk1 = sourceKeyChunks[1].asShortChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final int k0 = keyChunk0.get(chunkPosition); + final short k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void buildForUpdate(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk reincarnatedPositions) { + final IntChunk keyChunk0 = sourceKeyChunks[0].asIntChunk(); + final ShortChunk keyChunk1 = sourceKeyChunks[1].asShortChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final int k0 = keyChunk0.get(chunkPosition); + final short k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void doRemoveProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk emptiedPositions) { + final IntChunk keyChunk0 = sourceKeyChunks[0].asIntChunk(); + final ShortChunk keyChunk1 = sourceKeyChunks[1].asShortChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final int k0 = keyChunk0.get(chunkPosition); + final short k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + protected void doModifyProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final IntChunk keyChunk0 = sourceKeyChunks[0].asIntChunk(); + final ShortChunk keyChunk1 = sourceKeyChunks[1].asShortChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final int k0 = keyChunk0.get(chunkPosition); + final short k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + private static int hash(int k0, short k1) { + int hash = IntChunkHasher.hashInitialSingle(k0); + hash = ShortChunkHasher.hashUpdateSingle(hash, k1); + return hash; + } + + private boolean migrateOneLocation(int locationToMigrate) { + final int currentStateValue = alternateOutputPosition.getUnsafe(locationToMigrate); + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + return false; + } + final int k0 = alternateKeySource0.getUnsafe(locationToMigrate); + final short k1 = alternateKeySource1.getUnsafe(locationToMigrate); + final int hash = hash(k0, k1); + int destinationTableLocation = hashToTableLocation(hash); + while (mainOutputPosition.getUnsafe(destinationTableLocation) != EMPTY_OUTPUT_POSITION) { + destinationTableLocation = nextTableLocation(destinationTableLocation); + } + mainKeySource0.set(destinationTableLocation, k0); + mainKeySource1.set(destinationTableLocation, k1); + mainOutputPosition.set(destinationTableLocation, currentStateValue); + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + alternateOutputPosition.set(locationToMigrate, EMPTY_OUTPUT_POSITION); + return true; + } + + @Override + protected int rehashInternalPartial(int entriesToRehash) { + int rehashedEntries = 0; + while (rehashPointer > 0 && rehashedEntries < entriesToRehash) { + if (migrateOneLocation(--rehashPointer)) { + rehashedEntries++; + } + } + return rehashedEntries; + } + + @Override + protected void newAlternate() { + super.newAlternate(); + this.mainKeySource0 = (ImmutableIntArraySource)super.mainKeySources[0]; + this.alternateKeySource0 = (ImmutableIntArraySource)super.alternateKeySources[0]; + this.mainKeySource1 = (ImmutableShortArraySource)super.mainKeySources[1]; + this.alternateKeySource1 = (ImmutableShortArraySource)super.alternateKeySources[1]; + } + + @Override + protected void clearAlternate() { + super.clearAlternate(); + this.alternateKeySource0 = null; + this.alternateKeySource1 = null; + } + + @Override + protected void migrateFront() { + int location = 0; + while (migrateOneLocation(location++)); + } + + @Override + protected void rehashInternalFull(final int oldSize) { + final int[] destKeyArray0 = new int[tableSize]; + final short[] destKeyArray1 = new short[tableSize]; + final int[] destState = new int[tableSize]; + Arrays.fill(destState, EMPTY_OUTPUT_POSITION); + final int [] originalKeyArray0 = mainKeySource0.getArray(); + mainKeySource0.setArray(destKeyArray0); + final short [] originalKeyArray1 = mainKeySource1.getArray(); + mainKeySource1.setArray(destKeyArray1); + final int [] originalStateArray = mainOutputPosition.getArray(); + mainOutputPosition.setArray(destState); + for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + continue; + } + final int k0 = originalKeyArray0[sourceBucket]; + final short k1 = originalKeyArray1[sourceBucket]; + final int hash = hash(k0, k1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; + while (true) { + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + break; + } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); + } + } + } + + @Override + public int findPositionForKey(Object key) { + final Object [] ka = (Object[])key; + final int k0 = TypeUtils.unbox((Integer)ka[0]); + final short k1 = TypeUtils.unbox((Short)ka[1]); + int hash = hash(k0, k1); + int tableLocation = hashToTableLocation(hash); + final int firstTableLocation = tableLocation; + while (true) { + final int positionValue = mainOutputPosition.getUnsafe(tableLocation); + if (positionValue == EMPTY_OUTPUT_POSITION) { + int alternateTableLocation = hashToTableLocationAlternate(hash); + if (alternateTableLocation >= rehashPointer) { + return -1; + } + final int firstAlternateTableLocation = alternateTableLocation; + while (true) { + final int alternatePositionValue = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (alternatePositionValue == EMPTY_OUTPUT_POSITION) { + return -1; + } + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + return alternatePositionValue; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + return positionValue; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherLong.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherLong.java new file mode 100644 index 00000000000..bf4a659487b --- /dev/null +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherLong.java @@ -0,0 +1,356 @@ +// DO NOT EDIT THIS CLASS, AUTOMATICALLY GENERATED BY io.deephaven.engine.table.impl.by.typed.TypedHasherFactory +// Copyright (c) 2016-2022 Deephaven Data Labs and Patent Pending +// +package io.deephaven.engine.table.impl.by.typed.incopenagg.gen; + +import static io.deephaven.util.compare.LongComparisons.eq; + +import io.deephaven.base.verify.Assert; +import io.deephaven.chunk.Chunk; +import io.deephaven.chunk.LongChunk; +import io.deephaven.chunk.WritableIntChunk; +import io.deephaven.chunk.attributes.Values; +import io.deephaven.chunk.util.hashing.LongChunkHasher; +import io.deephaven.engine.rowset.RowSequence; +import io.deephaven.engine.rowset.chunkattributes.RowKeys; +import io.deephaven.engine.table.ColumnSource; +import io.deephaven.engine.table.impl.by.IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableLongArraySource; +import io.deephaven.util.type.TypeUtils; +import java.lang.Long; +import java.lang.Object; +import java.lang.Override; +import java.util.Arrays; + +final class IncrementalAggOpenHasherLong extends IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase { + private ImmutableLongArraySource mainKeySource0; + + private ImmutableLongArraySource alternateKeySource0; + + public IncrementalAggOpenHasherLong(ColumnSource[] tableKeySources, int tableSize, + double maximumLoadFactor, double targetLoadFactor) { + super(tableKeySources, tableSize, maximumLoadFactor); + this.mainKeySource0 = (ImmutableLongArraySource) super.mainKeySources[0]; + this.mainKeySource0.ensureCapacity(tableSize); + } + + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + + private int alternateNextTableLocation(int tableLocation) { + return (tableLocation + 1) & (alternateTableSize - 1); + } + + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final LongChunk keyChunk0 = sourceKeyChunks[0].asLongChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final long k0 = keyChunk0.get(chunkPosition); + final int hash = hash(k0); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void buildForUpdate(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk reincarnatedPositions) { + final LongChunk keyChunk0 = sourceKeyChunks[0].asLongChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final long k0 = keyChunk0.get(chunkPosition); + final int hash = hash(k0); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void doRemoveProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk emptiedPositions) { + final LongChunk keyChunk0 = sourceKeyChunks[0].asLongChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final long k0 = keyChunk0.get(chunkPosition); + final int hash = hash(k0); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + protected void doModifyProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final LongChunk keyChunk0 = sourceKeyChunks[0].asLongChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final long k0 = keyChunk0.get(chunkPosition); + final int hash = hash(k0); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0)) { + outputPositions.set(chunkPosition, outputPosition); + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0)) { + outputPositions.set(chunkPosition, outputPosition); + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + private static int hash(long k0) { + int hash = LongChunkHasher.hashInitialSingle(k0); + return hash; + } + + private boolean migrateOneLocation(int locationToMigrate) { + final int currentStateValue = alternateOutputPosition.getUnsafe(locationToMigrate); + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + return false; + } + final long k0 = alternateKeySource0.getUnsafe(locationToMigrate); + final int hash = hash(k0); + int destinationTableLocation = hashToTableLocation(hash); + while (mainOutputPosition.getUnsafe(destinationTableLocation) != EMPTY_OUTPUT_POSITION) { + destinationTableLocation = nextTableLocation(destinationTableLocation); + } + mainKeySource0.set(destinationTableLocation, k0); + mainOutputPosition.set(destinationTableLocation, currentStateValue); + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + alternateOutputPosition.set(locationToMigrate, EMPTY_OUTPUT_POSITION); + return true; + } + + @Override + protected int rehashInternalPartial(int entriesToRehash) { + int rehashedEntries = 0; + while (rehashPointer > 0 && rehashedEntries < entriesToRehash) { + if (migrateOneLocation(--rehashPointer)) { + rehashedEntries++; + } + } + return rehashedEntries; + } + + @Override + protected void newAlternate() { + super.newAlternate(); + this.mainKeySource0 = (ImmutableLongArraySource)super.mainKeySources[0]; + this.alternateKeySource0 = (ImmutableLongArraySource)super.alternateKeySources[0]; + } + + @Override + protected void clearAlternate() { + super.clearAlternate(); + this.alternateKeySource0 = null; + } + + @Override + protected void migrateFront() { + int location = 0; + while (migrateOneLocation(location++)); + } + + @Override + protected void rehashInternalFull(final int oldSize) { + final long[] destKeyArray0 = new long[tableSize]; + final int[] destState = new int[tableSize]; + Arrays.fill(destState, EMPTY_OUTPUT_POSITION); + final long [] originalKeyArray0 = mainKeySource0.getArray(); + mainKeySource0.setArray(destKeyArray0); + final int [] originalStateArray = mainOutputPosition.getArray(); + mainOutputPosition.setArray(destState); + for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + continue; + } + final long k0 = originalKeyArray0[sourceBucket]; + final int hash = hash(k0); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; + while (true) { + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + break; + } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); + } + } + } + + @Override + public int findPositionForKey(Object key) { + final long k0 = TypeUtils.unbox((Long)key); + int hash = hash(k0); + int tableLocation = hashToTableLocation(hash); + final int firstTableLocation = tableLocation; + while (true) { + final int positionValue = mainOutputPosition.getUnsafe(tableLocation); + if (positionValue == EMPTY_OUTPUT_POSITION) { + int alternateTableLocation = hashToTableLocationAlternate(hash); + if (alternateTableLocation >= rehashPointer) { + return -1; + } + final int firstAlternateTableLocation = alternateTableLocation; + while (true) { + final int alternatePositionValue = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (alternatePositionValue == EMPTY_OUTPUT_POSITION) { + return -1; + } + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0)) { + return alternatePositionValue; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (eq(mainKeySource0.getUnsafe(tableLocation), k0)) { + return positionValue; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherLongByte.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherLongByte.java new file mode 100644 index 00000000000..714dd1f984f --- /dev/null +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherLongByte.java @@ -0,0 +1,390 @@ +// DO NOT EDIT THIS CLASS, AUTOMATICALLY GENERATED BY io.deephaven.engine.table.impl.by.typed.TypedHasherFactory +// Copyright (c) 2016-2022 Deephaven Data Labs and Patent Pending +// +package io.deephaven.engine.table.impl.by.typed.incopenagg.gen; + +import static io.deephaven.util.compare.ByteComparisons.eq; +import static io.deephaven.util.compare.LongComparisons.eq; + +import io.deephaven.base.verify.Assert; +import io.deephaven.chunk.ByteChunk; +import io.deephaven.chunk.Chunk; +import io.deephaven.chunk.LongChunk; +import io.deephaven.chunk.WritableIntChunk; +import io.deephaven.chunk.attributes.Values; +import io.deephaven.chunk.util.hashing.ByteChunkHasher; +import io.deephaven.chunk.util.hashing.LongChunkHasher; +import io.deephaven.engine.rowset.RowSequence; +import io.deephaven.engine.rowset.chunkattributes.RowKeys; +import io.deephaven.engine.table.ColumnSource; +import io.deephaven.engine.table.impl.by.IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableByteArraySource; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableLongArraySource; +import io.deephaven.util.type.TypeUtils; +import java.lang.Byte; +import java.lang.Long; +import java.lang.Object; +import java.lang.Override; +import java.util.Arrays; + +final class IncrementalAggOpenHasherLongByte extends IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase { + private ImmutableLongArraySource mainKeySource0; + + private ImmutableLongArraySource alternateKeySource0; + + private ImmutableByteArraySource mainKeySource1; + + private ImmutableByteArraySource alternateKeySource1; + + public IncrementalAggOpenHasherLongByte(ColumnSource[] tableKeySources, int tableSize, + double maximumLoadFactor, double targetLoadFactor) { + super(tableKeySources, tableSize, maximumLoadFactor); + this.mainKeySource0 = (ImmutableLongArraySource) super.mainKeySources[0]; + this.mainKeySource0.ensureCapacity(tableSize); + this.mainKeySource1 = (ImmutableByteArraySource) super.mainKeySources[1]; + this.mainKeySource1.ensureCapacity(tableSize); + } + + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + + private int alternateNextTableLocation(int tableLocation) { + return (tableLocation + 1) & (alternateTableSize - 1); + } + + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final LongChunk keyChunk0 = sourceKeyChunks[0].asLongChunk(); + final ByteChunk keyChunk1 = sourceKeyChunks[1].asByteChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final long k0 = keyChunk0.get(chunkPosition); + final byte k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void buildForUpdate(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk reincarnatedPositions) { + final LongChunk keyChunk0 = sourceKeyChunks[0].asLongChunk(); + final ByteChunk keyChunk1 = sourceKeyChunks[1].asByteChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final long k0 = keyChunk0.get(chunkPosition); + final byte k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void doRemoveProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk emptiedPositions) { + final LongChunk keyChunk0 = sourceKeyChunks[0].asLongChunk(); + final ByteChunk keyChunk1 = sourceKeyChunks[1].asByteChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final long k0 = keyChunk0.get(chunkPosition); + final byte k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + protected void doModifyProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final LongChunk keyChunk0 = sourceKeyChunks[0].asLongChunk(); + final ByteChunk keyChunk1 = sourceKeyChunks[1].asByteChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final long k0 = keyChunk0.get(chunkPosition); + final byte k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + private static int hash(long k0, byte k1) { + int hash = LongChunkHasher.hashInitialSingle(k0); + hash = ByteChunkHasher.hashUpdateSingle(hash, k1); + return hash; + } + + private boolean migrateOneLocation(int locationToMigrate) { + final int currentStateValue = alternateOutputPosition.getUnsafe(locationToMigrate); + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + return false; + } + final long k0 = alternateKeySource0.getUnsafe(locationToMigrate); + final byte k1 = alternateKeySource1.getUnsafe(locationToMigrate); + final int hash = hash(k0, k1); + int destinationTableLocation = hashToTableLocation(hash); + while (mainOutputPosition.getUnsafe(destinationTableLocation) != EMPTY_OUTPUT_POSITION) { + destinationTableLocation = nextTableLocation(destinationTableLocation); + } + mainKeySource0.set(destinationTableLocation, k0); + mainKeySource1.set(destinationTableLocation, k1); + mainOutputPosition.set(destinationTableLocation, currentStateValue); + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + alternateOutputPosition.set(locationToMigrate, EMPTY_OUTPUT_POSITION); + return true; + } + + @Override + protected int rehashInternalPartial(int entriesToRehash) { + int rehashedEntries = 0; + while (rehashPointer > 0 && rehashedEntries < entriesToRehash) { + if (migrateOneLocation(--rehashPointer)) { + rehashedEntries++; + } + } + return rehashedEntries; + } + + @Override + protected void newAlternate() { + super.newAlternate(); + this.mainKeySource0 = (ImmutableLongArraySource)super.mainKeySources[0]; + this.alternateKeySource0 = (ImmutableLongArraySource)super.alternateKeySources[0]; + this.mainKeySource1 = (ImmutableByteArraySource)super.mainKeySources[1]; + this.alternateKeySource1 = (ImmutableByteArraySource)super.alternateKeySources[1]; + } + + @Override + protected void clearAlternate() { + super.clearAlternate(); + this.alternateKeySource0 = null; + this.alternateKeySource1 = null; + } + + @Override + protected void migrateFront() { + int location = 0; + while (migrateOneLocation(location++)); + } + + @Override + protected void rehashInternalFull(final int oldSize) { + final long[] destKeyArray0 = new long[tableSize]; + final byte[] destKeyArray1 = new byte[tableSize]; + final int[] destState = new int[tableSize]; + Arrays.fill(destState, EMPTY_OUTPUT_POSITION); + final long [] originalKeyArray0 = mainKeySource0.getArray(); + mainKeySource0.setArray(destKeyArray0); + final byte [] originalKeyArray1 = mainKeySource1.getArray(); + mainKeySource1.setArray(destKeyArray1); + final int [] originalStateArray = mainOutputPosition.getArray(); + mainOutputPosition.setArray(destState); + for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + continue; + } + final long k0 = originalKeyArray0[sourceBucket]; + final byte k1 = originalKeyArray1[sourceBucket]; + final int hash = hash(k0, k1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; + while (true) { + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + break; + } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); + } + } + } + + @Override + public int findPositionForKey(Object key) { + final Object [] ka = (Object[])key; + final long k0 = TypeUtils.unbox((Long)ka[0]); + final byte k1 = TypeUtils.unbox((Byte)ka[1]); + int hash = hash(k0, k1); + int tableLocation = hashToTableLocation(hash); + final int firstTableLocation = tableLocation; + while (true) { + final int positionValue = mainOutputPosition.getUnsafe(tableLocation); + if (positionValue == EMPTY_OUTPUT_POSITION) { + int alternateTableLocation = hashToTableLocationAlternate(hash); + if (alternateTableLocation >= rehashPointer) { + return -1; + } + final int firstAlternateTableLocation = alternateTableLocation; + while (true) { + final int alternatePositionValue = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (alternatePositionValue == EMPTY_OUTPUT_POSITION) { + return -1; + } + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + return alternatePositionValue; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + return positionValue; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherLongChar.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherLongChar.java new file mode 100644 index 00000000000..bb05616bdc9 --- /dev/null +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherLongChar.java @@ -0,0 +1,390 @@ +// DO NOT EDIT THIS CLASS, AUTOMATICALLY GENERATED BY io.deephaven.engine.table.impl.by.typed.TypedHasherFactory +// Copyright (c) 2016-2022 Deephaven Data Labs and Patent Pending +// +package io.deephaven.engine.table.impl.by.typed.incopenagg.gen; + +import static io.deephaven.util.compare.CharComparisons.eq; +import static io.deephaven.util.compare.LongComparisons.eq; + +import io.deephaven.base.verify.Assert; +import io.deephaven.chunk.CharChunk; +import io.deephaven.chunk.Chunk; +import io.deephaven.chunk.LongChunk; +import io.deephaven.chunk.WritableIntChunk; +import io.deephaven.chunk.attributes.Values; +import io.deephaven.chunk.util.hashing.CharChunkHasher; +import io.deephaven.chunk.util.hashing.LongChunkHasher; +import io.deephaven.engine.rowset.RowSequence; +import io.deephaven.engine.rowset.chunkattributes.RowKeys; +import io.deephaven.engine.table.ColumnSource; +import io.deephaven.engine.table.impl.by.IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableCharArraySource; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableLongArraySource; +import io.deephaven.util.type.TypeUtils; +import java.lang.Character; +import java.lang.Long; +import java.lang.Object; +import java.lang.Override; +import java.util.Arrays; + +final class IncrementalAggOpenHasherLongChar extends IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase { + private ImmutableLongArraySource mainKeySource0; + + private ImmutableLongArraySource alternateKeySource0; + + private ImmutableCharArraySource mainKeySource1; + + private ImmutableCharArraySource alternateKeySource1; + + public IncrementalAggOpenHasherLongChar(ColumnSource[] tableKeySources, int tableSize, + double maximumLoadFactor, double targetLoadFactor) { + super(tableKeySources, tableSize, maximumLoadFactor); + this.mainKeySource0 = (ImmutableLongArraySource) super.mainKeySources[0]; + this.mainKeySource0.ensureCapacity(tableSize); + this.mainKeySource1 = (ImmutableCharArraySource) super.mainKeySources[1]; + this.mainKeySource1.ensureCapacity(tableSize); + } + + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + + private int alternateNextTableLocation(int tableLocation) { + return (tableLocation + 1) & (alternateTableSize - 1); + } + + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final LongChunk keyChunk0 = sourceKeyChunks[0].asLongChunk(); + final CharChunk keyChunk1 = sourceKeyChunks[1].asCharChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final long k0 = keyChunk0.get(chunkPosition); + final char k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void buildForUpdate(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk reincarnatedPositions) { + final LongChunk keyChunk0 = sourceKeyChunks[0].asLongChunk(); + final CharChunk keyChunk1 = sourceKeyChunks[1].asCharChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final long k0 = keyChunk0.get(chunkPosition); + final char k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void doRemoveProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk emptiedPositions) { + final LongChunk keyChunk0 = sourceKeyChunks[0].asLongChunk(); + final CharChunk keyChunk1 = sourceKeyChunks[1].asCharChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final long k0 = keyChunk0.get(chunkPosition); + final char k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + protected void doModifyProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final LongChunk keyChunk0 = sourceKeyChunks[0].asLongChunk(); + final CharChunk keyChunk1 = sourceKeyChunks[1].asCharChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final long k0 = keyChunk0.get(chunkPosition); + final char k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + private static int hash(long k0, char k1) { + int hash = LongChunkHasher.hashInitialSingle(k0); + hash = CharChunkHasher.hashUpdateSingle(hash, k1); + return hash; + } + + private boolean migrateOneLocation(int locationToMigrate) { + final int currentStateValue = alternateOutputPosition.getUnsafe(locationToMigrate); + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + return false; + } + final long k0 = alternateKeySource0.getUnsafe(locationToMigrate); + final char k1 = alternateKeySource1.getUnsafe(locationToMigrate); + final int hash = hash(k0, k1); + int destinationTableLocation = hashToTableLocation(hash); + while (mainOutputPosition.getUnsafe(destinationTableLocation) != EMPTY_OUTPUT_POSITION) { + destinationTableLocation = nextTableLocation(destinationTableLocation); + } + mainKeySource0.set(destinationTableLocation, k0); + mainKeySource1.set(destinationTableLocation, k1); + mainOutputPosition.set(destinationTableLocation, currentStateValue); + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + alternateOutputPosition.set(locationToMigrate, EMPTY_OUTPUT_POSITION); + return true; + } + + @Override + protected int rehashInternalPartial(int entriesToRehash) { + int rehashedEntries = 0; + while (rehashPointer > 0 && rehashedEntries < entriesToRehash) { + if (migrateOneLocation(--rehashPointer)) { + rehashedEntries++; + } + } + return rehashedEntries; + } + + @Override + protected void newAlternate() { + super.newAlternate(); + this.mainKeySource0 = (ImmutableLongArraySource)super.mainKeySources[0]; + this.alternateKeySource0 = (ImmutableLongArraySource)super.alternateKeySources[0]; + this.mainKeySource1 = (ImmutableCharArraySource)super.mainKeySources[1]; + this.alternateKeySource1 = (ImmutableCharArraySource)super.alternateKeySources[1]; + } + + @Override + protected void clearAlternate() { + super.clearAlternate(); + this.alternateKeySource0 = null; + this.alternateKeySource1 = null; + } + + @Override + protected void migrateFront() { + int location = 0; + while (migrateOneLocation(location++)); + } + + @Override + protected void rehashInternalFull(final int oldSize) { + final long[] destKeyArray0 = new long[tableSize]; + final char[] destKeyArray1 = new char[tableSize]; + final int[] destState = new int[tableSize]; + Arrays.fill(destState, EMPTY_OUTPUT_POSITION); + final long [] originalKeyArray0 = mainKeySource0.getArray(); + mainKeySource0.setArray(destKeyArray0); + final char [] originalKeyArray1 = mainKeySource1.getArray(); + mainKeySource1.setArray(destKeyArray1); + final int [] originalStateArray = mainOutputPosition.getArray(); + mainOutputPosition.setArray(destState); + for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + continue; + } + final long k0 = originalKeyArray0[sourceBucket]; + final char k1 = originalKeyArray1[sourceBucket]; + final int hash = hash(k0, k1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; + while (true) { + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + break; + } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); + } + } + } + + @Override + public int findPositionForKey(Object key) { + final Object [] ka = (Object[])key; + final long k0 = TypeUtils.unbox((Long)ka[0]); + final char k1 = TypeUtils.unbox((Character)ka[1]); + int hash = hash(k0, k1); + int tableLocation = hashToTableLocation(hash); + final int firstTableLocation = tableLocation; + while (true) { + final int positionValue = mainOutputPosition.getUnsafe(tableLocation); + if (positionValue == EMPTY_OUTPUT_POSITION) { + int alternateTableLocation = hashToTableLocationAlternate(hash); + if (alternateTableLocation >= rehashPointer) { + return -1; + } + final int firstAlternateTableLocation = alternateTableLocation; + while (true) { + final int alternatePositionValue = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (alternatePositionValue == EMPTY_OUTPUT_POSITION) { + return -1; + } + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + return alternatePositionValue; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + return positionValue; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherLongDouble.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherLongDouble.java new file mode 100644 index 00000000000..901fea4b71d --- /dev/null +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherLongDouble.java @@ -0,0 +1,390 @@ +// DO NOT EDIT THIS CLASS, AUTOMATICALLY GENERATED BY io.deephaven.engine.table.impl.by.typed.TypedHasherFactory +// Copyright (c) 2016-2022 Deephaven Data Labs and Patent Pending +// +package io.deephaven.engine.table.impl.by.typed.incopenagg.gen; + +import static io.deephaven.util.compare.DoubleComparisons.eq; +import static io.deephaven.util.compare.LongComparisons.eq; + +import io.deephaven.base.verify.Assert; +import io.deephaven.chunk.Chunk; +import io.deephaven.chunk.DoubleChunk; +import io.deephaven.chunk.LongChunk; +import io.deephaven.chunk.WritableIntChunk; +import io.deephaven.chunk.attributes.Values; +import io.deephaven.chunk.util.hashing.DoubleChunkHasher; +import io.deephaven.chunk.util.hashing.LongChunkHasher; +import io.deephaven.engine.rowset.RowSequence; +import io.deephaven.engine.rowset.chunkattributes.RowKeys; +import io.deephaven.engine.table.ColumnSource; +import io.deephaven.engine.table.impl.by.IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableDoubleArraySource; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableLongArraySource; +import io.deephaven.util.type.TypeUtils; +import java.lang.Double; +import java.lang.Long; +import java.lang.Object; +import java.lang.Override; +import java.util.Arrays; + +final class IncrementalAggOpenHasherLongDouble extends IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase { + private ImmutableLongArraySource mainKeySource0; + + private ImmutableLongArraySource alternateKeySource0; + + private ImmutableDoubleArraySource mainKeySource1; + + private ImmutableDoubleArraySource alternateKeySource1; + + public IncrementalAggOpenHasherLongDouble(ColumnSource[] tableKeySources, int tableSize, + double maximumLoadFactor, double targetLoadFactor) { + super(tableKeySources, tableSize, maximumLoadFactor); + this.mainKeySource0 = (ImmutableLongArraySource) super.mainKeySources[0]; + this.mainKeySource0.ensureCapacity(tableSize); + this.mainKeySource1 = (ImmutableDoubleArraySource) super.mainKeySources[1]; + this.mainKeySource1.ensureCapacity(tableSize); + } + + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + + private int alternateNextTableLocation(int tableLocation) { + return (tableLocation + 1) & (alternateTableSize - 1); + } + + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final LongChunk keyChunk0 = sourceKeyChunks[0].asLongChunk(); + final DoubleChunk keyChunk1 = sourceKeyChunks[1].asDoubleChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final long k0 = keyChunk0.get(chunkPosition); + final double k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void buildForUpdate(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk reincarnatedPositions) { + final LongChunk keyChunk0 = sourceKeyChunks[0].asLongChunk(); + final DoubleChunk keyChunk1 = sourceKeyChunks[1].asDoubleChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final long k0 = keyChunk0.get(chunkPosition); + final double k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void doRemoveProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk emptiedPositions) { + final LongChunk keyChunk0 = sourceKeyChunks[0].asLongChunk(); + final DoubleChunk keyChunk1 = sourceKeyChunks[1].asDoubleChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final long k0 = keyChunk0.get(chunkPosition); + final double k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + protected void doModifyProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final LongChunk keyChunk0 = sourceKeyChunks[0].asLongChunk(); + final DoubleChunk keyChunk1 = sourceKeyChunks[1].asDoubleChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final long k0 = keyChunk0.get(chunkPosition); + final double k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + private static int hash(long k0, double k1) { + int hash = LongChunkHasher.hashInitialSingle(k0); + hash = DoubleChunkHasher.hashUpdateSingle(hash, k1); + return hash; + } + + private boolean migrateOneLocation(int locationToMigrate) { + final int currentStateValue = alternateOutputPosition.getUnsafe(locationToMigrate); + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + return false; + } + final long k0 = alternateKeySource0.getUnsafe(locationToMigrate); + final double k1 = alternateKeySource1.getUnsafe(locationToMigrate); + final int hash = hash(k0, k1); + int destinationTableLocation = hashToTableLocation(hash); + while (mainOutputPosition.getUnsafe(destinationTableLocation) != EMPTY_OUTPUT_POSITION) { + destinationTableLocation = nextTableLocation(destinationTableLocation); + } + mainKeySource0.set(destinationTableLocation, k0); + mainKeySource1.set(destinationTableLocation, k1); + mainOutputPosition.set(destinationTableLocation, currentStateValue); + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + alternateOutputPosition.set(locationToMigrate, EMPTY_OUTPUT_POSITION); + return true; + } + + @Override + protected int rehashInternalPartial(int entriesToRehash) { + int rehashedEntries = 0; + while (rehashPointer > 0 && rehashedEntries < entriesToRehash) { + if (migrateOneLocation(--rehashPointer)) { + rehashedEntries++; + } + } + return rehashedEntries; + } + + @Override + protected void newAlternate() { + super.newAlternate(); + this.mainKeySource0 = (ImmutableLongArraySource)super.mainKeySources[0]; + this.alternateKeySource0 = (ImmutableLongArraySource)super.alternateKeySources[0]; + this.mainKeySource1 = (ImmutableDoubleArraySource)super.mainKeySources[1]; + this.alternateKeySource1 = (ImmutableDoubleArraySource)super.alternateKeySources[1]; + } + + @Override + protected void clearAlternate() { + super.clearAlternate(); + this.alternateKeySource0 = null; + this.alternateKeySource1 = null; + } + + @Override + protected void migrateFront() { + int location = 0; + while (migrateOneLocation(location++)); + } + + @Override + protected void rehashInternalFull(final int oldSize) { + final long[] destKeyArray0 = new long[tableSize]; + final double[] destKeyArray1 = new double[tableSize]; + final int[] destState = new int[tableSize]; + Arrays.fill(destState, EMPTY_OUTPUT_POSITION); + final long [] originalKeyArray0 = mainKeySource0.getArray(); + mainKeySource0.setArray(destKeyArray0); + final double [] originalKeyArray1 = mainKeySource1.getArray(); + mainKeySource1.setArray(destKeyArray1); + final int [] originalStateArray = mainOutputPosition.getArray(); + mainOutputPosition.setArray(destState); + for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + continue; + } + final long k0 = originalKeyArray0[sourceBucket]; + final double k1 = originalKeyArray1[sourceBucket]; + final int hash = hash(k0, k1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; + while (true) { + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + break; + } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); + } + } + } + + @Override + public int findPositionForKey(Object key) { + final Object [] ka = (Object[])key; + final long k0 = TypeUtils.unbox((Long)ka[0]); + final double k1 = TypeUtils.unbox((Double)ka[1]); + int hash = hash(k0, k1); + int tableLocation = hashToTableLocation(hash); + final int firstTableLocation = tableLocation; + while (true) { + final int positionValue = mainOutputPosition.getUnsafe(tableLocation); + if (positionValue == EMPTY_OUTPUT_POSITION) { + int alternateTableLocation = hashToTableLocationAlternate(hash); + if (alternateTableLocation >= rehashPointer) { + return -1; + } + final int firstAlternateTableLocation = alternateTableLocation; + while (true) { + final int alternatePositionValue = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (alternatePositionValue == EMPTY_OUTPUT_POSITION) { + return -1; + } + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + return alternatePositionValue; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + return positionValue; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherLongFloat.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherLongFloat.java new file mode 100644 index 00000000000..30efd4efdb1 --- /dev/null +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherLongFloat.java @@ -0,0 +1,390 @@ +// DO NOT EDIT THIS CLASS, AUTOMATICALLY GENERATED BY io.deephaven.engine.table.impl.by.typed.TypedHasherFactory +// Copyright (c) 2016-2022 Deephaven Data Labs and Patent Pending +// +package io.deephaven.engine.table.impl.by.typed.incopenagg.gen; + +import static io.deephaven.util.compare.FloatComparisons.eq; +import static io.deephaven.util.compare.LongComparisons.eq; + +import io.deephaven.base.verify.Assert; +import io.deephaven.chunk.Chunk; +import io.deephaven.chunk.FloatChunk; +import io.deephaven.chunk.LongChunk; +import io.deephaven.chunk.WritableIntChunk; +import io.deephaven.chunk.attributes.Values; +import io.deephaven.chunk.util.hashing.FloatChunkHasher; +import io.deephaven.chunk.util.hashing.LongChunkHasher; +import io.deephaven.engine.rowset.RowSequence; +import io.deephaven.engine.rowset.chunkattributes.RowKeys; +import io.deephaven.engine.table.ColumnSource; +import io.deephaven.engine.table.impl.by.IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableFloatArraySource; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableLongArraySource; +import io.deephaven.util.type.TypeUtils; +import java.lang.Float; +import java.lang.Long; +import java.lang.Object; +import java.lang.Override; +import java.util.Arrays; + +final class IncrementalAggOpenHasherLongFloat extends IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase { + private ImmutableLongArraySource mainKeySource0; + + private ImmutableLongArraySource alternateKeySource0; + + private ImmutableFloatArraySource mainKeySource1; + + private ImmutableFloatArraySource alternateKeySource1; + + public IncrementalAggOpenHasherLongFloat(ColumnSource[] tableKeySources, int tableSize, + double maximumLoadFactor, double targetLoadFactor) { + super(tableKeySources, tableSize, maximumLoadFactor); + this.mainKeySource0 = (ImmutableLongArraySource) super.mainKeySources[0]; + this.mainKeySource0.ensureCapacity(tableSize); + this.mainKeySource1 = (ImmutableFloatArraySource) super.mainKeySources[1]; + this.mainKeySource1.ensureCapacity(tableSize); + } + + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + + private int alternateNextTableLocation(int tableLocation) { + return (tableLocation + 1) & (alternateTableSize - 1); + } + + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final LongChunk keyChunk0 = sourceKeyChunks[0].asLongChunk(); + final FloatChunk keyChunk1 = sourceKeyChunks[1].asFloatChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final long k0 = keyChunk0.get(chunkPosition); + final float k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void buildForUpdate(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk reincarnatedPositions) { + final LongChunk keyChunk0 = sourceKeyChunks[0].asLongChunk(); + final FloatChunk keyChunk1 = sourceKeyChunks[1].asFloatChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final long k0 = keyChunk0.get(chunkPosition); + final float k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void doRemoveProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk emptiedPositions) { + final LongChunk keyChunk0 = sourceKeyChunks[0].asLongChunk(); + final FloatChunk keyChunk1 = sourceKeyChunks[1].asFloatChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final long k0 = keyChunk0.get(chunkPosition); + final float k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + protected void doModifyProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final LongChunk keyChunk0 = sourceKeyChunks[0].asLongChunk(); + final FloatChunk keyChunk1 = sourceKeyChunks[1].asFloatChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final long k0 = keyChunk0.get(chunkPosition); + final float k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + private static int hash(long k0, float k1) { + int hash = LongChunkHasher.hashInitialSingle(k0); + hash = FloatChunkHasher.hashUpdateSingle(hash, k1); + return hash; + } + + private boolean migrateOneLocation(int locationToMigrate) { + final int currentStateValue = alternateOutputPosition.getUnsafe(locationToMigrate); + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + return false; + } + final long k0 = alternateKeySource0.getUnsafe(locationToMigrate); + final float k1 = alternateKeySource1.getUnsafe(locationToMigrate); + final int hash = hash(k0, k1); + int destinationTableLocation = hashToTableLocation(hash); + while (mainOutputPosition.getUnsafe(destinationTableLocation) != EMPTY_OUTPUT_POSITION) { + destinationTableLocation = nextTableLocation(destinationTableLocation); + } + mainKeySource0.set(destinationTableLocation, k0); + mainKeySource1.set(destinationTableLocation, k1); + mainOutputPosition.set(destinationTableLocation, currentStateValue); + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + alternateOutputPosition.set(locationToMigrate, EMPTY_OUTPUT_POSITION); + return true; + } + + @Override + protected int rehashInternalPartial(int entriesToRehash) { + int rehashedEntries = 0; + while (rehashPointer > 0 && rehashedEntries < entriesToRehash) { + if (migrateOneLocation(--rehashPointer)) { + rehashedEntries++; + } + } + return rehashedEntries; + } + + @Override + protected void newAlternate() { + super.newAlternate(); + this.mainKeySource0 = (ImmutableLongArraySource)super.mainKeySources[0]; + this.alternateKeySource0 = (ImmutableLongArraySource)super.alternateKeySources[0]; + this.mainKeySource1 = (ImmutableFloatArraySource)super.mainKeySources[1]; + this.alternateKeySource1 = (ImmutableFloatArraySource)super.alternateKeySources[1]; + } + + @Override + protected void clearAlternate() { + super.clearAlternate(); + this.alternateKeySource0 = null; + this.alternateKeySource1 = null; + } + + @Override + protected void migrateFront() { + int location = 0; + while (migrateOneLocation(location++)); + } + + @Override + protected void rehashInternalFull(final int oldSize) { + final long[] destKeyArray0 = new long[tableSize]; + final float[] destKeyArray1 = new float[tableSize]; + final int[] destState = new int[tableSize]; + Arrays.fill(destState, EMPTY_OUTPUT_POSITION); + final long [] originalKeyArray0 = mainKeySource0.getArray(); + mainKeySource0.setArray(destKeyArray0); + final float [] originalKeyArray1 = mainKeySource1.getArray(); + mainKeySource1.setArray(destKeyArray1); + final int [] originalStateArray = mainOutputPosition.getArray(); + mainOutputPosition.setArray(destState); + for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + continue; + } + final long k0 = originalKeyArray0[sourceBucket]; + final float k1 = originalKeyArray1[sourceBucket]; + final int hash = hash(k0, k1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; + while (true) { + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + break; + } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); + } + } + } + + @Override + public int findPositionForKey(Object key) { + final Object [] ka = (Object[])key; + final long k0 = TypeUtils.unbox((Long)ka[0]); + final float k1 = TypeUtils.unbox((Float)ka[1]); + int hash = hash(k0, k1); + int tableLocation = hashToTableLocation(hash); + final int firstTableLocation = tableLocation; + while (true) { + final int positionValue = mainOutputPosition.getUnsafe(tableLocation); + if (positionValue == EMPTY_OUTPUT_POSITION) { + int alternateTableLocation = hashToTableLocationAlternate(hash); + if (alternateTableLocation >= rehashPointer) { + return -1; + } + final int firstAlternateTableLocation = alternateTableLocation; + while (true) { + final int alternatePositionValue = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (alternatePositionValue == EMPTY_OUTPUT_POSITION) { + return -1; + } + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + return alternatePositionValue; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + return positionValue; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherLongInt.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherLongInt.java new file mode 100644 index 00000000000..b3030733c0d --- /dev/null +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherLongInt.java @@ -0,0 +1,390 @@ +// DO NOT EDIT THIS CLASS, AUTOMATICALLY GENERATED BY io.deephaven.engine.table.impl.by.typed.TypedHasherFactory +// Copyright (c) 2016-2022 Deephaven Data Labs and Patent Pending +// +package io.deephaven.engine.table.impl.by.typed.incopenagg.gen; + +import static io.deephaven.util.compare.IntComparisons.eq; +import static io.deephaven.util.compare.LongComparisons.eq; + +import io.deephaven.base.verify.Assert; +import io.deephaven.chunk.Chunk; +import io.deephaven.chunk.IntChunk; +import io.deephaven.chunk.LongChunk; +import io.deephaven.chunk.WritableIntChunk; +import io.deephaven.chunk.attributes.Values; +import io.deephaven.chunk.util.hashing.IntChunkHasher; +import io.deephaven.chunk.util.hashing.LongChunkHasher; +import io.deephaven.engine.rowset.RowSequence; +import io.deephaven.engine.rowset.chunkattributes.RowKeys; +import io.deephaven.engine.table.ColumnSource; +import io.deephaven.engine.table.impl.by.IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableIntArraySource; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableLongArraySource; +import io.deephaven.util.type.TypeUtils; +import java.lang.Integer; +import java.lang.Long; +import java.lang.Object; +import java.lang.Override; +import java.util.Arrays; + +final class IncrementalAggOpenHasherLongInt extends IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase { + private ImmutableLongArraySource mainKeySource0; + + private ImmutableLongArraySource alternateKeySource0; + + private ImmutableIntArraySource mainKeySource1; + + private ImmutableIntArraySource alternateKeySource1; + + public IncrementalAggOpenHasherLongInt(ColumnSource[] tableKeySources, int tableSize, + double maximumLoadFactor, double targetLoadFactor) { + super(tableKeySources, tableSize, maximumLoadFactor); + this.mainKeySource0 = (ImmutableLongArraySource) super.mainKeySources[0]; + this.mainKeySource0.ensureCapacity(tableSize); + this.mainKeySource1 = (ImmutableIntArraySource) super.mainKeySources[1]; + this.mainKeySource1.ensureCapacity(tableSize); + } + + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + + private int alternateNextTableLocation(int tableLocation) { + return (tableLocation + 1) & (alternateTableSize - 1); + } + + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final LongChunk keyChunk0 = sourceKeyChunks[0].asLongChunk(); + final IntChunk keyChunk1 = sourceKeyChunks[1].asIntChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final long k0 = keyChunk0.get(chunkPosition); + final int k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void buildForUpdate(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk reincarnatedPositions) { + final LongChunk keyChunk0 = sourceKeyChunks[0].asLongChunk(); + final IntChunk keyChunk1 = sourceKeyChunks[1].asIntChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final long k0 = keyChunk0.get(chunkPosition); + final int k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void doRemoveProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk emptiedPositions) { + final LongChunk keyChunk0 = sourceKeyChunks[0].asLongChunk(); + final IntChunk keyChunk1 = sourceKeyChunks[1].asIntChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final long k0 = keyChunk0.get(chunkPosition); + final int k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + protected void doModifyProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final LongChunk keyChunk0 = sourceKeyChunks[0].asLongChunk(); + final IntChunk keyChunk1 = sourceKeyChunks[1].asIntChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final long k0 = keyChunk0.get(chunkPosition); + final int k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + private static int hash(long k0, int k1) { + int hash = LongChunkHasher.hashInitialSingle(k0); + hash = IntChunkHasher.hashUpdateSingle(hash, k1); + return hash; + } + + private boolean migrateOneLocation(int locationToMigrate) { + final int currentStateValue = alternateOutputPosition.getUnsafe(locationToMigrate); + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + return false; + } + final long k0 = alternateKeySource0.getUnsafe(locationToMigrate); + final int k1 = alternateKeySource1.getUnsafe(locationToMigrate); + final int hash = hash(k0, k1); + int destinationTableLocation = hashToTableLocation(hash); + while (mainOutputPosition.getUnsafe(destinationTableLocation) != EMPTY_OUTPUT_POSITION) { + destinationTableLocation = nextTableLocation(destinationTableLocation); + } + mainKeySource0.set(destinationTableLocation, k0); + mainKeySource1.set(destinationTableLocation, k1); + mainOutputPosition.set(destinationTableLocation, currentStateValue); + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + alternateOutputPosition.set(locationToMigrate, EMPTY_OUTPUT_POSITION); + return true; + } + + @Override + protected int rehashInternalPartial(int entriesToRehash) { + int rehashedEntries = 0; + while (rehashPointer > 0 && rehashedEntries < entriesToRehash) { + if (migrateOneLocation(--rehashPointer)) { + rehashedEntries++; + } + } + return rehashedEntries; + } + + @Override + protected void newAlternate() { + super.newAlternate(); + this.mainKeySource0 = (ImmutableLongArraySource)super.mainKeySources[0]; + this.alternateKeySource0 = (ImmutableLongArraySource)super.alternateKeySources[0]; + this.mainKeySource1 = (ImmutableIntArraySource)super.mainKeySources[1]; + this.alternateKeySource1 = (ImmutableIntArraySource)super.alternateKeySources[1]; + } + + @Override + protected void clearAlternate() { + super.clearAlternate(); + this.alternateKeySource0 = null; + this.alternateKeySource1 = null; + } + + @Override + protected void migrateFront() { + int location = 0; + while (migrateOneLocation(location++)); + } + + @Override + protected void rehashInternalFull(final int oldSize) { + final long[] destKeyArray0 = new long[tableSize]; + final int[] destKeyArray1 = new int[tableSize]; + final int[] destState = new int[tableSize]; + Arrays.fill(destState, EMPTY_OUTPUT_POSITION); + final long [] originalKeyArray0 = mainKeySource0.getArray(); + mainKeySource0.setArray(destKeyArray0); + final int [] originalKeyArray1 = mainKeySource1.getArray(); + mainKeySource1.setArray(destKeyArray1); + final int [] originalStateArray = mainOutputPosition.getArray(); + mainOutputPosition.setArray(destState); + for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + continue; + } + final long k0 = originalKeyArray0[sourceBucket]; + final int k1 = originalKeyArray1[sourceBucket]; + final int hash = hash(k0, k1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; + while (true) { + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + break; + } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); + } + } + } + + @Override + public int findPositionForKey(Object key) { + final Object [] ka = (Object[])key; + final long k0 = TypeUtils.unbox((Long)ka[0]); + final int k1 = TypeUtils.unbox((Integer)ka[1]); + int hash = hash(k0, k1); + int tableLocation = hashToTableLocation(hash); + final int firstTableLocation = tableLocation; + while (true) { + final int positionValue = mainOutputPosition.getUnsafe(tableLocation); + if (positionValue == EMPTY_OUTPUT_POSITION) { + int alternateTableLocation = hashToTableLocationAlternate(hash); + if (alternateTableLocation >= rehashPointer) { + return -1; + } + final int firstAlternateTableLocation = alternateTableLocation; + while (true) { + final int alternatePositionValue = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (alternatePositionValue == EMPTY_OUTPUT_POSITION) { + return -1; + } + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + return alternatePositionValue; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + return positionValue; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherLongLong.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherLongLong.java new file mode 100644 index 00000000000..838310f5893 --- /dev/null +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherLongLong.java @@ -0,0 +1,385 @@ +// DO NOT EDIT THIS CLASS, AUTOMATICALLY GENERATED BY io.deephaven.engine.table.impl.by.typed.TypedHasherFactory +// Copyright (c) 2016-2022 Deephaven Data Labs and Patent Pending +// +package io.deephaven.engine.table.impl.by.typed.incopenagg.gen; + +import static io.deephaven.util.compare.LongComparisons.eq; + +import io.deephaven.base.verify.Assert; +import io.deephaven.chunk.Chunk; +import io.deephaven.chunk.LongChunk; +import io.deephaven.chunk.WritableIntChunk; +import io.deephaven.chunk.attributes.Values; +import io.deephaven.chunk.util.hashing.LongChunkHasher; +import io.deephaven.engine.rowset.RowSequence; +import io.deephaven.engine.rowset.chunkattributes.RowKeys; +import io.deephaven.engine.table.ColumnSource; +import io.deephaven.engine.table.impl.by.IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableLongArraySource; +import io.deephaven.util.type.TypeUtils; +import java.lang.Long; +import java.lang.Object; +import java.lang.Override; +import java.util.Arrays; + +final class IncrementalAggOpenHasherLongLong extends IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase { + private ImmutableLongArraySource mainKeySource0; + + private ImmutableLongArraySource alternateKeySource0; + + private ImmutableLongArraySource mainKeySource1; + + private ImmutableLongArraySource alternateKeySource1; + + public IncrementalAggOpenHasherLongLong(ColumnSource[] tableKeySources, int tableSize, + double maximumLoadFactor, double targetLoadFactor) { + super(tableKeySources, tableSize, maximumLoadFactor); + this.mainKeySource0 = (ImmutableLongArraySource) super.mainKeySources[0]; + this.mainKeySource0.ensureCapacity(tableSize); + this.mainKeySource1 = (ImmutableLongArraySource) super.mainKeySources[1]; + this.mainKeySource1.ensureCapacity(tableSize); + } + + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + + private int alternateNextTableLocation(int tableLocation) { + return (tableLocation + 1) & (alternateTableSize - 1); + } + + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final LongChunk keyChunk0 = sourceKeyChunks[0].asLongChunk(); + final LongChunk keyChunk1 = sourceKeyChunks[1].asLongChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final long k0 = keyChunk0.get(chunkPosition); + final long k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void buildForUpdate(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk reincarnatedPositions) { + final LongChunk keyChunk0 = sourceKeyChunks[0].asLongChunk(); + final LongChunk keyChunk1 = sourceKeyChunks[1].asLongChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final long k0 = keyChunk0.get(chunkPosition); + final long k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void doRemoveProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk emptiedPositions) { + final LongChunk keyChunk0 = sourceKeyChunks[0].asLongChunk(); + final LongChunk keyChunk1 = sourceKeyChunks[1].asLongChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final long k0 = keyChunk0.get(chunkPosition); + final long k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + protected void doModifyProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final LongChunk keyChunk0 = sourceKeyChunks[0].asLongChunk(); + final LongChunk keyChunk1 = sourceKeyChunks[1].asLongChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final long k0 = keyChunk0.get(chunkPosition); + final long k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + private static int hash(long k0, long k1) { + int hash = LongChunkHasher.hashInitialSingle(k0); + hash = LongChunkHasher.hashUpdateSingle(hash, k1); + return hash; + } + + private boolean migrateOneLocation(int locationToMigrate) { + final int currentStateValue = alternateOutputPosition.getUnsafe(locationToMigrate); + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + return false; + } + final long k0 = alternateKeySource0.getUnsafe(locationToMigrate); + final long k1 = alternateKeySource1.getUnsafe(locationToMigrate); + final int hash = hash(k0, k1); + int destinationTableLocation = hashToTableLocation(hash); + while (mainOutputPosition.getUnsafe(destinationTableLocation) != EMPTY_OUTPUT_POSITION) { + destinationTableLocation = nextTableLocation(destinationTableLocation); + } + mainKeySource0.set(destinationTableLocation, k0); + mainKeySource1.set(destinationTableLocation, k1); + mainOutputPosition.set(destinationTableLocation, currentStateValue); + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + alternateOutputPosition.set(locationToMigrate, EMPTY_OUTPUT_POSITION); + return true; + } + + @Override + protected int rehashInternalPartial(int entriesToRehash) { + int rehashedEntries = 0; + while (rehashPointer > 0 && rehashedEntries < entriesToRehash) { + if (migrateOneLocation(--rehashPointer)) { + rehashedEntries++; + } + } + return rehashedEntries; + } + + @Override + protected void newAlternate() { + super.newAlternate(); + this.mainKeySource0 = (ImmutableLongArraySource)super.mainKeySources[0]; + this.alternateKeySource0 = (ImmutableLongArraySource)super.alternateKeySources[0]; + this.mainKeySource1 = (ImmutableLongArraySource)super.mainKeySources[1]; + this.alternateKeySource1 = (ImmutableLongArraySource)super.alternateKeySources[1]; + } + + @Override + protected void clearAlternate() { + super.clearAlternate(); + this.alternateKeySource0 = null; + this.alternateKeySource1 = null; + } + + @Override + protected void migrateFront() { + int location = 0; + while (migrateOneLocation(location++)); + } + + @Override + protected void rehashInternalFull(final int oldSize) { + final long[] destKeyArray0 = new long[tableSize]; + final long[] destKeyArray1 = new long[tableSize]; + final int[] destState = new int[tableSize]; + Arrays.fill(destState, EMPTY_OUTPUT_POSITION); + final long [] originalKeyArray0 = mainKeySource0.getArray(); + mainKeySource0.setArray(destKeyArray0); + final long [] originalKeyArray1 = mainKeySource1.getArray(); + mainKeySource1.setArray(destKeyArray1); + final int [] originalStateArray = mainOutputPosition.getArray(); + mainOutputPosition.setArray(destState); + for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + continue; + } + final long k0 = originalKeyArray0[sourceBucket]; + final long k1 = originalKeyArray1[sourceBucket]; + final int hash = hash(k0, k1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; + while (true) { + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + break; + } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); + } + } + } + + @Override + public int findPositionForKey(Object key) { + final Object [] ka = (Object[])key; + final long k0 = TypeUtils.unbox((Long)ka[0]); + final long k1 = TypeUtils.unbox((Long)ka[1]); + int hash = hash(k0, k1); + int tableLocation = hashToTableLocation(hash); + final int firstTableLocation = tableLocation; + while (true) { + final int positionValue = mainOutputPosition.getUnsafe(tableLocation); + if (positionValue == EMPTY_OUTPUT_POSITION) { + int alternateTableLocation = hashToTableLocationAlternate(hash); + if (alternateTableLocation >= rehashPointer) { + return -1; + } + final int firstAlternateTableLocation = alternateTableLocation; + while (true) { + final int alternatePositionValue = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (alternatePositionValue == EMPTY_OUTPUT_POSITION) { + return -1; + } + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + return alternatePositionValue; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + return positionValue; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherLongObject.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherLongObject.java new file mode 100644 index 00000000000..7260ca6cd27 --- /dev/null +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherLongObject.java @@ -0,0 +1,390 @@ +// DO NOT EDIT THIS CLASS, AUTOMATICALLY GENERATED BY io.deephaven.engine.table.impl.by.typed.TypedHasherFactory +// Copyright (c) 2016-2022 Deephaven Data Labs and Patent Pending +// +package io.deephaven.engine.table.impl.by.typed.incopenagg.gen; + +import static io.deephaven.util.compare.LongComparisons.eq; +import static io.deephaven.util.compare.ObjectComparisons.eq; + +import io.deephaven.base.verify.Assert; +import io.deephaven.chunk.Chunk; +import io.deephaven.chunk.LongChunk; +import io.deephaven.chunk.ObjectChunk; +import io.deephaven.chunk.WritableIntChunk; +import io.deephaven.chunk.attributes.Values; +import io.deephaven.chunk.util.hashing.LongChunkHasher; +import io.deephaven.chunk.util.hashing.ObjectChunkHasher; +import io.deephaven.engine.rowset.RowSequence; +import io.deephaven.engine.rowset.chunkattributes.RowKeys; +import io.deephaven.engine.table.ColumnSource; +import io.deephaven.engine.table.impl.by.IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableLongArraySource; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableObjectArraySource; +import io.deephaven.util.type.TypeUtils; +import java.lang.Long; +import java.lang.Object; +import java.lang.Override; +import java.util.Arrays; + +final class IncrementalAggOpenHasherLongObject extends IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase { + private ImmutableLongArraySource mainKeySource0; + + private ImmutableLongArraySource alternateKeySource0; + + private ImmutableObjectArraySource mainKeySource1; + + private ImmutableObjectArraySource alternateKeySource1; + + public IncrementalAggOpenHasherLongObject(ColumnSource[] tableKeySources, int tableSize, + double maximumLoadFactor, double targetLoadFactor) { + super(tableKeySources, tableSize, maximumLoadFactor); + this.mainKeySource0 = (ImmutableLongArraySource) super.mainKeySources[0]; + this.mainKeySource0.ensureCapacity(tableSize); + this.mainKeySource1 = (ImmutableObjectArraySource) super.mainKeySources[1]; + this.mainKeySource1.ensureCapacity(tableSize); + } + + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + + private int alternateNextTableLocation(int tableLocation) { + return (tableLocation + 1) & (alternateTableSize - 1); + } + + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final LongChunk keyChunk0 = sourceKeyChunks[0].asLongChunk(); + final ObjectChunk keyChunk1 = sourceKeyChunks[1].asObjectChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final long k0 = keyChunk0.get(chunkPosition); + final Object k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void buildForUpdate(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk reincarnatedPositions) { + final LongChunk keyChunk0 = sourceKeyChunks[0].asLongChunk(); + final ObjectChunk keyChunk1 = sourceKeyChunks[1].asObjectChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final long k0 = keyChunk0.get(chunkPosition); + final Object k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void doRemoveProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk emptiedPositions) { + final LongChunk keyChunk0 = sourceKeyChunks[0].asLongChunk(); + final ObjectChunk keyChunk1 = sourceKeyChunks[1].asObjectChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final long k0 = keyChunk0.get(chunkPosition); + final Object k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + protected void doModifyProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final LongChunk keyChunk0 = sourceKeyChunks[0].asLongChunk(); + final ObjectChunk keyChunk1 = sourceKeyChunks[1].asObjectChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final long k0 = keyChunk0.get(chunkPosition); + final Object k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + private static int hash(long k0, Object k1) { + int hash = LongChunkHasher.hashInitialSingle(k0); + hash = ObjectChunkHasher.hashUpdateSingle(hash, k1); + return hash; + } + + private boolean migrateOneLocation(int locationToMigrate) { + final int currentStateValue = alternateOutputPosition.getUnsafe(locationToMigrate); + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + return false; + } + final long k0 = alternateKeySource0.getUnsafe(locationToMigrate); + final Object k1 = alternateKeySource1.getUnsafe(locationToMigrate); + final int hash = hash(k0, k1); + int destinationTableLocation = hashToTableLocation(hash); + while (mainOutputPosition.getUnsafe(destinationTableLocation) != EMPTY_OUTPUT_POSITION) { + destinationTableLocation = nextTableLocation(destinationTableLocation); + } + mainKeySource0.set(destinationTableLocation, k0); + mainKeySource1.set(destinationTableLocation, k1); + alternateKeySource1.set(locationToMigrate, null); + mainOutputPosition.set(destinationTableLocation, currentStateValue); + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + alternateOutputPosition.set(locationToMigrate, EMPTY_OUTPUT_POSITION); + return true; + } + + @Override + protected int rehashInternalPartial(int entriesToRehash) { + int rehashedEntries = 0; + while (rehashPointer > 0 && rehashedEntries < entriesToRehash) { + if (migrateOneLocation(--rehashPointer)) { + rehashedEntries++; + } + } + return rehashedEntries; + } + + @Override + protected void newAlternate() { + super.newAlternate(); + this.mainKeySource0 = (ImmutableLongArraySource)super.mainKeySources[0]; + this.alternateKeySource0 = (ImmutableLongArraySource)super.alternateKeySources[0]; + this.mainKeySource1 = (ImmutableObjectArraySource)super.mainKeySources[1]; + this.alternateKeySource1 = (ImmutableObjectArraySource)super.alternateKeySources[1]; + } + + @Override + protected void clearAlternate() { + super.clearAlternate(); + this.alternateKeySource0 = null; + this.alternateKeySource1 = null; + } + + @Override + protected void migrateFront() { + int location = 0; + while (migrateOneLocation(location++)); + } + + @Override + protected void rehashInternalFull(final int oldSize) { + final long[] destKeyArray0 = new long[tableSize]; + final Object[] destKeyArray1 = new Object[tableSize]; + final int[] destState = new int[tableSize]; + Arrays.fill(destState, EMPTY_OUTPUT_POSITION); + final long [] originalKeyArray0 = mainKeySource0.getArray(); + mainKeySource0.setArray(destKeyArray0); + final Object [] originalKeyArray1 = mainKeySource1.getArray(); + mainKeySource1.setArray(destKeyArray1); + final int [] originalStateArray = mainOutputPosition.getArray(); + mainOutputPosition.setArray(destState); + for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + continue; + } + final long k0 = originalKeyArray0[sourceBucket]; + final Object k1 = originalKeyArray1[sourceBucket]; + final int hash = hash(k0, k1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; + while (true) { + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + break; + } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); + } + } + } + + @Override + public int findPositionForKey(Object key) { + final Object [] ka = (Object[])key; + final long k0 = TypeUtils.unbox((Long)ka[0]); + final Object k1 = ka[1]; + int hash = hash(k0, k1); + int tableLocation = hashToTableLocation(hash); + final int firstTableLocation = tableLocation; + while (true) { + final int positionValue = mainOutputPosition.getUnsafe(tableLocation); + if (positionValue == EMPTY_OUTPUT_POSITION) { + int alternateTableLocation = hashToTableLocationAlternate(hash); + if (alternateTableLocation >= rehashPointer) { + return -1; + } + final int firstAlternateTableLocation = alternateTableLocation; + while (true) { + final int alternatePositionValue = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (alternatePositionValue == EMPTY_OUTPUT_POSITION) { + return -1; + } + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + return alternatePositionValue; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + return positionValue; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherLongShort.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherLongShort.java new file mode 100644 index 00000000000..a366a608887 --- /dev/null +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherLongShort.java @@ -0,0 +1,390 @@ +// DO NOT EDIT THIS CLASS, AUTOMATICALLY GENERATED BY io.deephaven.engine.table.impl.by.typed.TypedHasherFactory +// Copyright (c) 2016-2022 Deephaven Data Labs and Patent Pending +// +package io.deephaven.engine.table.impl.by.typed.incopenagg.gen; + +import static io.deephaven.util.compare.LongComparisons.eq; +import static io.deephaven.util.compare.ShortComparisons.eq; + +import io.deephaven.base.verify.Assert; +import io.deephaven.chunk.Chunk; +import io.deephaven.chunk.LongChunk; +import io.deephaven.chunk.ShortChunk; +import io.deephaven.chunk.WritableIntChunk; +import io.deephaven.chunk.attributes.Values; +import io.deephaven.chunk.util.hashing.LongChunkHasher; +import io.deephaven.chunk.util.hashing.ShortChunkHasher; +import io.deephaven.engine.rowset.RowSequence; +import io.deephaven.engine.rowset.chunkattributes.RowKeys; +import io.deephaven.engine.table.ColumnSource; +import io.deephaven.engine.table.impl.by.IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableLongArraySource; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableShortArraySource; +import io.deephaven.util.type.TypeUtils; +import java.lang.Long; +import java.lang.Object; +import java.lang.Override; +import java.lang.Short; +import java.util.Arrays; + +final class IncrementalAggOpenHasherLongShort extends IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase { + private ImmutableLongArraySource mainKeySource0; + + private ImmutableLongArraySource alternateKeySource0; + + private ImmutableShortArraySource mainKeySource1; + + private ImmutableShortArraySource alternateKeySource1; + + public IncrementalAggOpenHasherLongShort(ColumnSource[] tableKeySources, int tableSize, + double maximumLoadFactor, double targetLoadFactor) { + super(tableKeySources, tableSize, maximumLoadFactor); + this.mainKeySource0 = (ImmutableLongArraySource) super.mainKeySources[0]; + this.mainKeySource0.ensureCapacity(tableSize); + this.mainKeySource1 = (ImmutableShortArraySource) super.mainKeySources[1]; + this.mainKeySource1.ensureCapacity(tableSize); + } + + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + + private int alternateNextTableLocation(int tableLocation) { + return (tableLocation + 1) & (alternateTableSize - 1); + } + + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final LongChunk keyChunk0 = sourceKeyChunks[0].asLongChunk(); + final ShortChunk keyChunk1 = sourceKeyChunks[1].asShortChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final long k0 = keyChunk0.get(chunkPosition); + final short k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void buildForUpdate(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk reincarnatedPositions) { + final LongChunk keyChunk0 = sourceKeyChunks[0].asLongChunk(); + final ShortChunk keyChunk1 = sourceKeyChunks[1].asShortChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final long k0 = keyChunk0.get(chunkPosition); + final short k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void doRemoveProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk emptiedPositions) { + final LongChunk keyChunk0 = sourceKeyChunks[0].asLongChunk(); + final ShortChunk keyChunk1 = sourceKeyChunks[1].asShortChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final long k0 = keyChunk0.get(chunkPosition); + final short k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + protected void doModifyProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final LongChunk keyChunk0 = sourceKeyChunks[0].asLongChunk(); + final ShortChunk keyChunk1 = sourceKeyChunks[1].asShortChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final long k0 = keyChunk0.get(chunkPosition); + final short k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + private static int hash(long k0, short k1) { + int hash = LongChunkHasher.hashInitialSingle(k0); + hash = ShortChunkHasher.hashUpdateSingle(hash, k1); + return hash; + } + + private boolean migrateOneLocation(int locationToMigrate) { + final int currentStateValue = alternateOutputPosition.getUnsafe(locationToMigrate); + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + return false; + } + final long k0 = alternateKeySource0.getUnsafe(locationToMigrate); + final short k1 = alternateKeySource1.getUnsafe(locationToMigrate); + final int hash = hash(k0, k1); + int destinationTableLocation = hashToTableLocation(hash); + while (mainOutputPosition.getUnsafe(destinationTableLocation) != EMPTY_OUTPUT_POSITION) { + destinationTableLocation = nextTableLocation(destinationTableLocation); + } + mainKeySource0.set(destinationTableLocation, k0); + mainKeySource1.set(destinationTableLocation, k1); + mainOutputPosition.set(destinationTableLocation, currentStateValue); + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + alternateOutputPosition.set(locationToMigrate, EMPTY_OUTPUT_POSITION); + return true; + } + + @Override + protected int rehashInternalPartial(int entriesToRehash) { + int rehashedEntries = 0; + while (rehashPointer > 0 && rehashedEntries < entriesToRehash) { + if (migrateOneLocation(--rehashPointer)) { + rehashedEntries++; + } + } + return rehashedEntries; + } + + @Override + protected void newAlternate() { + super.newAlternate(); + this.mainKeySource0 = (ImmutableLongArraySource)super.mainKeySources[0]; + this.alternateKeySource0 = (ImmutableLongArraySource)super.alternateKeySources[0]; + this.mainKeySource1 = (ImmutableShortArraySource)super.mainKeySources[1]; + this.alternateKeySource1 = (ImmutableShortArraySource)super.alternateKeySources[1]; + } + + @Override + protected void clearAlternate() { + super.clearAlternate(); + this.alternateKeySource0 = null; + this.alternateKeySource1 = null; + } + + @Override + protected void migrateFront() { + int location = 0; + while (migrateOneLocation(location++)); + } + + @Override + protected void rehashInternalFull(final int oldSize) { + final long[] destKeyArray0 = new long[tableSize]; + final short[] destKeyArray1 = new short[tableSize]; + final int[] destState = new int[tableSize]; + Arrays.fill(destState, EMPTY_OUTPUT_POSITION); + final long [] originalKeyArray0 = mainKeySource0.getArray(); + mainKeySource0.setArray(destKeyArray0); + final short [] originalKeyArray1 = mainKeySource1.getArray(); + mainKeySource1.setArray(destKeyArray1); + final int [] originalStateArray = mainOutputPosition.getArray(); + mainOutputPosition.setArray(destState); + for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + continue; + } + final long k0 = originalKeyArray0[sourceBucket]; + final short k1 = originalKeyArray1[sourceBucket]; + final int hash = hash(k0, k1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; + while (true) { + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + break; + } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); + } + } + } + + @Override + public int findPositionForKey(Object key) { + final Object [] ka = (Object[])key; + final long k0 = TypeUtils.unbox((Long)ka[0]); + final short k1 = TypeUtils.unbox((Short)ka[1]); + int hash = hash(k0, k1); + int tableLocation = hashToTableLocation(hash); + final int firstTableLocation = tableLocation; + while (true) { + final int positionValue = mainOutputPosition.getUnsafe(tableLocation); + if (positionValue == EMPTY_OUTPUT_POSITION) { + int alternateTableLocation = hashToTableLocationAlternate(hash); + if (alternateTableLocation >= rehashPointer) { + return -1; + } + final int firstAlternateTableLocation = alternateTableLocation; + while (true) { + final int alternatePositionValue = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (alternatePositionValue == EMPTY_OUTPUT_POSITION) { + return -1; + } + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + return alternatePositionValue; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + return positionValue; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherObject.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherObject.java new file mode 100644 index 00000000000..5605e819e1d --- /dev/null +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherObject.java @@ -0,0 +1,355 @@ +// DO NOT EDIT THIS CLASS, AUTOMATICALLY GENERATED BY io.deephaven.engine.table.impl.by.typed.TypedHasherFactory +// Copyright (c) 2016-2022 Deephaven Data Labs and Patent Pending +// +package io.deephaven.engine.table.impl.by.typed.incopenagg.gen; + +import static io.deephaven.util.compare.ObjectComparisons.eq; + +import io.deephaven.base.verify.Assert; +import io.deephaven.chunk.Chunk; +import io.deephaven.chunk.ObjectChunk; +import io.deephaven.chunk.WritableIntChunk; +import io.deephaven.chunk.attributes.Values; +import io.deephaven.chunk.util.hashing.ObjectChunkHasher; +import io.deephaven.engine.rowset.RowSequence; +import io.deephaven.engine.rowset.chunkattributes.RowKeys; +import io.deephaven.engine.table.ColumnSource; +import io.deephaven.engine.table.impl.by.IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableObjectArraySource; +import java.lang.Object; +import java.lang.Override; +import java.util.Arrays; + +final class IncrementalAggOpenHasherObject extends IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase { + private ImmutableObjectArraySource mainKeySource0; + + private ImmutableObjectArraySource alternateKeySource0; + + public IncrementalAggOpenHasherObject(ColumnSource[] tableKeySources, int tableSize, + double maximumLoadFactor, double targetLoadFactor) { + super(tableKeySources, tableSize, maximumLoadFactor); + this.mainKeySource0 = (ImmutableObjectArraySource) super.mainKeySources[0]; + this.mainKeySource0.ensureCapacity(tableSize); + } + + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + + private int alternateNextTableLocation(int tableLocation) { + return (tableLocation + 1) & (alternateTableSize - 1); + } + + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final ObjectChunk keyChunk0 = sourceKeyChunks[0].asObjectChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final Object k0 = keyChunk0.get(chunkPosition); + final int hash = hash(k0); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void buildForUpdate(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk reincarnatedPositions) { + final ObjectChunk keyChunk0 = sourceKeyChunks[0].asObjectChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final Object k0 = keyChunk0.get(chunkPosition); + final int hash = hash(k0); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void doRemoveProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk emptiedPositions) { + final ObjectChunk keyChunk0 = sourceKeyChunks[0].asObjectChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final Object k0 = keyChunk0.get(chunkPosition); + final int hash = hash(k0); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + protected void doModifyProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final ObjectChunk keyChunk0 = sourceKeyChunks[0].asObjectChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final Object k0 = keyChunk0.get(chunkPosition); + final int hash = hash(k0); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0)) { + outputPositions.set(chunkPosition, outputPosition); + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0)) { + outputPositions.set(chunkPosition, outputPosition); + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + private static int hash(Object k0) { + int hash = ObjectChunkHasher.hashInitialSingle(k0); + return hash; + } + + private boolean migrateOneLocation(int locationToMigrate) { + final int currentStateValue = alternateOutputPosition.getUnsafe(locationToMigrate); + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + return false; + } + final Object k0 = alternateKeySource0.getUnsafe(locationToMigrate); + final int hash = hash(k0); + int destinationTableLocation = hashToTableLocation(hash); + while (mainOutputPosition.getUnsafe(destinationTableLocation) != EMPTY_OUTPUT_POSITION) { + destinationTableLocation = nextTableLocation(destinationTableLocation); + } + mainKeySource0.set(destinationTableLocation, k0); + alternateKeySource0.set(locationToMigrate, null); + mainOutputPosition.set(destinationTableLocation, currentStateValue); + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + alternateOutputPosition.set(locationToMigrate, EMPTY_OUTPUT_POSITION); + return true; + } + + @Override + protected int rehashInternalPartial(int entriesToRehash) { + int rehashedEntries = 0; + while (rehashPointer > 0 && rehashedEntries < entriesToRehash) { + if (migrateOneLocation(--rehashPointer)) { + rehashedEntries++; + } + } + return rehashedEntries; + } + + @Override + protected void newAlternate() { + super.newAlternate(); + this.mainKeySource0 = (ImmutableObjectArraySource)super.mainKeySources[0]; + this.alternateKeySource0 = (ImmutableObjectArraySource)super.alternateKeySources[0]; + } + + @Override + protected void clearAlternate() { + super.clearAlternate(); + this.alternateKeySource0 = null; + } + + @Override + protected void migrateFront() { + int location = 0; + while (migrateOneLocation(location++)); + } + + @Override + protected void rehashInternalFull(final int oldSize) { + final Object[] destKeyArray0 = new Object[tableSize]; + final int[] destState = new int[tableSize]; + Arrays.fill(destState, EMPTY_OUTPUT_POSITION); + final Object [] originalKeyArray0 = mainKeySource0.getArray(); + mainKeySource0.setArray(destKeyArray0); + final int [] originalStateArray = mainOutputPosition.getArray(); + mainOutputPosition.setArray(destState); + for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + continue; + } + final Object k0 = originalKeyArray0[sourceBucket]; + final int hash = hash(k0); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; + while (true) { + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + break; + } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); + } + } + } + + @Override + public int findPositionForKey(Object key) { + final Object k0 = key; + int hash = hash(k0); + int tableLocation = hashToTableLocation(hash); + final int firstTableLocation = tableLocation; + while (true) { + final int positionValue = mainOutputPosition.getUnsafe(tableLocation); + if (positionValue == EMPTY_OUTPUT_POSITION) { + int alternateTableLocation = hashToTableLocationAlternate(hash); + if (alternateTableLocation >= rehashPointer) { + return -1; + } + final int firstAlternateTableLocation = alternateTableLocation; + while (true) { + final int alternatePositionValue = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (alternatePositionValue == EMPTY_OUTPUT_POSITION) { + return -1; + } + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0)) { + return alternatePositionValue; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (eq(mainKeySource0.getUnsafe(tableLocation), k0)) { + return positionValue; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherObjectByte.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherObjectByte.java new file mode 100644 index 00000000000..c3ec150fdda --- /dev/null +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherObjectByte.java @@ -0,0 +1,390 @@ +// DO NOT EDIT THIS CLASS, AUTOMATICALLY GENERATED BY io.deephaven.engine.table.impl.by.typed.TypedHasherFactory +// Copyright (c) 2016-2022 Deephaven Data Labs and Patent Pending +// +package io.deephaven.engine.table.impl.by.typed.incopenagg.gen; + +import static io.deephaven.util.compare.ByteComparisons.eq; +import static io.deephaven.util.compare.ObjectComparisons.eq; + +import io.deephaven.base.verify.Assert; +import io.deephaven.chunk.ByteChunk; +import io.deephaven.chunk.Chunk; +import io.deephaven.chunk.ObjectChunk; +import io.deephaven.chunk.WritableIntChunk; +import io.deephaven.chunk.attributes.Values; +import io.deephaven.chunk.util.hashing.ByteChunkHasher; +import io.deephaven.chunk.util.hashing.ObjectChunkHasher; +import io.deephaven.engine.rowset.RowSequence; +import io.deephaven.engine.rowset.chunkattributes.RowKeys; +import io.deephaven.engine.table.ColumnSource; +import io.deephaven.engine.table.impl.by.IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableByteArraySource; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableObjectArraySource; +import io.deephaven.util.type.TypeUtils; +import java.lang.Byte; +import java.lang.Object; +import java.lang.Override; +import java.util.Arrays; + +final class IncrementalAggOpenHasherObjectByte extends IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase { + private ImmutableObjectArraySource mainKeySource0; + + private ImmutableObjectArraySource alternateKeySource0; + + private ImmutableByteArraySource mainKeySource1; + + private ImmutableByteArraySource alternateKeySource1; + + public IncrementalAggOpenHasherObjectByte(ColumnSource[] tableKeySources, int tableSize, + double maximumLoadFactor, double targetLoadFactor) { + super(tableKeySources, tableSize, maximumLoadFactor); + this.mainKeySource0 = (ImmutableObjectArraySource) super.mainKeySources[0]; + this.mainKeySource0.ensureCapacity(tableSize); + this.mainKeySource1 = (ImmutableByteArraySource) super.mainKeySources[1]; + this.mainKeySource1.ensureCapacity(tableSize); + } + + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + + private int alternateNextTableLocation(int tableLocation) { + return (tableLocation + 1) & (alternateTableSize - 1); + } + + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final ObjectChunk keyChunk0 = sourceKeyChunks[0].asObjectChunk(); + final ByteChunk keyChunk1 = sourceKeyChunks[1].asByteChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final Object k0 = keyChunk0.get(chunkPosition); + final byte k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void buildForUpdate(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk reincarnatedPositions) { + final ObjectChunk keyChunk0 = sourceKeyChunks[0].asObjectChunk(); + final ByteChunk keyChunk1 = sourceKeyChunks[1].asByteChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final Object k0 = keyChunk0.get(chunkPosition); + final byte k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void doRemoveProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk emptiedPositions) { + final ObjectChunk keyChunk0 = sourceKeyChunks[0].asObjectChunk(); + final ByteChunk keyChunk1 = sourceKeyChunks[1].asByteChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final Object k0 = keyChunk0.get(chunkPosition); + final byte k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + protected void doModifyProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final ObjectChunk keyChunk0 = sourceKeyChunks[0].asObjectChunk(); + final ByteChunk keyChunk1 = sourceKeyChunks[1].asByteChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final Object k0 = keyChunk0.get(chunkPosition); + final byte k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + private static int hash(Object k0, byte k1) { + int hash = ObjectChunkHasher.hashInitialSingle(k0); + hash = ByteChunkHasher.hashUpdateSingle(hash, k1); + return hash; + } + + private boolean migrateOneLocation(int locationToMigrate) { + final int currentStateValue = alternateOutputPosition.getUnsafe(locationToMigrate); + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + return false; + } + final Object k0 = alternateKeySource0.getUnsafe(locationToMigrate); + final byte k1 = alternateKeySource1.getUnsafe(locationToMigrate); + final int hash = hash(k0, k1); + int destinationTableLocation = hashToTableLocation(hash); + while (mainOutputPosition.getUnsafe(destinationTableLocation) != EMPTY_OUTPUT_POSITION) { + destinationTableLocation = nextTableLocation(destinationTableLocation); + } + mainKeySource0.set(destinationTableLocation, k0); + alternateKeySource0.set(locationToMigrate, null); + mainKeySource1.set(destinationTableLocation, k1); + mainOutputPosition.set(destinationTableLocation, currentStateValue); + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + alternateOutputPosition.set(locationToMigrate, EMPTY_OUTPUT_POSITION); + return true; + } + + @Override + protected int rehashInternalPartial(int entriesToRehash) { + int rehashedEntries = 0; + while (rehashPointer > 0 && rehashedEntries < entriesToRehash) { + if (migrateOneLocation(--rehashPointer)) { + rehashedEntries++; + } + } + return rehashedEntries; + } + + @Override + protected void newAlternate() { + super.newAlternate(); + this.mainKeySource0 = (ImmutableObjectArraySource)super.mainKeySources[0]; + this.alternateKeySource0 = (ImmutableObjectArraySource)super.alternateKeySources[0]; + this.mainKeySource1 = (ImmutableByteArraySource)super.mainKeySources[1]; + this.alternateKeySource1 = (ImmutableByteArraySource)super.alternateKeySources[1]; + } + + @Override + protected void clearAlternate() { + super.clearAlternate(); + this.alternateKeySource0 = null; + this.alternateKeySource1 = null; + } + + @Override + protected void migrateFront() { + int location = 0; + while (migrateOneLocation(location++)); + } + + @Override + protected void rehashInternalFull(final int oldSize) { + final Object[] destKeyArray0 = new Object[tableSize]; + final byte[] destKeyArray1 = new byte[tableSize]; + final int[] destState = new int[tableSize]; + Arrays.fill(destState, EMPTY_OUTPUT_POSITION); + final Object [] originalKeyArray0 = mainKeySource0.getArray(); + mainKeySource0.setArray(destKeyArray0); + final byte [] originalKeyArray1 = mainKeySource1.getArray(); + mainKeySource1.setArray(destKeyArray1); + final int [] originalStateArray = mainOutputPosition.getArray(); + mainOutputPosition.setArray(destState); + for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + continue; + } + final Object k0 = originalKeyArray0[sourceBucket]; + final byte k1 = originalKeyArray1[sourceBucket]; + final int hash = hash(k0, k1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; + while (true) { + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + break; + } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); + } + } + } + + @Override + public int findPositionForKey(Object key) { + final Object [] ka = (Object[])key; + final Object k0 = ka[0]; + final byte k1 = TypeUtils.unbox((Byte)ka[1]); + int hash = hash(k0, k1); + int tableLocation = hashToTableLocation(hash); + final int firstTableLocation = tableLocation; + while (true) { + final int positionValue = mainOutputPosition.getUnsafe(tableLocation); + if (positionValue == EMPTY_OUTPUT_POSITION) { + int alternateTableLocation = hashToTableLocationAlternate(hash); + if (alternateTableLocation >= rehashPointer) { + return -1; + } + final int firstAlternateTableLocation = alternateTableLocation; + while (true) { + final int alternatePositionValue = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (alternatePositionValue == EMPTY_OUTPUT_POSITION) { + return -1; + } + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + return alternatePositionValue; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + return positionValue; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherObjectChar.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherObjectChar.java new file mode 100644 index 00000000000..a0f4b236ffa --- /dev/null +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherObjectChar.java @@ -0,0 +1,390 @@ +// DO NOT EDIT THIS CLASS, AUTOMATICALLY GENERATED BY io.deephaven.engine.table.impl.by.typed.TypedHasherFactory +// Copyright (c) 2016-2022 Deephaven Data Labs and Patent Pending +// +package io.deephaven.engine.table.impl.by.typed.incopenagg.gen; + +import static io.deephaven.util.compare.CharComparisons.eq; +import static io.deephaven.util.compare.ObjectComparisons.eq; + +import io.deephaven.base.verify.Assert; +import io.deephaven.chunk.CharChunk; +import io.deephaven.chunk.Chunk; +import io.deephaven.chunk.ObjectChunk; +import io.deephaven.chunk.WritableIntChunk; +import io.deephaven.chunk.attributes.Values; +import io.deephaven.chunk.util.hashing.CharChunkHasher; +import io.deephaven.chunk.util.hashing.ObjectChunkHasher; +import io.deephaven.engine.rowset.RowSequence; +import io.deephaven.engine.rowset.chunkattributes.RowKeys; +import io.deephaven.engine.table.ColumnSource; +import io.deephaven.engine.table.impl.by.IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableCharArraySource; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableObjectArraySource; +import io.deephaven.util.type.TypeUtils; +import java.lang.Character; +import java.lang.Object; +import java.lang.Override; +import java.util.Arrays; + +final class IncrementalAggOpenHasherObjectChar extends IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase { + private ImmutableObjectArraySource mainKeySource0; + + private ImmutableObjectArraySource alternateKeySource0; + + private ImmutableCharArraySource mainKeySource1; + + private ImmutableCharArraySource alternateKeySource1; + + public IncrementalAggOpenHasherObjectChar(ColumnSource[] tableKeySources, int tableSize, + double maximumLoadFactor, double targetLoadFactor) { + super(tableKeySources, tableSize, maximumLoadFactor); + this.mainKeySource0 = (ImmutableObjectArraySource) super.mainKeySources[0]; + this.mainKeySource0.ensureCapacity(tableSize); + this.mainKeySource1 = (ImmutableCharArraySource) super.mainKeySources[1]; + this.mainKeySource1.ensureCapacity(tableSize); + } + + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + + private int alternateNextTableLocation(int tableLocation) { + return (tableLocation + 1) & (alternateTableSize - 1); + } + + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final ObjectChunk keyChunk0 = sourceKeyChunks[0].asObjectChunk(); + final CharChunk keyChunk1 = sourceKeyChunks[1].asCharChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final Object k0 = keyChunk0.get(chunkPosition); + final char k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void buildForUpdate(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk reincarnatedPositions) { + final ObjectChunk keyChunk0 = sourceKeyChunks[0].asObjectChunk(); + final CharChunk keyChunk1 = sourceKeyChunks[1].asCharChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final Object k0 = keyChunk0.get(chunkPosition); + final char k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void doRemoveProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk emptiedPositions) { + final ObjectChunk keyChunk0 = sourceKeyChunks[0].asObjectChunk(); + final CharChunk keyChunk1 = sourceKeyChunks[1].asCharChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final Object k0 = keyChunk0.get(chunkPosition); + final char k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + protected void doModifyProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final ObjectChunk keyChunk0 = sourceKeyChunks[0].asObjectChunk(); + final CharChunk keyChunk1 = sourceKeyChunks[1].asCharChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final Object k0 = keyChunk0.get(chunkPosition); + final char k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + private static int hash(Object k0, char k1) { + int hash = ObjectChunkHasher.hashInitialSingle(k0); + hash = CharChunkHasher.hashUpdateSingle(hash, k1); + return hash; + } + + private boolean migrateOneLocation(int locationToMigrate) { + final int currentStateValue = alternateOutputPosition.getUnsafe(locationToMigrate); + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + return false; + } + final Object k0 = alternateKeySource0.getUnsafe(locationToMigrate); + final char k1 = alternateKeySource1.getUnsafe(locationToMigrate); + final int hash = hash(k0, k1); + int destinationTableLocation = hashToTableLocation(hash); + while (mainOutputPosition.getUnsafe(destinationTableLocation) != EMPTY_OUTPUT_POSITION) { + destinationTableLocation = nextTableLocation(destinationTableLocation); + } + mainKeySource0.set(destinationTableLocation, k0); + alternateKeySource0.set(locationToMigrate, null); + mainKeySource1.set(destinationTableLocation, k1); + mainOutputPosition.set(destinationTableLocation, currentStateValue); + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + alternateOutputPosition.set(locationToMigrate, EMPTY_OUTPUT_POSITION); + return true; + } + + @Override + protected int rehashInternalPartial(int entriesToRehash) { + int rehashedEntries = 0; + while (rehashPointer > 0 && rehashedEntries < entriesToRehash) { + if (migrateOneLocation(--rehashPointer)) { + rehashedEntries++; + } + } + return rehashedEntries; + } + + @Override + protected void newAlternate() { + super.newAlternate(); + this.mainKeySource0 = (ImmutableObjectArraySource)super.mainKeySources[0]; + this.alternateKeySource0 = (ImmutableObjectArraySource)super.alternateKeySources[0]; + this.mainKeySource1 = (ImmutableCharArraySource)super.mainKeySources[1]; + this.alternateKeySource1 = (ImmutableCharArraySource)super.alternateKeySources[1]; + } + + @Override + protected void clearAlternate() { + super.clearAlternate(); + this.alternateKeySource0 = null; + this.alternateKeySource1 = null; + } + + @Override + protected void migrateFront() { + int location = 0; + while (migrateOneLocation(location++)); + } + + @Override + protected void rehashInternalFull(final int oldSize) { + final Object[] destKeyArray0 = new Object[tableSize]; + final char[] destKeyArray1 = new char[tableSize]; + final int[] destState = new int[tableSize]; + Arrays.fill(destState, EMPTY_OUTPUT_POSITION); + final Object [] originalKeyArray0 = mainKeySource0.getArray(); + mainKeySource0.setArray(destKeyArray0); + final char [] originalKeyArray1 = mainKeySource1.getArray(); + mainKeySource1.setArray(destKeyArray1); + final int [] originalStateArray = mainOutputPosition.getArray(); + mainOutputPosition.setArray(destState); + for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + continue; + } + final Object k0 = originalKeyArray0[sourceBucket]; + final char k1 = originalKeyArray1[sourceBucket]; + final int hash = hash(k0, k1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; + while (true) { + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + break; + } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); + } + } + } + + @Override + public int findPositionForKey(Object key) { + final Object [] ka = (Object[])key; + final Object k0 = ka[0]; + final char k1 = TypeUtils.unbox((Character)ka[1]); + int hash = hash(k0, k1); + int tableLocation = hashToTableLocation(hash); + final int firstTableLocation = tableLocation; + while (true) { + final int positionValue = mainOutputPosition.getUnsafe(tableLocation); + if (positionValue == EMPTY_OUTPUT_POSITION) { + int alternateTableLocation = hashToTableLocationAlternate(hash); + if (alternateTableLocation >= rehashPointer) { + return -1; + } + final int firstAlternateTableLocation = alternateTableLocation; + while (true) { + final int alternatePositionValue = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (alternatePositionValue == EMPTY_OUTPUT_POSITION) { + return -1; + } + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + return alternatePositionValue; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + return positionValue; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherObjectDouble.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherObjectDouble.java new file mode 100644 index 00000000000..f766e9a4d19 --- /dev/null +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherObjectDouble.java @@ -0,0 +1,390 @@ +// DO NOT EDIT THIS CLASS, AUTOMATICALLY GENERATED BY io.deephaven.engine.table.impl.by.typed.TypedHasherFactory +// Copyright (c) 2016-2022 Deephaven Data Labs and Patent Pending +// +package io.deephaven.engine.table.impl.by.typed.incopenagg.gen; + +import static io.deephaven.util.compare.DoubleComparisons.eq; +import static io.deephaven.util.compare.ObjectComparisons.eq; + +import io.deephaven.base.verify.Assert; +import io.deephaven.chunk.Chunk; +import io.deephaven.chunk.DoubleChunk; +import io.deephaven.chunk.ObjectChunk; +import io.deephaven.chunk.WritableIntChunk; +import io.deephaven.chunk.attributes.Values; +import io.deephaven.chunk.util.hashing.DoubleChunkHasher; +import io.deephaven.chunk.util.hashing.ObjectChunkHasher; +import io.deephaven.engine.rowset.RowSequence; +import io.deephaven.engine.rowset.chunkattributes.RowKeys; +import io.deephaven.engine.table.ColumnSource; +import io.deephaven.engine.table.impl.by.IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableDoubleArraySource; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableObjectArraySource; +import io.deephaven.util.type.TypeUtils; +import java.lang.Double; +import java.lang.Object; +import java.lang.Override; +import java.util.Arrays; + +final class IncrementalAggOpenHasherObjectDouble extends IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase { + private ImmutableObjectArraySource mainKeySource0; + + private ImmutableObjectArraySource alternateKeySource0; + + private ImmutableDoubleArraySource mainKeySource1; + + private ImmutableDoubleArraySource alternateKeySource1; + + public IncrementalAggOpenHasherObjectDouble(ColumnSource[] tableKeySources, int tableSize, + double maximumLoadFactor, double targetLoadFactor) { + super(tableKeySources, tableSize, maximumLoadFactor); + this.mainKeySource0 = (ImmutableObjectArraySource) super.mainKeySources[0]; + this.mainKeySource0.ensureCapacity(tableSize); + this.mainKeySource1 = (ImmutableDoubleArraySource) super.mainKeySources[1]; + this.mainKeySource1.ensureCapacity(tableSize); + } + + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + + private int alternateNextTableLocation(int tableLocation) { + return (tableLocation + 1) & (alternateTableSize - 1); + } + + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final ObjectChunk keyChunk0 = sourceKeyChunks[0].asObjectChunk(); + final DoubleChunk keyChunk1 = sourceKeyChunks[1].asDoubleChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final Object k0 = keyChunk0.get(chunkPosition); + final double k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void buildForUpdate(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk reincarnatedPositions) { + final ObjectChunk keyChunk0 = sourceKeyChunks[0].asObjectChunk(); + final DoubleChunk keyChunk1 = sourceKeyChunks[1].asDoubleChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final Object k0 = keyChunk0.get(chunkPosition); + final double k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void doRemoveProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk emptiedPositions) { + final ObjectChunk keyChunk0 = sourceKeyChunks[0].asObjectChunk(); + final DoubleChunk keyChunk1 = sourceKeyChunks[1].asDoubleChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final Object k0 = keyChunk0.get(chunkPosition); + final double k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + protected void doModifyProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final ObjectChunk keyChunk0 = sourceKeyChunks[0].asObjectChunk(); + final DoubleChunk keyChunk1 = sourceKeyChunks[1].asDoubleChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final Object k0 = keyChunk0.get(chunkPosition); + final double k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + private static int hash(Object k0, double k1) { + int hash = ObjectChunkHasher.hashInitialSingle(k0); + hash = DoubleChunkHasher.hashUpdateSingle(hash, k1); + return hash; + } + + private boolean migrateOneLocation(int locationToMigrate) { + final int currentStateValue = alternateOutputPosition.getUnsafe(locationToMigrate); + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + return false; + } + final Object k0 = alternateKeySource0.getUnsafe(locationToMigrate); + final double k1 = alternateKeySource1.getUnsafe(locationToMigrate); + final int hash = hash(k0, k1); + int destinationTableLocation = hashToTableLocation(hash); + while (mainOutputPosition.getUnsafe(destinationTableLocation) != EMPTY_OUTPUT_POSITION) { + destinationTableLocation = nextTableLocation(destinationTableLocation); + } + mainKeySource0.set(destinationTableLocation, k0); + alternateKeySource0.set(locationToMigrate, null); + mainKeySource1.set(destinationTableLocation, k1); + mainOutputPosition.set(destinationTableLocation, currentStateValue); + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + alternateOutputPosition.set(locationToMigrate, EMPTY_OUTPUT_POSITION); + return true; + } + + @Override + protected int rehashInternalPartial(int entriesToRehash) { + int rehashedEntries = 0; + while (rehashPointer > 0 && rehashedEntries < entriesToRehash) { + if (migrateOneLocation(--rehashPointer)) { + rehashedEntries++; + } + } + return rehashedEntries; + } + + @Override + protected void newAlternate() { + super.newAlternate(); + this.mainKeySource0 = (ImmutableObjectArraySource)super.mainKeySources[0]; + this.alternateKeySource0 = (ImmutableObjectArraySource)super.alternateKeySources[0]; + this.mainKeySource1 = (ImmutableDoubleArraySource)super.mainKeySources[1]; + this.alternateKeySource1 = (ImmutableDoubleArraySource)super.alternateKeySources[1]; + } + + @Override + protected void clearAlternate() { + super.clearAlternate(); + this.alternateKeySource0 = null; + this.alternateKeySource1 = null; + } + + @Override + protected void migrateFront() { + int location = 0; + while (migrateOneLocation(location++)); + } + + @Override + protected void rehashInternalFull(final int oldSize) { + final Object[] destKeyArray0 = new Object[tableSize]; + final double[] destKeyArray1 = new double[tableSize]; + final int[] destState = new int[tableSize]; + Arrays.fill(destState, EMPTY_OUTPUT_POSITION); + final Object [] originalKeyArray0 = mainKeySource0.getArray(); + mainKeySource0.setArray(destKeyArray0); + final double [] originalKeyArray1 = mainKeySource1.getArray(); + mainKeySource1.setArray(destKeyArray1); + final int [] originalStateArray = mainOutputPosition.getArray(); + mainOutputPosition.setArray(destState); + for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + continue; + } + final Object k0 = originalKeyArray0[sourceBucket]; + final double k1 = originalKeyArray1[sourceBucket]; + final int hash = hash(k0, k1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; + while (true) { + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + break; + } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); + } + } + } + + @Override + public int findPositionForKey(Object key) { + final Object [] ka = (Object[])key; + final Object k0 = ka[0]; + final double k1 = TypeUtils.unbox((Double)ka[1]); + int hash = hash(k0, k1); + int tableLocation = hashToTableLocation(hash); + final int firstTableLocation = tableLocation; + while (true) { + final int positionValue = mainOutputPosition.getUnsafe(tableLocation); + if (positionValue == EMPTY_OUTPUT_POSITION) { + int alternateTableLocation = hashToTableLocationAlternate(hash); + if (alternateTableLocation >= rehashPointer) { + return -1; + } + final int firstAlternateTableLocation = alternateTableLocation; + while (true) { + final int alternatePositionValue = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (alternatePositionValue == EMPTY_OUTPUT_POSITION) { + return -1; + } + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + return alternatePositionValue; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + return positionValue; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherObjectFloat.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherObjectFloat.java new file mode 100644 index 00000000000..ef087d1f6e7 --- /dev/null +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherObjectFloat.java @@ -0,0 +1,390 @@ +// DO NOT EDIT THIS CLASS, AUTOMATICALLY GENERATED BY io.deephaven.engine.table.impl.by.typed.TypedHasherFactory +// Copyright (c) 2016-2022 Deephaven Data Labs and Patent Pending +// +package io.deephaven.engine.table.impl.by.typed.incopenagg.gen; + +import static io.deephaven.util.compare.FloatComparisons.eq; +import static io.deephaven.util.compare.ObjectComparisons.eq; + +import io.deephaven.base.verify.Assert; +import io.deephaven.chunk.Chunk; +import io.deephaven.chunk.FloatChunk; +import io.deephaven.chunk.ObjectChunk; +import io.deephaven.chunk.WritableIntChunk; +import io.deephaven.chunk.attributes.Values; +import io.deephaven.chunk.util.hashing.FloatChunkHasher; +import io.deephaven.chunk.util.hashing.ObjectChunkHasher; +import io.deephaven.engine.rowset.RowSequence; +import io.deephaven.engine.rowset.chunkattributes.RowKeys; +import io.deephaven.engine.table.ColumnSource; +import io.deephaven.engine.table.impl.by.IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableFloatArraySource; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableObjectArraySource; +import io.deephaven.util.type.TypeUtils; +import java.lang.Float; +import java.lang.Object; +import java.lang.Override; +import java.util.Arrays; + +final class IncrementalAggOpenHasherObjectFloat extends IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase { + private ImmutableObjectArraySource mainKeySource0; + + private ImmutableObjectArraySource alternateKeySource0; + + private ImmutableFloatArraySource mainKeySource1; + + private ImmutableFloatArraySource alternateKeySource1; + + public IncrementalAggOpenHasherObjectFloat(ColumnSource[] tableKeySources, int tableSize, + double maximumLoadFactor, double targetLoadFactor) { + super(tableKeySources, tableSize, maximumLoadFactor); + this.mainKeySource0 = (ImmutableObjectArraySource) super.mainKeySources[0]; + this.mainKeySource0.ensureCapacity(tableSize); + this.mainKeySource1 = (ImmutableFloatArraySource) super.mainKeySources[1]; + this.mainKeySource1.ensureCapacity(tableSize); + } + + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + + private int alternateNextTableLocation(int tableLocation) { + return (tableLocation + 1) & (alternateTableSize - 1); + } + + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final ObjectChunk keyChunk0 = sourceKeyChunks[0].asObjectChunk(); + final FloatChunk keyChunk1 = sourceKeyChunks[1].asFloatChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final Object k0 = keyChunk0.get(chunkPosition); + final float k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void buildForUpdate(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk reincarnatedPositions) { + final ObjectChunk keyChunk0 = sourceKeyChunks[0].asObjectChunk(); + final FloatChunk keyChunk1 = sourceKeyChunks[1].asFloatChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final Object k0 = keyChunk0.get(chunkPosition); + final float k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void doRemoveProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk emptiedPositions) { + final ObjectChunk keyChunk0 = sourceKeyChunks[0].asObjectChunk(); + final FloatChunk keyChunk1 = sourceKeyChunks[1].asFloatChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final Object k0 = keyChunk0.get(chunkPosition); + final float k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + protected void doModifyProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final ObjectChunk keyChunk0 = sourceKeyChunks[0].asObjectChunk(); + final FloatChunk keyChunk1 = sourceKeyChunks[1].asFloatChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final Object k0 = keyChunk0.get(chunkPosition); + final float k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + private static int hash(Object k0, float k1) { + int hash = ObjectChunkHasher.hashInitialSingle(k0); + hash = FloatChunkHasher.hashUpdateSingle(hash, k1); + return hash; + } + + private boolean migrateOneLocation(int locationToMigrate) { + final int currentStateValue = alternateOutputPosition.getUnsafe(locationToMigrate); + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + return false; + } + final Object k0 = alternateKeySource0.getUnsafe(locationToMigrate); + final float k1 = alternateKeySource1.getUnsafe(locationToMigrate); + final int hash = hash(k0, k1); + int destinationTableLocation = hashToTableLocation(hash); + while (mainOutputPosition.getUnsafe(destinationTableLocation) != EMPTY_OUTPUT_POSITION) { + destinationTableLocation = nextTableLocation(destinationTableLocation); + } + mainKeySource0.set(destinationTableLocation, k0); + alternateKeySource0.set(locationToMigrate, null); + mainKeySource1.set(destinationTableLocation, k1); + mainOutputPosition.set(destinationTableLocation, currentStateValue); + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + alternateOutputPosition.set(locationToMigrate, EMPTY_OUTPUT_POSITION); + return true; + } + + @Override + protected int rehashInternalPartial(int entriesToRehash) { + int rehashedEntries = 0; + while (rehashPointer > 0 && rehashedEntries < entriesToRehash) { + if (migrateOneLocation(--rehashPointer)) { + rehashedEntries++; + } + } + return rehashedEntries; + } + + @Override + protected void newAlternate() { + super.newAlternate(); + this.mainKeySource0 = (ImmutableObjectArraySource)super.mainKeySources[0]; + this.alternateKeySource0 = (ImmutableObjectArraySource)super.alternateKeySources[0]; + this.mainKeySource1 = (ImmutableFloatArraySource)super.mainKeySources[1]; + this.alternateKeySource1 = (ImmutableFloatArraySource)super.alternateKeySources[1]; + } + + @Override + protected void clearAlternate() { + super.clearAlternate(); + this.alternateKeySource0 = null; + this.alternateKeySource1 = null; + } + + @Override + protected void migrateFront() { + int location = 0; + while (migrateOneLocation(location++)); + } + + @Override + protected void rehashInternalFull(final int oldSize) { + final Object[] destKeyArray0 = new Object[tableSize]; + final float[] destKeyArray1 = new float[tableSize]; + final int[] destState = new int[tableSize]; + Arrays.fill(destState, EMPTY_OUTPUT_POSITION); + final Object [] originalKeyArray0 = mainKeySource0.getArray(); + mainKeySource0.setArray(destKeyArray0); + final float [] originalKeyArray1 = mainKeySource1.getArray(); + mainKeySource1.setArray(destKeyArray1); + final int [] originalStateArray = mainOutputPosition.getArray(); + mainOutputPosition.setArray(destState); + for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + continue; + } + final Object k0 = originalKeyArray0[sourceBucket]; + final float k1 = originalKeyArray1[sourceBucket]; + final int hash = hash(k0, k1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; + while (true) { + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + break; + } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); + } + } + } + + @Override + public int findPositionForKey(Object key) { + final Object [] ka = (Object[])key; + final Object k0 = ka[0]; + final float k1 = TypeUtils.unbox((Float)ka[1]); + int hash = hash(k0, k1); + int tableLocation = hashToTableLocation(hash); + final int firstTableLocation = tableLocation; + while (true) { + final int positionValue = mainOutputPosition.getUnsafe(tableLocation); + if (positionValue == EMPTY_OUTPUT_POSITION) { + int alternateTableLocation = hashToTableLocationAlternate(hash); + if (alternateTableLocation >= rehashPointer) { + return -1; + } + final int firstAlternateTableLocation = alternateTableLocation; + while (true) { + final int alternatePositionValue = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (alternatePositionValue == EMPTY_OUTPUT_POSITION) { + return -1; + } + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + return alternatePositionValue; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + return positionValue; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherObjectInt.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherObjectInt.java new file mode 100644 index 00000000000..92fbde1661e --- /dev/null +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherObjectInt.java @@ -0,0 +1,390 @@ +// DO NOT EDIT THIS CLASS, AUTOMATICALLY GENERATED BY io.deephaven.engine.table.impl.by.typed.TypedHasherFactory +// Copyright (c) 2016-2022 Deephaven Data Labs and Patent Pending +// +package io.deephaven.engine.table.impl.by.typed.incopenagg.gen; + +import static io.deephaven.util.compare.IntComparisons.eq; +import static io.deephaven.util.compare.ObjectComparisons.eq; + +import io.deephaven.base.verify.Assert; +import io.deephaven.chunk.Chunk; +import io.deephaven.chunk.IntChunk; +import io.deephaven.chunk.ObjectChunk; +import io.deephaven.chunk.WritableIntChunk; +import io.deephaven.chunk.attributes.Values; +import io.deephaven.chunk.util.hashing.IntChunkHasher; +import io.deephaven.chunk.util.hashing.ObjectChunkHasher; +import io.deephaven.engine.rowset.RowSequence; +import io.deephaven.engine.rowset.chunkattributes.RowKeys; +import io.deephaven.engine.table.ColumnSource; +import io.deephaven.engine.table.impl.by.IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableIntArraySource; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableObjectArraySource; +import io.deephaven.util.type.TypeUtils; +import java.lang.Integer; +import java.lang.Object; +import java.lang.Override; +import java.util.Arrays; + +final class IncrementalAggOpenHasherObjectInt extends IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase { + private ImmutableObjectArraySource mainKeySource0; + + private ImmutableObjectArraySource alternateKeySource0; + + private ImmutableIntArraySource mainKeySource1; + + private ImmutableIntArraySource alternateKeySource1; + + public IncrementalAggOpenHasherObjectInt(ColumnSource[] tableKeySources, int tableSize, + double maximumLoadFactor, double targetLoadFactor) { + super(tableKeySources, tableSize, maximumLoadFactor); + this.mainKeySource0 = (ImmutableObjectArraySource) super.mainKeySources[0]; + this.mainKeySource0.ensureCapacity(tableSize); + this.mainKeySource1 = (ImmutableIntArraySource) super.mainKeySources[1]; + this.mainKeySource1.ensureCapacity(tableSize); + } + + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + + private int alternateNextTableLocation(int tableLocation) { + return (tableLocation + 1) & (alternateTableSize - 1); + } + + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final ObjectChunk keyChunk0 = sourceKeyChunks[0].asObjectChunk(); + final IntChunk keyChunk1 = sourceKeyChunks[1].asIntChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final Object k0 = keyChunk0.get(chunkPosition); + final int k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void buildForUpdate(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk reincarnatedPositions) { + final ObjectChunk keyChunk0 = sourceKeyChunks[0].asObjectChunk(); + final IntChunk keyChunk1 = sourceKeyChunks[1].asIntChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final Object k0 = keyChunk0.get(chunkPosition); + final int k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void doRemoveProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk emptiedPositions) { + final ObjectChunk keyChunk0 = sourceKeyChunks[0].asObjectChunk(); + final IntChunk keyChunk1 = sourceKeyChunks[1].asIntChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final Object k0 = keyChunk0.get(chunkPosition); + final int k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + protected void doModifyProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final ObjectChunk keyChunk0 = sourceKeyChunks[0].asObjectChunk(); + final IntChunk keyChunk1 = sourceKeyChunks[1].asIntChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final Object k0 = keyChunk0.get(chunkPosition); + final int k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + private static int hash(Object k0, int k1) { + int hash = ObjectChunkHasher.hashInitialSingle(k0); + hash = IntChunkHasher.hashUpdateSingle(hash, k1); + return hash; + } + + private boolean migrateOneLocation(int locationToMigrate) { + final int currentStateValue = alternateOutputPosition.getUnsafe(locationToMigrate); + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + return false; + } + final Object k0 = alternateKeySource0.getUnsafe(locationToMigrate); + final int k1 = alternateKeySource1.getUnsafe(locationToMigrate); + final int hash = hash(k0, k1); + int destinationTableLocation = hashToTableLocation(hash); + while (mainOutputPosition.getUnsafe(destinationTableLocation) != EMPTY_OUTPUT_POSITION) { + destinationTableLocation = nextTableLocation(destinationTableLocation); + } + mainKeySource0.set(destinationTableLocation, k0); + alternateKeySource0.set(locationToMigrate, null); + mainKeySource1.set(destinationTableLocation, k1); + mainOutputPosition.set(destinationTableLocation, currentStateValue); + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + alternateOutputPosition.set(locationToMigrate, EMPTY_OUTPUT_POSITION); + return true; + } + + @Override + protected int rehashInternalPartial(int entriesToRehash) { + int rehashedEntries = 0; + while (rehashPointer > 0 && rehashedEntries < entriesToRehash) { + if (migrateOneLocation(--rehashPointer)) { + rehashedEntries++; + } + } + return rehashedEntries; + } + + @Override + protected void newAlternate() { + super.newAlternate(); + this.mainKeySource0 = (ImmutableObjectArraySource)super.mainKeySources[0]; + this.alternateKeySource0 = (ImmutableObjectArraySource)super.alternateKeySources[0]; + this.mainKeySource1 = (ImmutableIntArraySource)super.mainKeySources[1]; + this.alternateKeySource1 = (ImmutableIntArraySource)super.alternateKeySources[1]; + } + + @Override + protected void clearAlternate() { + super.clearAlternate(); + this.alternateKeySource0 = null; + this.alternateKeySource1 = null; + } + + @Override + protected void migrateFront() { + int location = 0; + while (migrateOneLocation(location++)); + } + + @Override + protected void rehashInternalFull(final int oldSize) { + final Object[] destKeyArray0 = new Object[tableSize]; + final int[] destKeyArray1 = new int[tableSize]; + final int[] destState = new int[tableSize]; + Arrays.fill(destState, EMPTY_OUTPUT_POSITION); + final Object [] originalKeyArray0 = mainKeySource0.getArray(); + mainKeySource0.setArray(destKeyArray0); + final int [] originalKeyArray1 = mainKeySource1.getArray(); + mainKeySource1.setArray(destKeyArray1); + final int [] originalStateArray = mainOutputPosition.getArray(); + mainOutputPosition.setArray(destState); + for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + continue; + } + final Object k0 = originalKeyArray0[sourceBucket]; + final int k1 = originalKeyArray1[sourceBucket]; + final int hash = hash(k0, k1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; + while (true) { + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + break; + } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); + } + } + } + + @Override + public int findPositionForKey(Object key) { + final Object [] ka = (Object[])key; + final Object k0 = ka[0]; + final int k1 = TypeUtils.unbox((Integer)ka[1]); + int hash = hash(k0, k1); + int tableLocation = hashToTableLocation(hash); + final int firstTableLocation = tableLocation; + while (true) { + final int positionValue = mainOutputPosition.getUnsafe(tableLocation); + if (positionValue == EMPTY_OUTPUT_POSITION) { + int alternateTableLocation = hashToTableLocationAlternate(hash); + if (alternateTableLocation >= rehashPointer) { + return -1; + } + final int firstAlternateTableLocation = alternateTableLocation; + while (true) { + final int alternatePositionValue = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (alternatePositionValue == EMPTY_OUTPUT_POSITION) { + return -1; + } + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + return alternatePositionValue; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + return positionValue; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherObjectLong.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherObjectLong.java new file mode 100644 index 00000000000..bea579c6fee --- /dev/null +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherObjectLong.java @@ -0,0 +1,390 @@ +// DO NOT EDIT THIS CLASS, AUTOMATICALLY GENERATED BY io.deephaven.engine.table.impl.by.typed.TypedHasherFactory +// Copyright (c) 2016-2022 Deephaven Data Labs and Patent Pending +// +package io.deephaven.engine.table.impl.by.typed.incopenagg.gen; + +import static io.deephaven.util.compare.LongComparisons.eq; +import static io.deephaven.util.compare.ObjectComparisons.eq; + +import io.deephaven.base.verify.Assert; +import io.deephaven.chunk.Chunk; +import io.deephaven.chunk.LongChunk; +import io.deephaven.chunk.ObjectChunk; +import io.deephaven.chunk.WritableIntChunk; +import io.deephaven.chunk.attributes.Values; +import io.deephaven.chunk.util.hashing.LongChunkHasher; +import io.deephaven.chunk.util.hashing.ObjectChunkHasher; +import io.deephaven.engine.rowset.RowSequence; +import io.deephaven.engine.rowset.chunkattributes.RowKeys; +import io.deephaven.engine.table.ColumnSource; +import io.deephaven.engine.table.impl.by.IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableLongArraySource; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableObjectArraySource; +import io.deephaven.util.type.TypeUtils; +import java.lang.Long; +import java.lang.Object; +import java.lang.Override; +import java.util.Arrays; + +final class IncrementalAggOpenHasherObjectLong extends IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase { + private ImmutableObjectArraySource mainKeySource0; + + private ImmutableObjectArraySource alternateKeySource0; + + private ImmutableLongArraySource mainKeySource1; + + private ImmutableLongArraySource alternateKeySource1; + + public IncrementalAggOpenHasherObjectLong(ColumnSource[] tableKeySources, int tableSize, + double maximumLoadFactor, double targetLoadFactor) { + super(tableKeySources, tableSize, maximumLoadFactor); + this.mainKeySource0 = (ImmutableObjectArraySource) super.mainKeySources[0]; + this.mainKeySource0.ensureCapacity(tableSize); + this.mainKeySource1 = (ImmutableLongArraySource) super.mainKeySources[1]; + this.mainKeySource1.ensureCapacity(tableSize); + } + + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + + private int alternateNextTableLocation(int tableLocation) { + return (tableLocation + 1) & (alternateTableSize - 1); + } + + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final ObjectChunk keyChunk0 = sourceKeyChunks[0].asObjectChunk(); + final LongChunk keyChunk1 = sourceKeyChunks[1].asLongChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final Object k0 = keyChunk0.get(chunkPosition); + final long k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void buildForUpdate(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk reincarnatedPositions) { + final ObjectChunk keyChunk0 = sourceKeyChunks[0].asObjectChunk(); + final LongChunk keyChunk1 = sourceKeyChunks[1].asLongChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final Object k0 = keyChunk0.get(chunkPosition); + final long k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void doRemoveProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk emptiedPositions) { + final ObjectChunk keyChunk0 = sourceKeyChunks[0].asObjectChunk(); + final LongChunk keyChunk1 = sourceKeyChunks[1].asLongChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final Object k0 = keyChunk0.get(chunkPosition); + final long k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + protected void doModifyProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final ObjectChunk keyChunk0 = sourceKeyChunks[0].asObjectChunk(); + final LongChunk keyChunk1 = sourceKeyChunks[1].asLongChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final Object k0 = keyChunk0.get(chunkPosition); + final long k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + private static int hash(Object k0, long k1) { + int hash = ObjectChunkHasher.hashInitialSingle(k0); + hash = LongChunkHasher.hashUpdateSingle(hash, k1); + return hash; + } + + private boolean migrateOneLocation(int locationToMigrate) { + final int currentStateValue = alternateOutputPosition.getUnsafe(locationToMigrate); + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + return false; + } + final Object k0 = alternateKeySource0.getUnsafe(locationToMigrate); + final long k1 = alternateKeySource1.getUnsafe(locationToMigrate); + final int hash = hash(k0, k1); + int destinationTableLocation = hashToTableLocation(hash); + while (mainOutputPosition.getUnsafe(destinationTableLocation) != EMPTY_OUTPUT_POSITION) { + destinationTableLocation = nextTableLocation(destinationTableLocation); + } + mainKeySource0.set(destinationTableLocation, k0); + alternateKeySource0.set(locationToMigrate, null); + mainKeySource1.set(destinationTableLocation, k1); + mainOutputPosition.set(destinationTableLocation, currentStateValue); + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + alternateOutputPosition.set(locationToMigrate, EMPTY_OUTPUT_POSITION); + return true; + } + + @Override + protected int rehashInternalPartial(int entriesToRehash) { + int rehashedEntries = 0; + while (rehashPointer > 0 && rehashedEntries < entriesToRehash) { + if (migrateOneLocation(--rehashPointer)) { + rehashedEntries++; + } + } + return rehashedEntries; + } + + @Override + protected void newAlternate() { + super.newAlternate(); + this.mainKeySource0 = (ImmutableObjectArraySource)super.mainKeySources[0]; + this.alternateKeySource0 = (ImmutableObjectArraySource)super.alternateKeySources[0]; + this.mainKeySource1 = (ImmutableLongArraySource)super.mainKeySources[1]; + this.alternateKeySource1 = (ImmutableLongArraySource)super.alternateKeySources[1]; + } + + @Override + protected void clearAlternate() { + super.clearAlternate(); + this.alternateKeySource0 = null; + this.alternateKeySource1 = null; + } + + @Override + protected void migrateFront() { + int location = 0; + while (migrateOneLocation(location++)); + } + + @Override + protected void rehashInternalFull(final int oldSize) { + final Object[] destKeyArray0 = new Object[tableSize]; + final long[] destKeyArray1 = new long[tableSize]; + final int[] destState = new int[tableSize]; + Arrays.fill(destState, EMPTY_OUTPUT_POSITION); + final Object [] originalKeyArray0 = mainKeySource0.getArray(); + mainKeySource0.setArray(destKeyArray0); + final long [] originalKeyArray1 = mainKeySource1.getArray(); + mainKeySource1.setArray(destKeyArray1); + final int [] originalStateArray = mainOutputPosition.getArray(); + mainOutputPosition.setArray(destState); + for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + continue; + } + final Object k0 = originalKeyArray0[sourceBucket]; + final long k1 = originalKeyArray1[sourceBucket]; + final int hash = hash(k0, k1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; + while (true) { + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + break; + } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); + } + } + } + + @Override + public int findPositionForKey(Object key) { + final Object [] ka = (Object[])key; + final Object k0 = ka[0]; + final long k1 = TypeUtils.unbox((Long)ka[1]); + int hash = hash(k0, k1); + int tableLocation = hashToTableLocation(hash); + final int firstTableLocation = tableLocation; + while (true) { + final int positionValue = mainOutputPosition.getUnsafe(tableLocation); + if (positionValue == EMPTY_OUTPUT_POSITION) { + int alternateTableLocation = hashToTableLocationAlternate(hash); + if (alternateTableLocation >= rehashPointer) { + return -1; + } + final int firstAlternateTableLocation = alternateTableLocation; + while (true) { + final int alternatePositionValue = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (alternatePositionValue == EMPTY_OUTPUT_POSITION) { + return -1; + } + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + return alternatePositionValue; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + return positionValue; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherObjectObject.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherObjectObject.java new file mode 100644 index 00000000000..a8c78380afb --- /dev/null +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherObjectObject.java @@ -0,0 +1,385 @@ +// DO NOT EDIT THIS CLASS, AUTOMATICALLY GENERATED BY io.deephaven.engine.table.impl.by.typed.TypedHasherFactory +// Copyright (c) 2016-2022 Deephaven Data Labs and Patent Pending +// +package io.deephaven.engine.table.impl.by.typed.incopenagg.gen; + +import static io.deephaven.util.compare.ObjectComparisons.eq; + +import io.deephaven.base.verify.Assert; +import io.deephaven.chunk.Chunk; +import io.deephaven.chunk.ObjectChunk; +import io.deephaven.chunk.WritableIntChunk; +import io.deephaven.chunk.attributes.Values; +import io.deephaven.chunk.util.hashing.ObjectChunkHasher; +import io.deephaven.engine.rowset.RowSequence; +import io.deephaven.engine.rowset.chunkattributes.RowKeys; +import io.deephaven.engine.table.ColumnSource; +import io.deephaven.engine.table.impl.by.IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableObjectArraySource; +import java.lang.Object; +import java.lang.Override; +import java.util.Arrays; + +final class IncrementalAggOpenHasherObjectObject extends IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase { + private ImmutableObjectArraySource mainKeySource0; + + private ImmutableObjectArraySource alternateKeySource0; + + private ImmutableObjectArraySource mainKeySource1; + + private ImmutableObjectArraySource alternateKeySource1; + + public IncrementalAggOpenHasherObjectObject(ColumnSource[] tableKeySources, int tableSize, + double maximumLoadFactor, double targetLoadFactor) { + super(tableKeySources, tableSize, maximumLoadFactor); + this.mainKeySource0 = (ImmutableObjectArraySource) super.mainKeySources[0]; + this.mainKeySource0.ensureCapacity(tableSize); + this.mainKeySource1 = (ImmutableObjectArraySource) super.mainKeySources[1]; + this.mainKeySource1.ensureCapacity(tableSize); + } + + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + + private int alternateNextTableLocation(int tableLocation) { + return (tableLocation + 1) & (alternateTableSize - 1); + } + + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final ObjectChunk keyChunk0 = sourceKeyChunks[0].asObjectChunk(); + final ObjectChunk keyChunk1 = sourceKeyChunks[1].asObjectChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final Object k0 = keyChunk0.get(chunkPosition); + final Object k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void buildForUpdate(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk reincarnatedPositions) { + final ObjectChunk keyChunk0 = sourceKeyChunks[0].asObjectChunk(); + final ObjectChunk keyChunk1 = sourceKeyChunks[1].asObjectChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final Object k0 = keyChunk0.get(chunkPosition); + final Object k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void doRemoveProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk emptiedPositions) { + final ObjectChunk keyChunk0 = sourceKeyChunks[0].asObjectChunk(); + final ObjectChunk keyChunk1 = sourceKeyChunks[1].asObjectChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final Object k0 = keyChunk0.get(chunkPosition); + final Object k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + protected void doModifyProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final ObjectChunk keyChunk0 = sourceKeyChunks[0].asObjectChunk(); + final ObjectChunk keyChunk1 = sourceKeyChunks[1].asObjectChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final Object k0 = keyChunk0.get(chunkPosition); + final Object k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + private static int hash(Object k0, Object k1) { + int hash = ObjectChunkHasher.hashInitialSingle(k0); + hash = ObjectChunkHasher.hashUpdateSingle(hash, k1); + return hash; + } + + private boolean migrateOneLocation(int locationToMigrate) { + final int currentStateValue = alternateOutputPosition.getUnsafe(locationToMigrate); + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + return false; + } + final Object k0 = alternateKeySource0.getUnsafe(locationToMigrate); + final Object k1 = alternateKeySource1.getUnsafe(locationToMigrate); + final int hash = hash(k0, k1); + int destinationTableLocation = hashToTableLocation(hash); + while (mainOutputPosition.getUnsafe(destinationTableLocation) != EMPTY_OUTPUT_POSITION) { + destinationTableLocation = nextTableLocation(destinationTableLocation); + } + mainKeySource0.set(destinationTableLocation, k0); + alternateKeySource0.set(locationToMigrate, null); + mainKeySource1.set(destinationTableLocation, k1); + alternateKeySource1.set(locationToMigrate, null); + mainOutputPosition.set(destinationTableLocation, currentStateValue); + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + alternateOutputPosition.set(locationToMigrate, EMPTY_OUTPUT_POSITION); + return true; + } + + @Override + protected int rehashInternalPartial(int entriesToRehash) { + int rehashedEntries = 0; + while (rehashPointer > 0 && rehashedEntries < entriesToRehash) { + if (migrateOneLocation(--rehashPointer)) { + rehashedEntries++; + } + } + return rehashedEntries; + } + + @Override + protected void newAlternate() { + super.newAlternate(); + this.mainKeySource0 = (ImmutableObjectArraySource)super.mainKeySources[0]; + this.alternateKeySource0 = (ImmutableObjectArraySource)super.alternateKeySources[0]; + this.mainKeySource1 = (ImmutableObjectArraySource)super.mainKeySources[1]; + this.alternateKeySource1 = (ImmutableObjectArraySource)super.alternateKeySources[1]; + } + + @Override + protected void clearAlternate() { + super.clearAlternate(); + this.alternateKeySource0 = null; + this.alternateKeySource1 = null; + } + + @Override + protected void migrateFront() { + int location = 0; + while (migrateOneLocation(location++)); + } + + @Override + protected void rehashInternalFull(final int oldSize) { + final Object[] destKeyArray0 = new Object[tableSize]; + final Object[] destKeyArray1 = new Object[tableSize]; + final int[] destState = new int[tableSize]; + Arrays.fill(destState, EMPTY_OUTPUT_POSITION); + final Object [] originalKeyArray0 = mainKeySource0.getArray(); + mainKeySource0.setArray(destKeyArray0); + final Object [] originalKeyArray1 = mainKeySource1.getArray(); + mainKeySource1.setArray(destKeyArray1); + final int [] originalStateArray = mainOutputPosition.getArray(); + mainOutputPosition.setArray(destState); + for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + continue; + } + final Object k0 = originalKeyArray0[sourceBucket]; + final Object k1 = originalKeyArray1[sourceBucket]; + final int hash = hash(k0, k1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; + while (true) { + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + break; + } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); + } + } + } + + @Override + public int findPositionForKey(Object key) { + final Object [] ka = (Object[])key; + final Object k0 = ka[0]; + final Object k1 = ka[1]; + int hash = hash(k0, k1); + int tableLocation = hashToTableLocation(hash); + final int firstTableLocation = tableLocation; + while (true) { + final int positionValue = mainOutputPosition.getUnsafe(tableLocation); + if (positionValue == EMPTY_OUTPUT_POSITION) { + int alternateTableLocation = hashToTableLocationAlternate(hash); + if (alternateTableLocation >= rehashPointer) { + return -1; + } + final int firstAlternateTableLocation = alternateTableLocation; + while (true) { + final int alternatePositionValue = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (alternatePositionValue == EMPTY_OUTPUT_POSITION) { + return -1; + } + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + return alternatePositionValue; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + return positionValue; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherObjectShort.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherObjectShort.java new file mode 100644 index 00000000000..1c9058ed0c7 --- /dev/null +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherObjectShort.java @@ -0,0 +1,390 @@ +// DO NOT EDIT THIS CLASS, AUTOMATICALLY GENERATED BY io.deephaven.engine.table.impl.by.typed.TypedHasherFactory +// Copyright (c) 2016-2022 Deephaven Data Labs and Patent Pending +// +package io.deephaven.engine.table.impl.by.typed.incopenagg.gen; + +import static io.deephaven.util.compare.ObjectComparisons.eq; +import static io.deephaven.util.compare.ShortComparisons.eq; + +import io.deephaven.base.verify.Assert; +import io.deephaven.chunk.Chunk; +import io.deephaven.chunk.ObjectChunk; +import io.deephaven.chunk.ShortChunk; +import io.deephaven.chunk.WritableIntChunk; +import io.deephaven.chunk.attributes.Values; +import io.deephaven.chunk.util.hashing.ObjectChunkHasher; +import io.deephaven.chunk.util.hashing.ShortChunkHasher; +import io.deephaven.engine.rowset.RowSequence; +import io.deephaven.engine.rowset.chunkattributes.RowKeys; +import io.deephaven.engine.table.ColumnSource; +import io.deephaven.engine.table.impl.by.IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableObjectArraySource; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableShortArraySource; +import io.deephaven.util.type.TypeUtils; +import java.lang.Object; +import java.lang.Override; +import java.lang.Short; +import java.util.Arrays; + +final class IncrementalAggOpenHasherObjectShort extends IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase { + private ImmutableObjectArraySource mainKeySource0; + + private ImmutableObjectArraySource alternateKeySource0; + + private ImmutableShortArraySource mainKeySource1; + + private ImmutableShortArraySource alternateKeySource1; + + public IncrementalAggOpenHasherObjectShort(ColumnSource[] tableKeySources, int tableSize, + double maximumLoadFactor, double targetLoadFactor) { + super(tableKeySources, tableSize, maximumLoadFactor); + this.mainKeySource0 = (ImmutableObjectArraySource) super.mainKeySources[0]; + this.mainKeySource0.ensureCapacity(tableSize); + this.mainKeySource1 = (ImmutableShortArraySource) super.mainKeySources[1]; + this.mainKeySource1.ensureCapacity(tableSize); + } + + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + + private int alternateNextTableLocation(int tableLocation) { + return (tableLocation + 1) & (alternateTableSize - 1); + } + + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final ObjectChunk keyChunk0 = sourceKeyChunks[0].asObjectChunk(); + final ShortChunk keyChunk1 = sourceKeyChunks[1].asShortChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final Object k0 = keyChunk0.get(chunkPosition); + final short k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void buildForUpdate(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk reincarnatedPositions) { + final ObjectChunk keyChunk0 = sourceKeyChunks[0].asObjectChunk(); + final ShortChunk keyChunk1 = sourceKeyChunks[1].asShortChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final Object k0 = keyChunk0.get(chunkPosition); + final short k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void doRemoveProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk emptiedPositions) { + final ObjectChunk keyChunk0 = sourceKeyChunks[0].asObjectChunk(); + final ShortChunk keyChunk1 = sourceKeyChunks[1].asShortChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final Object k0 = keyChunk0.get(chunkPosition); + final short k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + protected void doModifyProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final ObjectChunk keyChunk0 = sourceKeyChunks[0].asObjectChunk(); + final ShortChunk keyChunk1 = sourceKeyChunks[1].asShortChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final Object k0 = keyChunk0.get(chunkPosition); + final short k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + private static int hash(Object k0, short k1) { + int hash = ObjectChunkHasher.hashInitialSingle(k0); + hash = ShortChunkHasher.hashUpdateSingle(hash, k1); + return hash; + } + + private boolean migrateOneLocation(int locationToMigrate) { + final int currentStateValue = alternateOutputPosition.getUnsafe(locationToMigrate); + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + return false; + } + final Object k0 = alternateKeySource0.getUnsafe(locationToMigrate); + final short k1 = alternateKeySource1.getUnsafe(locationToMigrate); + final int hash = hash(k0, k1); + int destinationTableLocation = hashToTableLocation(hash); + while (mainOutputPosition.getUnsafe(destinationTableLocation) != EMPTY_OUTPUT_POSITION) { + destinationTableLocation = nextTableLocation(destinationTableLocation); + } + mainKeySource0.set(destinationTableLocation, k0); + alternateKeySource0.set(locationToMigrate, null); + mainKeySource1.set(destinationTableLocation, k1); + mainOutputPosition.set(destinationTableLocation, currentStateValue); + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + alternateOutputPosition.set(locationToMigrate, EMPTY_OUTPUT_POSITION); + return true; + } + + @Override + protected int rehashInternalPartial(int entriesToRehash) { + int rehashedEntries = 0; + while (rehashPointer > 0 && rehashedEntries < entriesToRehash) { + if (migrateOneLocation(--rehashPointer)) { + rehashedEntries++; + } + } + return rehashedEntries; + } + + @Override + protected void newAlternate() { + super.newAlternate(); + this.mainKeySource0 = (ImmutableObjectArraySource)super.mainKeySources[0]; + this.alternateKeySource0 = (ImmutableObjectArraySource)super.alternateKeySources[0]; + this.mainKeySource1 = (ImmutableShortArraySource)super.mainKeySources[1]; + this.alternateKeySource1 = (ImmutableShortArraySource)super.alternateKeySources[1]; + } + + @Override + protected void clearAlternate() { + super.clearAlternate(); + this.alternateKeySource0 = null; + this.alternateKeySource1 = null; + } + + @Override + protected void migrateFront() { + int location = 0; + while (migrateOneLocation(location++)); + } + + @Override + protected void rehashInternalFull(final int oldSize) { + final Object[] destKeyArray0 = new Object[tableSize]; + final short[] destKeyArray1 = new short[tableSize]; + final int[] destState = new int[tableSize]; + Arrays.fill(destState, EMPTY_OUTPUT_POSITION); + final Object [] originalKeyArray0 = mainKeySource0.getArray(); + mainKeySource0.setArray(destKeyArray0); + final short [] originalKeyArray1 = mainKeySource1.getArray(); + mainKeySource1.setArray(destKeyArray1); + final int [] originalStateArray = mainOutputPosition.getArray(); + mainOutputPosition.setArray(destState); + for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + continue; + } + final Object k0 = originalKeyArray0[sourceBucket]; + final short k1 = originalKeyArray1[sourceBucket]; + final int hash = hash(k0, k1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; + while (true) { + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + break; + } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); + } + } + } + + @Override + public int findPositionForKey(Object key) { + final Object [] ka = (Object[])key; + final Object k0 = ka[0]; + final short k1 = TypeUtils.unbox((Short)ka[1]); + int hash = hash(k0, k1); + int tableLocation = hashToTableLocation(hash); + final int firstTableLocation = tableLocation; + while (true) { + final int positionValue = mainOutputPosition.getUnsafe(tableLocation); + if (positionValue == EMPTY_OUTPUT_POSITION) { + int alternateTableLocation = hashToTableLocationAlternate(hash); + if (alternateTableLocation >= rehashPointer) { + return -1; + } + final int firstAlternateTableLocation = alternateTableLocation; + while (true) { + final int alternatePositionValue = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (alternatePositionValue == EMPTY_OUTPUT_POSITION) { + return -1; + } + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + return alternatePositionValue; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + return positionValue; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherShort.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherShort.java new file mode 100644 index 00000000000..fb0e8e132d7 --- /dev/null +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherShort.java @@ -0,0 +1,356 @@ +// DO NOT EDIT THIS CLASS, AUTOMATICALLY GENERATED BY io.deephaven.engine.table.impl.by.typed.TypedHasherFactory +// Copyright (c) 2016-2022 Deephaven Data Labs and Patent Pending +// +package io.deephaven.engine.table.impl.by.typed.incopenagg.gen; + +import static io.deephaven.util.compare.ShortComparisons.eq; + +import io.deephaven.base.verify.Assert; +import io.deephaven.chunk.Chunk; +import io.deephaven.chunk.ShortChunk; +import io.deephaven.chunk.WritableIntChunk; +import io.deephaven.chunk.attributes.Values; +import io.deephaven.chunk.util.hashing.ShortChunkHasher; +import io.deephaven.engine.rowset.RowSequence; +import io.deephaven.engine.rowset.chunkattributes.RowKeys; +import io.deephaven.engine.table.ColumnSource; +import io.deephaven.engine.table.impl.by.IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableShortArraySource; +import io.deephaven.util.type.TypeUtils; +import java.lang.Object; +import java.lang.Override; +import java.lang.Short; +import java.util.Arrays; + +final class IncrementalAggOpenHasherShort extends IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase { + private ImmutableShortArraySource mainKeySource0; + + private ImmutableShortArraySource alternateKeySource0; + + public IncrementalAggOpenHasherShort(ColumnSource[] tableKeySources, int tableSize, + double maximumLoadFactor, double targetLoadFactor) { + super(tableKeySources, tableSize, maximumLoadFactor); + this.mainKeySource0 = (ImmutableShortArraySource) super.mainKeySources[0]; + this.mainKeySource0.ensureCapacity(tableSize); + } + + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + + private int alternateNextTableLocation(int tableLocation) { + return (tableLocation + 1) & (alternateTableSize - 1); + } + + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final ShortChunk keyChunk0 = sourceKeyChunks[0].asShortChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final short k0 = keyChunk0.get(chunkPosition); + final int hash = hash(k0); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void buildForUpdate(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk reincarnatedPositions) { + final ShortChunk keyChunk0 = sourceKeyChunks[0].asShortChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final short k0 = keyChunk0.get(chunkPosition); + final int hash = hash(k0); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void doRemoveProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk emptiedPositions) { + final ShortChunk keyChunk0 = sourceKeyChunks[0].asShortChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final short k0 = keyChunk0.get(chunkPosition); + final int hash = hash(k0); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + protected void doModifyProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final ShortChunk keyChunk0 = sourceKeyChunks[0].asShortChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final short k0 = keyChunk0.get(chunkPosition); + final int hash = hash(k0); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0)) { + outputPositions.set(chunkPosition, outputPosition); + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0)) { + outputPositions.set(chunkPosition, outputPosition); + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + private static int hash(short k0) { + int hash = ShortChunkHasher.hashInitialSingle(k0); + return hash; + } + + private boolean migrateOneLocation(int locationToMigrate) { + final int currentStateValue = alternateOutputPosition.getUnsafe(locationToMigrate); + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + return false; + } + final short k0 = alternateKeySource0.getUnsafe(locationToMigrate); + final int hash = hash(k0); + int destinationTableLocation = hashToTableLocation(hash); + while (mainOutputPosition.getUnsafe(destinationTableLocation) != EMPTY_OUTPUT_POSITION) { + destinationTableLocation = nextTableLocation(destinationTableLocation); + } + mainKeySource0.set(destinationTableLocation, k0); + mainOutputPosition.set(destinationTableLocation, currentStateValue); + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + alternateOutputPosition.set(locationToMigrate, EMPTY_OUTPUT_POSITION); + return true; + } + + @Override + protected int rehashInternalPartial(int entriesToRehash) { + int rehashedEntries = 0; + while (rehashPointer > 0 && rehashedEntries < entriesToRehash) { + if (migrateOneLocation(--rehashPointer)) { + rehashedEntries++; + } + } + return rehashedEntries; + } + + @Override + protected void newAlternate() { + super.newAlternate(); + this.mainKeySource0 = (ImmutableShortArraySource)super.mainKeySources[0]; + this.alternateKeySource0 = (ImmutableShortArraySource)super.alternateKeySources[0]; + } + + @Override + protected void clearAlternate() { + super.clearAlternate(); + this.alternateKeySource0 = null; + } + + @Override + protected void migrateFront() { + int location = 0; + while (migrateOneLocation(location++)); + } + + @Override + protected void rehashInternalFull(final int oldSize) { + final short[] destKeyArray0 = new short[tableSize]; + final int[] destState = new int[tableSize]; + Arrays.fill(destState, EMPTY_OUTPUT_POSITION); + final short [] originalKeyArray0 = mainKeySource0.getArray(); + mainKeySource0.setArray(destKeyArray0); + final int [] originalStateArray = mainOutputPosition.getArray(); + mainOutputPosition.setArray(destState); + for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + continue; + } + final short k0 = originalKeyArray0[sourceBucket]; + final int hash = hash(k0); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; + while (true) { + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + break; + } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); + } + } + } + + @Override + public int findPositionForKey(Object key) { + final short k0 = TypeUtils.unbox((Short)key); + int hash = hash(k0); + int tableLocation = hashToTableLocation(hash); + final int firstTableLocation = tableLocation; + while (true) { + final int positionValue = mainOutputPosition.getUnsafe(tableLocation); + if (positionValue == EMPTY_OUTPUT_POSITION) { + int alternateTableLocation = hashToTableLocationAlternate(hash); + if (alternateTableLocation >= rehashPointer) { + return -1; + } + final int firstAlternateTableLocation = alternateTableLocation; + while (true) { + final int alternatePositionValue = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (alternatePositionValue == EMPTY_OUTPUT_POSITION) { + return -1; + } + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0)) { + return alternatePositionValue; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (eq(mainKeySource0.getUnsafe(tableLocation), k0)) { + return positionValue; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherShortByte.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherShortByte.java new file mode 100644 index 00000000000..fc2eaa5a421 --- /dev/null +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherShortByte.java @@ -0,0 +1,390 @@ +// DO NOT EDIT THIS CLASS, AUTOMATICALLY GENERATED BY io.deephaven.engine.table.impl.by.typed.TypedHasherFactory +// Copyright (c) 2016-2022 Deephaven Data Labs and Patent Pending +// +package io.deephaven.engine.table.impl.by.typed.incopenagg.gen; + +import static io.deephaven.util.compare.ByteComparisons.eq; +import static io.deephaven.util.compare.ShortComparisons.eq; + +import io.deephaven.base.verify.Assert; +import io.deephaven.chunk.ByteChunk; +import io.deephaven.chunk.Chunk; +import io.deephaven.chunk.ShortChunk; +import io.deephaven.chunk.WritableIntChunk; +import io.deephaven.chunk.attributes.Values; +import io.deephaven.chunk.util.hashing.ByteChunkHasher; +import io.deephaven.chunk.util.hashing.ShortChunkHasher; +import io.deephaven.engine.rowset.RowSequence; +import io.deephaven.engine.rowset.chunkattributes.RowKeys; +import io.deephaven.engine.table.ColumnSource; +import io.deephaven.engine.table.impl.by.IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableByteArraySource; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableShortArraySource; +import io.deephaven.util.type.TypeUtils; +import java.lang.Byte; +import java.lang.Object; +import java.lang.Override; +import java.lang.Short; +import java.util.Arrays; + +final class IncrementalAggOpenHasherShortByte extends IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase { + private ImmutableShortArraySource mainKeySource0; + + private ImmutableShortArraySource alternateKeySource0; + + private ImmutableByteArraySource mainKeySource1; + + private ImmutableByteArraySource alternateKeySource1; + + public IncrementalAggOpenHasherShortByte(ColumnSource[] tableKeySources, int tableSize, + double maximumLoadFactor, double targetLoadFactor) { + super(tableKeySources, tableSize, maximumLoadFactor); + this.mainKeySource0 = (ImmutableShortArraySource) super.mainKeySources[0]; + this.mainKeySource0.ensureCapacity(tableSize); + this.mainKeySource1 = (ImmutableByteArraySource) super.mainKeySources[1]; + this.mainKeySource1.ensureCapacity(tableSize); + } + + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + + private int alternateNextTableLocation(int tableLocation) { + return (tableLocation + 1) & (alternateTableSize - 1); + } + + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final ShortChunk keyChunk0 = sourceKeyChunks[0].asShortChunk(); + final ByteChunk keyChunk1 = sourceKeyChunks[1].asByteChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final short k0 = keyChunk0.get(chunkPosition); + final byte k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void buildForUpdate(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk reincarnatedPositions) { + final ShortChunk keyChunk0 = sourceKeyChunks[0].asShortChunk(); + final ByteChunk keyChunk1 = sourceKeyChunks[1].asByteChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final short k0 = keyChunk0.get(chunkPosition); + final byte k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void doRemoveProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk emptiedPositions) { + final ShortChunk keyChunk0 = sourceKeyChunks[0].asShortChunk(); + final ByteChunk keyChunk1 = sourceKeyChunks[1].asByteChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final short k0 = keyChunk0.get(chunkPosition); + final byte k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + protected void doModifyProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final ShortChunk keyChunk0 = sourceKeyChunks[0].asShortChunk(); + final ByteChunk keyChunk1 = sourceKeyChunks[1].asByteChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final short k0 = keyChunk0.get(chunkPosition); + final byte k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + private static int hash(short k0, byte k1) { + int hash = ShortChunkHasher.hashInitialSingle(k0); + hash = ByteChunkHasher.hashUpdateSingle(hash, k1); + return hash; + } + + private boolean migrateOneLocation(int locationToMigrate) { + final int currentStateValue = alternateOutputPosition.getUnsafe(locationToMigrate); + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + return false; + } + final short k0 = alternateKeySource0.getUnsafe(locationToMigrate); + final byte k1 = alternateKeySource1.getUnsafe(locationToMigrate); + final int hash = hash(k0, k1); + int destinationTableLocation = hashToTableLocation(hash); + while (mainOutputPosition.getUnsafe(destinationTableLocation) != EMPTY_OUTPUT_POSITION) { + destinationTableLocation = nextTableLocation(destinationTableLocation); + } + mainKeySource0.set(destinationTableLocation, k0); + mainKeySource1.set(destinationTableLocation, k1); + mainOutputPosition.set(destinationTableLocation, currentStateValue); + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + alternateOutputPosition.set(locationToMigrate, EMPTY_OUTPUT_POSITION); + return true; + } + + @Override + protected int rehashInternalPartial(int entriesToRehash) { + int rehashedEntries = 0; + while (rehashPointer > 0 && rehashedEntries < entriesToRehash) { + if (migrateOneLocation(--rehashPointer)) { + rehashedEntries++; + } + } + return rehashedEntries; + } + + @Override + protected void newAlternate() { + super.newAlternate(); + this.mainKeySource0 = (ImmutableShortArraySource)super.mainKeySources[0]; + this.alternateKeySource0 = (ImmutableShortArraySource)super.alternateKeySources[0]; + this.mainKeySource1 = (ImmutableByteArraySource)super.mainKeySources[1]; + this.alternateKeySource1 = (ImmutableByteArraySource)super.alternateKeySources[1]; + } + + @Override + protected void clearAlternate() { + super.clearAlternate(); + this.alternateKeySource0 = null; + this.alternateKeySource1 = null; + } + + @Override + protected void migrateFront() { + int location = 0; + while (migrateOneLocation(location++)); + } + + @Override + protected void rehashInternalFull(final int oldSize) { + final short[] destKeyArray0 = new short[tableSize]; + final byte[] destKeyArray1 = new byte[tableSize]; + final int[] destState = new int[tableSize]; + Arrays.fill(destState, EMPTY_OUTPUT_POSITION); + final short [] originalKeyArray0 = mainKeySource0.getArray(); + mainKeySource0.setArray(destKeyArray0); + final byte [] originalKeyArray1 = mainKeySource1.getArray(); + mainKeySource1.setArray(destKeyArray1); + final int [] originalStateArray = mainOutputPosition.getArray(); + mainOutputPosition.setArray(destState); + for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + continue; + } + final short k0 = originalKeyArray0[sourceBucket]; + final byte k1 = originalKeyArray1[sourceBucket]; + final int hash = hash(k0, k1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; + while (true) { + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + break; + } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); + } + } + } + + @Override + public int findPositionForKey(Object key) { + final Object [] ka = (Object[])key; + final short k0 = TypeUtils.unbox((Short)ka[0]); + final byte k1 = TypeUtils.unbox((Byte)ka[1]); + int hash = hash(k0, k1); + int tableLocation = hashToTableLocation(hash); + final int firstTableLocation = tableLocation; + while (true) { + final int positionValue = mainOutputPosition.getUnsafe(tableLocation); + if (positionValue == EMPTY_OUTPUT_POSITION) { + int alternateTableLocation = hashToTableLocationAlternate(hash); + if (alternateTableLocation >= rehashPointer) { + return -1; + } + final int firstAlternateTableLocation = alternateTableLocation; + while (true) { + final int alternatePositionValue = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (alternatePositionValue == EMPTY_OUTPUT_POSITION) { + return -1; + } + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + return alternatePositionValue; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + return positionValue; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherShortChar.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherShortChar.java new file mode 100644 index 00000000000..134b7536845 --- /dev/null +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherShortChar.java @@ -0,0 +1,390 @@ +// DO NOT EDIT THIS CLASS, AUTOMATICALLY GENERATED BY io.deephaven.engine.table.impl.by.typed.TypedHasherFactory +// Copyright (c) 2016-2022 Deephaven Data Labs and Patent Pending +// +package io.deephaven.engine.table.impl.by.typed.incopenagg.gen; + +import static io.deephaven.util.compare.CharComparisons.eq; +import static io.deephaven.util.compare.ShortComparisons.eq; + +import io.deephaven.base.verify.Assert; +import io.deephaven.chunk.CharChunk; +import io.deephaven.chunk.Chunk; +import io.deephaven.chunk.ShortChunk; +import io.deephaven.chunk.WritableIntChunk; +import io.deephaven.chunk.attributes.Values; +import io.deephaven.chunk.util.hashing.CharChunkHasher; +import io.deephaven.chunk.util.hashing.ShortChunkHasher; +import io.deephaven.engine.rowset.RowSequence; +import io.deephaven.engine.rowset.chunkattributes.RowKeys; +import io.deephaven.engine.table.ColumnSource; +import io.deephaven.engine.table.impl.by.IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableCharArraySource; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableShortArraySource; +import io.deephaven.util.type.TypeUtils; +import java.lang.Character; +import java.lang.Object; +import java.lang.Override; +import java.lang.Short; +import java.util.Arrays; + +final class IncrementalAggOpenHasherShortChar extends IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase { + private ImmutableShortArraySource mainKeySource0; + + private ImmutableShortArraySource alternateKeySource0; + + private ImmutableCharArraySource mainKeySource1; + + private ImmutableCharArraySource alternateKeySource1; + + public IncrementalAggOpenHasherShortChar(ColumnSource[] tableKeySources, int tableSize, + double maximumLoadFactor, double targetLoadFactor) { + super(tableKeySources, tableSize, maximumLoadFactor); + this.mainKeySource0 = (ImmutableShortArraySource) super.mainKeySources[0]; + this.mainKeySource0.ensureCapacity(tableSize); + this.mainKeySource1 = (ImmutableCharArraySource) super.mainKeySources[1]; + this.mainKeySource1.ensureCapacity(tableSize); + } + + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + + private int alternateNextTableLocation(int tableLocation) { + return (tableLocation + 1) & (alternateTableSize - 1); + } + + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final ShortChunk keyChunk0 = sourceKeyChunks[0].asShortChunk(); + final CharChunk keyChunk1 = sourceKeyChunks[1].asCharChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final short k0 = keyChunk0.get(chunkPosition); + final char k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void buildForUpdate(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk reincarnatedPositions) { + final ShortChunk keyChunk0 = sourceKeyChunks[0].asShortChunk(); + final CharChunk keyChunk1 = sourceKeyChunks[1].asCharChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final short k0 = keyChunk0.get(chunkPosition); + final char k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void doRemoveProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk emptiedPositions) { + final ShortChunk keyChunk0 = sourceKeyChunks[0].asShortChunk(); + final CharChunk keyChunk1 = sourceKeyChunks[1].asCharChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final short k0 = keyChunk0.get(chunkPosition); + final char k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + protected void doModifyProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final ShortChunk keyChunk0 = sourceKeyChunks[0].asShortChunk(); + final CharChunk keyChunk1 = sourceKeyChunks[1].asCharChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final short k0 = keyChunk0.get(chunkPosition); + final char k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + private static int hash(short k0, char k1) { + int hash = ShortChunkHasher.hashInitialSingle(k0); + hash = CharChunkHasher.hashUpdateSingle(hash, k1); + return hash; + } + + private boolean migrateOneLocation(int locationToMigrate) { + final int currentStateValue = alternateOutputPosition.getUnsafe(locationToMigrate); + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + return false; + } + final short k0 = alternateKeySource0.getUnsafe(locationToMigrate); + final char k1 = alternateKeySource1.getUnsafe(locationToMigrate); + final int hash = hash(k0, k1); + int destinationTableLocation = hashToTableLocation(hash); + while (mainOutputPosition.getUnsafe(destinationTableLocation) != EMPTY_OUTPUT_POSITION) { + destinationTableLocation = nextTableLocation(destinationTableLocation); + } + mainKeySource0.set(destinationTableLocation, k0); + mainKeySource1.set(destinationTableLocation, k1); + mainOutputPosition.set(destinationTableLocation, currentStateValue); + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + alternateOutputPosition.set(locationToMigrate, EMPTY_OUTPUT_POSITION); + return true; + } + + @Override + protected int rehashInternalPartial(int entriesToRehash) { + int rehashedEntries = 0; + while (rehashPointer > 0 && rehashedEntries < entriesToRehash) { + if (migrateOneLocation(--rehashPointer)) { + rehashedEntries++; + } + } + return rehashedEntries; + } + + @Override + protected void newAlternate() { + super.newAlternate(); + this.mainKeySource0 = (ImmutableShortArraySource)super.mainKeySources[0]; + this.alternateKeySource0 = (ImmutableShortArraySource)super.alternateKeySources[0]; + this.mainKeySource1 = (ImmutableCharArraySource)super.mainKeySources[1]; + this.alternateKeySource1 = (ImmutableCharArraySource)super.alternateKeySources[1]; + } + + @Override + protected void clearAlternate() { + super.clearAlternate(); + this.alternateKeySource0 = null; + this.alternateKeySource1 = null; + } + + @Override + protected void migrateFront() { + int location = 0; + while (migrateOneLocation(location++)); + } + + @Override + protected void rehashInternalFull(final int oldSize) { + final short[] destKeyArray0 = new short[tableSize]; + final char[] destKeyArray1 = new char[tableSize]; + final int[] destState = new int[tableSize]; + Arrays.fill(destState, EMPTY_OUTPUT_POSITION); + final short [] originalKeyArray0 = mainKeySource0.getArray(); + mainKeySource0.setArray(destKeyArray0); + final char [] originalKeyArray1 = mainKeySource1.getArray(); + mainKeySource1.setArray(destKeyArray1); + final int [] originalStateArray = mainOutputPosition.getArray(); + mainOutputPosition.setArray(destState); + for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + continue; + } + final short k0 = originalKeyArray0[sourceBucket]; + final char k1 = originalKeyArray1[sourceBucket]; + final int hash = hash(k0, k1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; + while (true) { + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + break; + } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); + } + } + } + + @Override + public int findPositionForKey(Object key) { + final Object [] ka = (Object[])key; + final short k0 = TypeUtils.unbox((Short)ka[0]); + final char k1 = TypeUtils.unbox((Character)ka[1]); + int hash = hash(k0, k1); + int tableLocation = hashToTableLocation(hash); + final int firstTableLocation = tableLocation; + while (true) { + final int positionValue = mainOutputPosition.getUnsafe(tableLocation); + if (positionValue == EMPTY_OUTPUT_POSITION) { + int alternateTableLocation = hashToTableLocationAlternate(hash); + if (alternateTableLocation >= rehashPointer) { + return -1; + } + final int firstAlternateTableLocation = alternateTableLocation; + while (true) { + final int alternatePositionValue = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (alternatePositionValue == EMPTY_OUTPUT_POSITION) { + return -1; + } + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + return alternatePositionValue; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + return positionValue; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherShortDouble.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherShortDouble.java new file mode 100644 index 00000000000..c721f2d2616 --- /dev/null +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherShortDouble.java @@ -0,0 +1,390 @@ +// DO NOT EDIT THIS CLASS, AUTOMATICALLY GENERATED BY io.deephaven.engine.table.impl.by.typed.TypedHasherFactory +// Copyright (c) 2016-2022 Deephaven Data Labs and Patent Pending +// +package io.deephaven.engine.table.impl.by.typed.incopenagg.gen; + +import static io.deephaven.util.compare.DoubleComparisons.eq; +import static io.deephaven.util.compare.ShortComparisons.eq; + +import io.deephaven.base.verify.Assert; +import io.deephaven.chunk.Chunk; +import io.deephaven.chunk.DoubleChunk; +import io.deephaven.chunk.ShortChunk; +import io.deephaven.chunk.WritableIntChunk; +import io.deephaven.chunk.attributes.Values; +import io.deephaven.chunk.util.hashing.DoubleChunkHasher; +import io.deephaven.chunk.util.hashing.ShortChunkHasher; +import io.deephaven.engine.rowset.RowSequence; +import io.deephaven.engine.rowset.chunkattributes.RowKeys; +import io.deephaven.engine.table.ColumnSource; +import io.deephaven.engine.table.impl.by.IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableDoubleArraySource; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableShortArraySource; +import io.deephaven.util.type.TypeUtils; +import java.lang.Double; +import java.lang.Object; +import java.lang.Override; +import java.lang.Short; +import java.util.Arrays; + +final class IncrementalAggOpenHasherShortDouble extends IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase { + private ImmutableShortArraySource mainKeySource0; + + private ImmutableShortArraySource alternateKeySource0; + + private ImmutableDoubleArraySource mainKeySource1; + + private ImmutableDoubleArraySource alternateKeySource1; + + public IncrementalAggOpenHasherShortDouble(ColumnSource[] tableKeySources, int tableSize, + double maximumLoadFactor, double targetLoadFactor) { + super(tableKeySources, tableSize, maximumLoadFactor); + this.mainKeySource0 = (ImmutableShortArraySource) super.mainKeySources[0]; + this.mainKeySource0.ensureCapacity(tableSize); + this.mainKeySource1 = (ImmutableDoubleArraySource) super.mainKeySources[1]; + this.mainKeySource1.ensureCapacity(tableSize); + } + + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + + private int alternateNextTableLocation(int tableLocation) { + return (tableLocation + 1) & (alternateTableSize - 1); + } + + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final ShortChunk keyChunk0 = sourceKeyChunks[0].asShortChunk(); + final DoubleChunk keyChunk1 = sourceKeyChunks[1].asDoubleChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final short k0 = keyChunk0.get(chunkPosition); + final double k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void buildForUpdate(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk reincarnatedPositions) { + final ShortChunk keyChunk0 = sourceKeyChunks[0].asShortChunk(); + final DoubleChunk keyChunk1 = sourceKeyChunks[1].asDoubleChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final short k0 = keyChunk0.get(chunkPosition); + final double k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void doRemoveProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk emptiedPositions) { + final ShortChunk keyChunk0 = sourceKeyChunks[0].asShortChunk(); + final DoubleChunk keyChunk1 = sourceKeyChunks[1].asDoubleChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final short k0 = keyChunk0.get(chunkPosition); + final double k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + protected void doModifyProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final ShortChunk keyChunk0 = sourceKeyChunks[0].asShortChunk(); + final DoubleChunk keyChunk1 = sourceKeyChunks[1].asDoubleChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final short k0 = keyChunk0.get(chunkPosition); + final double k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + private static int hash(short k0, double k1) { + int hash = ShortChunkHasher.hashInitialSingle(k0); + hash = DoubleChunkHasher.hashUpdateSingle(hash, k1); + return hash; + } + + private boolean migrateOneLocation(int locationToMigrate) { + final int currentStateValue = alternateOutputPosition.getUnsafe(locationToMigrate); + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + return false; + } + final short k0 = alternateKeySource0.getUnsafe(locationToMigrate); + final double k1 = alternateKeySource1.getUnsafe(locationToMigrate); + final int hash = hash(k0, k1); + int destinationTableLocation = hashToTableLocation(hash); + while (mainOutputPosition.getUnsafe(destinationTableLocation) != EMPTY_OUTPUT_POSITION) { + destinationTableLocation = nextTableLocation(destinationTableLocation); + } + mainKeySource0.set(destinationTableLocation, k0); + mainKeySource1.set(destinationTableLocation, k1); + mainOutputPosition.set(destinationTableLocation, currentStateValue); + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + alternateOutputPosition.set(locationToMigrate, EMPTY_OUTPUT_POSITION); + return true; + } + + @Override + protected int rehashInternalPartial(int entriesToRehash) { + int rehashedEntries = 0; + while (rehashPointer > 0 && rehashedEntries < entriesToRehash) { + if (migrateOneLocation(--rehashPointer)) { + rehashedEntries++; + } + } + return rehashedEntries; + } + + @Override + protected void newAlternate() { + super.newAlternate(); + this.mainKeySource0 = (ImmutableShortArraySource)super.mainKeySources[0]; + this.alternateKeySource0 = (ImmutableShortArraySource)super.alternateKeySources[0]; + this.mainKeySource1 = (ImmutableDoubleArraySource)super.mainKeySources[1]; + this.alternateKeySource1 = (ImmutableDoubleArraySource)super.alternateKeySources[1]; + } + + @Override + protected void clearAlternate() { + super.clearAlternate(); + this.alternateKeySource0 = null; + this.alternateKeySource1 = null; + } + + @Override + protected void migrateFront() { + int location = 0; + while (migrateOneLocation(location++)); + } + + @Override + protected void rehashInternalFull(final int oldSize) { + final short[] destKeyArray0 = new short[tableSize]; + final double[] destKeyArray1 = new double[tableSize]; + final int[] destState = new int[tableSize]; + Arrays.fill(destState, EMPTY_OUTPUT_POSITION); + final short [] originalKeyArray0 = mainKeySource0.getArray(); + mainKeySource0.setArray(destKeyArray0); + final double [] originalKeyArray1 = mainKeySource1.getArray(); + mainKeySource1.setArray(destKeyArray1); + final int [] originalStateArray = mainOutputPosition.getArray(); + mainOutputPosition.setArray(destState); + for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + continue; + } + final short k0 = originalKeyArray0[sourceBucket]; + final double k1 = originalKeyArray1[sourceBucket]; + final int hash = hash(k0, k1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; + while (true) { + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + break; + } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); + } + } + } + + @Override + public int findPositionForKey(Object key) { + final Object [] ka = (Object[])key; + final short k0 = TypeUtils.unbox((Short)ka[0]); + final double k1 = TypeUtils.unbox((Double)ka[1]); + int hash = hash(k0, k1); + int tableLocation = hashToTableLocation(hash); + final int firstTableLocation = tableLocation; + while (true) { + final int positionValue = mainOutputPosition.getUnsafe(tableLocation); + if (positionValue == EMPTY_OUTPUT_POSITION) { + int alternateTableLocation = hashToTableLocationAlternate(hash); + if (alternateTableLocation >= rehashPointer) { + return -1; + } + final int firstAlternateTableLocation = alternateTableLocation; + while (true) { + final int alternatePositionValue = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (alternatePositionValue == EMPTY_OUTPUT_POSITION) { + return -1; + } + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + return alternatePositionValue; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + return positionValue; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherShortFloat.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherShortFloat.java new file mode 100644 index 00000000000..9cf6908c297 --- /dev/null +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherShortFloat.java @@ -0,0 +1,390 @@ +// DO NOT EDIT THIS CLASS, AUTOMATICALLY GENERATED BY io.deephaven.engine.table.impl.by.typed.TypedHasherFactory +// Copyright (c) 2016-2022 Deephaven Data Labs and Patent Pending +// +package io.deephaven.engine.table.impl.by.typed.incopenagg.gen; + +import static io.deephaven.util.compare.FloatComparisons.eq; +import static io.deephaven.util.compare.ShortComparisons.eq; + +import io.deephaven.base.verify.Assert; +import io.deephaven.chunk.Chunk; +import io.deephaven.chunk.FloatChunk; +import io.deephaven.chunk.ShortChunk; +import io.deephaven.chunk.WritableIntChunk; +import io.deephaven.chunk.attributes.Values; +import io.deephaven.chunk.util.hashing.FloatChunkHasher; +import io.deephaven.chunk.util.hashing.ShortChunkHasher; +import io.deephaven.engine.rowset.RowSequence; +import io.deephaven.engine.rowset.chunkattributes.RowKeys; +import io.deephaven.engine.table.ColumnSource; +import io.deephaven.engine.table.impl.by.IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableFloatArraySource; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableShortArraySource; +import io.deephaven.util.type.TypeUtils; +import java.lang.Float; +import java.lang.Object; +import java.lang.Override; +import java.lang.Short; +import java.util.Arrays; + +final class IncrementalAggOpenHasherShortFloat extends IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase { + private ImmutableShortArraySource mainKeySource0; + + private ImmutableShortArraySource alternateKeySource0; + + private ImmutableFloatArraySource mainKeySource1; + + private ImmutableFloatArraySource alternateKeySource1; + + public IncrementalAggOpenHasherShortFloat(ColumnSource[] tableKeySources, int tableSize, + double maximumLoadFactor, double targetLoadFactor) { + super(tableKeySources, tableSize, maximumLoadFactor); + this.mainKeySource0 = (ImmutableShortArraySource) super.mainKeySources[0]; + this.mainKeySource0.ensureCapacity(tableSize); + this.mainKeySource1 = (ImmutableFloatArraySource) super.mainKeySources[1]; + this.mainKeySource1.ensureCapacity(tableSize); + } + + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + + private int alternateNextTableLocation(int tableLocation) { + return (tableLocation + 1) & (alternateTableSize - 1); + } + + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final ShortChunk keyChunk0 = sourceKeyChunks[0].asShortChunk(); + final FloatChunk keyChunk1 = sourceKeyChunks[1].asFloatChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final short k0 = keyChunk0.get(chunkPosition); + final float k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void buildForUpdate(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk reincarnatedPositions) { + final ShortChunk keyChunk0 = sourceKeyChunks[0].asShortChunk(); + final FloatChunk keyChunk1 = sourceKeyChunks[1].asFloatChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final short k0 = keyChunk0.get(chunkPosition); + final float k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void doRemoveProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk emptiedPositions) { + final ShortChunk keyChunk0 = sourceKeyChunks[0].asShortChunk(); + final FloatChunk keyChunk1 = sourceKeyChunks[1].asFloatChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final short k0 = keyChunk0.get(chunkPosition); + final float k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + protected void doModifyProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final ShortChunk keyChunk0 = sourceKeyChunks[0].asShortChunk(); + final FloatChunk keyChunk1 = sourceKeyChunks[1].asFloatChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final short k0 = keyChunk0.get(chunkPosition); + final float k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + private static int hash(short k0, float k1) { + int hash = ShortChunkHasher.hashInitialSingle(k0); + hash = FloatChunkHasher.hashUpdateSingle(hash, k1); + return hash; + } + + private boolean migrateOneLocation(int locationToMigrate) { + final int currentStateValue = alternateOutputPosition.getUnsafe(locationToMigrate); + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + return false; + } + final short k0 = alternateKeySource0.getUnsafe(locationToMigrate); + final float k1 = alternateKeySource1.getUnsafe(locationToMigrate); + final int hash = hash(k0, k1); + int destinationTableLocation = hashToTableLocation(hash); + while (mainOutputPosition.getUnsafe(destinationTableLocation) != EMPTY_OUTPUT_POSITION) { + destinationTableLocation = nextTableLocation(destinationTableLocation); + } + mainKeySource0.set(destinationTableLocation, k0); + mainKeySource1.set(destinationTableLocation, k1); + mainOutputPosition.set(destinationTableLocation, currentStateValue); + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + alternateOutputPosition.set(locationToMigrate, EMPTY_OUTPUT_POSITION); + return true; + } + + @Override + protected int rehashInternalPartial(int entriesToRehash) { + int rehashedEntries = 0; + while (rehashPointer > 0 && rehashedEntries < entriesToRehash) { + if (migrateOneLocation(--rehashPointer)) { + rehashedEntries++; + } + } + return rehashedEntries; + } + + @Override + protected void newAlternate() { + super.newAlternate(); + this.mainKeySource0 = (ImmutableShortArraySource)super.mainKeySources[0]; + this.alternateKeySource0 = (ImmutableShortArraySource)super.alternateKeySources[0]; + this.mainKeySource1 = (ImmutableFloatArraySource)super.mainKeySources[1]; + this.alternateKeySource1 = (ImmutableFloatArraySource)super.alternateKeySources[1]; + } + + @Override + protected void clearAlternate() { + super.clearAlternate(); + this.alternateKeySource0 = null; + this.alternateKeySource1 = null; + } + + @Override + protected void migrateFront() { + int location = 0; + while (migrateOneLocation(location++)); + } + + @Override + protected void rehashInternalFull(final int oldSize) { + final short[] destKeyArray0 = new short[tableSize]; + final float[] destKeyArray1 = new float[tableSize]; + final int[] destState = new int[tableSize]; + Arrays.fill(destState, EMPTY_OUTPUT_POSITION); + final short [] originalKeyArray0 = mainKeySource0.getArray(); + mainKeySource0.setArray(destKeyArray0); + final float [] originalKeyArray1 = mainKeySource1.getArray(); + mainKeySource1.setArray(destKeyArray1); + final int [] originalStateArray = mainOutputPosition.getArray(); + mainOutputPosition.setArray(destState); + for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + continue; + } + final short k0 = originalKeyArray0[sourceBucket]; + final float k1 = originalKeyArray1[sourceBucket]; + final int hash = hash(k0, k1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; + while (true) { + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + break; + } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); + } + } + } + + @Override + public int findPositionForKey(Object key) { + final Object [] ka = (Object[])key; + final short k0 = TypeUtils.unbox((Short)ka[0]); + final float k1 = TypeUtils.unbox((Float)ka[1]); + int hash = hash(k0, k1); + int tableLocation = hashToTableLocation(hash); + final int firstTableLocation = tableLocation; + while (true) { + final int positionValue = mainOutputPosition.getUnsafe(tableLocation); + if (positionValue == EMPTY_OUTPUT_POSITION) { + int alternateTableLocation = hashToTableLocationAlternate(hash); + if (alternateTableLocation >= rehashPointer) { + return -1; + } + final int firstAlternateTableLocation = alternateTableLocation; + while (true) { + final int alternatePositionValue = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (alternatePositionValue == EMPTY_OUTPUT_POSITION) { + return -1; + } + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + return alternatePositionValue; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + return positionValue; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherShortInt.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherShortInt.java new file mode 100644 index 00000000000..4eb626bee8a --- /dev/null +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherShortInt.java @@ -0,0 +1,390 @@ +// DO NOT EDIT THIS CLASS, AUTOMATICALLY GENERATED BY io.deephaven.engine.table.impl.by.typed.TypedHasherFactory +// Copyright (c) 2016-2022 Deephaven Data Labs and Patent Pending +// +package io.deephaven.engine.table.impl.by.typed.incopenagg.gen; + +import static io.deephaven.util.compare.IntComparisons.eq; +import static io.deephaven.util.compare.ShortComparisons.eq; + +import io.deephaven.base.verify.Assert; +import io.deephaven.chunk.Chunk; +import io.deephaven.chunk.IntChunk; +import io.deephaven.chunk.ShortChunk; +import io.deephaven.chunk.WritableIntChunk; +import io.deephaven.chunk.attributes.Values; +import io.deephaven.chunk.util.hashing.IntChunkHasher; +import io.deephaven.chunk.util.hashing.ShortChunkHasher; +import io.deephaven.engine.rowset.RowSequence; +import io.deephaven.engine.rowset.chunkattributes.RowKeys; +import io.deephaven.engine.table.ColumnSource; +import io.deephaven.engine.table.impl.by.IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableIntArraySource; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableShortArraySource; +import io.deephaven.util.type.TypeUtils; +import java.lang.Integer; +import java.lang.Object; +import java.lang.Override; +import java.lang.Short; +import java.util.Arrays; + +final class IncrementalAggOpenHasherShortInt extends IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase { + private ImmutableShortArraySource mainKeySource0; + + private ImmutableShortArraySource alternateKeySource0; + + private ImmutableIntArraySource mainKeySource1; + + private ImmutableIntArraySource alternateKeySource1; + + public IncrementalAggOpenHasherShortInt(ColumnSource[] tableKeySources, int tableSize, + double maximumLoadFactor, double targetLoadFactor) { + super(tableKeySources, tableSize, maximumLoadFactor); + this.mainKeySource0 = (ImmutableShortArraySource) super.mainKeySources[0]; + this.mainKeySource0.ensureCapacity(tableSize); + this.mainKeySource1 = (ImmutableIntArraySource) super.mainKeySources[1]; + this.mainKeySource1.ensureCapacity(tableSize); + } + + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + + private int alternateNextTableLocation(int tableLocation) { + return (tableLocation + 1) & (alternateTableSize - 1); + } + + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final ShortChunk keyChunk0 = sourceKeyChunks[0].asShortChunk(); + final IntChunk keyChunk1 = sourceKeyChunks[1].asIntChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final short k0 = keyChunk0.get(chunkPosition); + final int k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void buildForUpdate(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk reincarnatedPositions) { + final ShortChunk keyChunk0 = sourceKeyChunks[0].asShortChunk(); + final IntChunk keyChunk1 = sourceKeyChunks[1].asIntChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final short k0 = keyChunk0.get(chunkPosition); + final int k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void doRemoveProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk emptiedPositions) { + final ShortChunk keyChunk0 = sourceKeyChunks[0].asShortChunk(); + final IntChunk keyChunk1 = sourceKeyChunks[1].asIntChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final short k0 = keyChunk0.get(chunkPosition); + final int k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + protected void doModifyProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final ShortChunk keyChunk0 = sourceKeyChunks[0].asShortChunk(); + final IntChunk keyChunk1 = sourceKeyChunks[1].asIntChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final short k0 = keyChunk0.get(chunkPosition); + final int k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + private static int hash(short k0, int k1) { + int hash = ShortChunkHasher.hashInitialSingle(k0); + hash = IntChunkHasher.hashUpdateSingle(hash, k1); + return hash; + } + + private boolean migrateOneLocation(int locationToMigrate) { + final int currentStateValue = alternateOutputPosition.getUnsafe(locationToMigrate); + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + return false; + } + final short k0 = alternateKeySource0.getUnsafe(locationToMigrate); + final int k1 = alternateKeySource1.getUnsafe(locationToMigrate); + final int hash = hash(k0, k1); + int destinationTableLocation = hashToTableLocation(hash); + while (mainOutputPosition.getUnsafe(destinationTableLocation) != EMPTY_OUTPUT_POSITION) { + destinationTableLocation = nextTableLocation(destinationTableLocation); + } + mainKeySource0.set(destinationTableLocation, k0); + mainKeySource1.set(destinationTableLocation, k1); + mainOutputPosition.set(destinationTableLocation, currentStateValue); + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + alternateOutputPosition.set(locationToMigrate, EMPTY_OUTPUT_POSITION); + return true; + } + + @Override + protected int rehashInternalPartial(int entriesToRehash) { + int rehashedEntries = 0; + while (rehashPointer > 0 && rehashedEntries < entriesToRehash) { + if (migrateOneLocation(--rehashPointer)) { + rehashedEntries++; + } + } + return rehashedEntries; + } + + @Override + protected void newAlternate() { + super.newAlternate(); + this.mainKeySource0 = (ImmutableShortArraySource)super.mainKeySources[0]; + this.alternateKeySource0 = (ImmutableShortArraySource)super.alternateKeySources[0]; + this.mainKeySource1 = (ImmutableIntArraySource)super.mainKeySources[1]; + this.alternateKeySource1 = (ImmutableIntArraySource)super.alternateKeySources[1]; + } + + @Override + protected void clearAlternate() { + super.clearAlternate(); + this.alternateKeySource0 = null; + this.alternateKeySource1 = null; + } + + @Override + protected void migrateFront() { + int location = 0; + while (migrateOneLocation(location++)); + } + + @Override + protected void rehashInternalFull(final int oldSize) { + final short[] destKeyArray0 = new short[tableSize]; + final int[] destKeyArray1 = new int[tableSize]; + final int[] destState = new int[tableSize]; + Arrays.fill(destState, EMPTY_OUTPUT_POSITION); + final short [] originalKeyArray0 = mainKeySource0.getArray(); + mainKeySource0.setArray(destKeyArray0); + final int [] originalKeyArray1 = mainKeySource1.getArray(); + mainKeySource1.setArray(destKeyArray1); + final int [] originalStateArray = mainOutputPosition.getArray(); + mainOutputPosition.setArray(destState); + for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + continue; + } + final short k0 = originalKeyArray0[sourceBucket]; + final int k1 = originalKeyArray1[sourceBucket]; + final int hash = hash(k0, k1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; + while (true) { + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + break; + } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); + } + } + } + + @Override + public int findPositionForKey(Object key) { + final Object [] ka = (Object[])key; + final short k0 = TypeUtils.unbox((Short)ka[0]); + final int k1 = TypeUtils.unbox((Integer)ka[1]); + int hash = hash(k0, k1); + int tableLocation = hashToTableLocation(hash); + final int firstTableLocation = tableLocation; + while (true) { + final int positionValue = mainOutputPosition.getUnsafe(tableLocation); + if (positionValue == EMPTY_OUTPUT_POSITION) { + int alternateTableLocation = hashToTableLocationAlternate(hash); + if (alternateTableLocation >= rehashPointer) { + return -1; + } + final int firstAlternateTableLocation = alternateTableLocation; + while (true) { + final int alternatePositionValue = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (alternatePositionValue == EMPTY_OUTPUT_POSITION) { + return -1; + } + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + return alternatePositionValue; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + return positionValue; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherShortLong.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherShortLong.java new file mode 100644 index 00000000000..ea3dda8b38c --- /dev/null +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherShortLong.java @@ -0,0 +1,390 @@ +// DO NOT EDIT THIS CLASS, AUTOMATICALLY GENERATED BY io.deephaven.engine.table.impl.by.typed.TypedHasherFactory +// Copyright (c) 2016-2022 Deephaven Data Labs and Patent Pending +// +package io.deephaven.engine.table.impl.by.typed.incopenagg.gen; + +import static io.deephaven.util.compare.LongComparisons.eq; +import static io.deephaven.util.compare.ShortComparisons.eq; + +import io.deephaven.base.verify.Assert; +import io.deephaven.chunk.Chunk; +import io.deephaven.chunk.LongChunk; +import io.deephaven.chunk.ShortChunk; +import io.deephaven.chunk.WritableIntChunk; +import io.deephaven.chunk.attributes.Values; +import io.deephaven.chunk.util.hashing.LongChunkHasher; +import io.deephaven.chunk.util.hashing.ShortChunkHasher; +import io.deephaven.engine.rowset.RowSequence; +import io.deephaven.engine.rowset.chunkattributes.RowKeys; +import io.deephaven.engine.table.ColumnSource; +import io.deephaven.engine.table.impl.by.IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableLongArraySource; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableShortArraySource; +import io.deephaven.util.type.TypeUtils; +import java.lang.Long; +import java.lang.Object; +import java.lang.Override; +import java.lang.Short; +import java.util.Arrays; + +final class IncrementalAggOpenHasherShortLong extends IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase { + private ImmutableShortArraySource mainKeySource0; + + private ImmutableShortArraySource alternateKeySource0; + + private ImmutableLongArraySource mainKeySource1; + + private ImmutableLongArraySource alternateKeySource1; + + public IncrementalAggOpenHasherShortLong(ColumnSource[] tableKeySources, int tableSize, + double maximumLoadFactor, double targetLoadFactor) { + super(tableKeySources, tableSize, maximumLoadFactor); + this.mainKeySource0 = (ImmutableShortArraySource) super.mainKeySources[0]; + this.mainKeySource0.ensureCapacity(tableSize); + this.mainKeySource1 = (ImmutableLongArraySource) super.mainKeySources[1]; + this.mainKeySource1.ensureCapacity(tableSize); + } + + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + + private int alternateNextTableLocation(int tableLocation) { + return (tableLocation + 1) & (alternateTableSize - 1); + } + + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final ShortChunk keyChunk0 = sourceKeyChunks[0].asShortChunk(); + final LongChunk keyChunk1 = sourceKeyChunks[1].asLongChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final short k0 = keyChunk0.get(chunkPosition); + final long k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void buildForUpdate(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk reincarnatedPositions) { + final ShortChunk keyChunk0 = sourceKeyChunks[0].asShortChunk(); + final LongChunk keyChunk1 = sourceKeyChunks[1].asLongChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final short k0 = keyChunk0.get(chunkPosition); + final long k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void doRemoveProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk emptiedPositions) { + final ShortChunk keyChunk0 = sourceKeyChunks[0].asShortChunk(); + final LongChunk keyChunk1 = sourceKeyChunks[1].asLongChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final short k0 = keyChunk0.get(chunkPosition); + final long k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + protected void doModifyProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final ShortChunk keyChunk0 = sourceKeyChunks[0].asShortChunk(); + final LongChunk keyChunk1 = sourceKeyChunks[1].asLongChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final short k0 = keyChunk0.get(chunkPosition); + final long k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + private static int hash(short k0, long k1) { + int hash = ShortChunkHasher.hashInitialSingle(k0); + hash = LongChunkHasher.hashUpdateSingle(hash, k1); + return hash; + } + + private boolean migrateOneLocation(int locationToMigrate) { + final int currentStateValue = alternateOutputPosition.getUnsafe(locationToMigrate); + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + return false; + } + final short k0 = alternateKeySource0.getUnsafe(locationToMigrate); + final long k1 = alternateKeySource1.getUnsafe(locationToMigrate); + final int hash = hash(k0, k1); + int destinationTableLocation = hashToTableLocation(hash); + while (mainOutputPosition.getUnsafe(destinationTableLocation) != EMPTY_OUTPUT_POSITION) { + destinationTableLocation = nextTableLocation(destinationTableLocation); + } + mainKeySource0.set(destinationTableLocation, k0); + mainKeySource1.set(destinationTableLocation, k1); + mainOutputPosition.set(destinationTableLocation, currentStateValue); + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + alternateOutputPosition.set(locationToMigrate, EMPTY_OUTPUT_POSITION); + return true; + } + + @Override + protected int rehashInternalPartial(int entriesToRehash) { + int rehashedEntries = 0; + while (rehashPointer > 0 && rehashedEntries < entriesToRehash) { + if (migrateOneLocation(--rehashPointer)) { + rehashedEntries++; + } + } + return rehashedEntries; + } + + @Override + protected void newAlternate() { + super.newAlternate(); + this.mainKeySource0 = (ImmutableShortArraySource)super.mainKeySources[0]; + this.alternateKeySource0 = (ImmutableShortArraySource)super.alternateKeySources[0]; + this.mainKeySource1 = (ImmutableLongArraySource)super.mainKeySources[1]; + this.alternateKeySource1 = (ImmutableLongArraySource)super.alternateKeySources[1]; + } + + @Override + protected void clearAlternate() { + super.clearAlternate(); + this.alternateKeySource0 = null; + this.alternateKeySource1 = null; + } + + @Override + protected void migrateFront() { + int location = 0; + while (migrateOneLocation(location++)); + } + + @Override + protected void rehashInternalFull(final int oldSize) { + final short[] destKeyArray0 = new short[tableSize]; + final long[] destKeyArray1 = new long[tableSize]; + final int[] destState = new int[tableSize]; + Arrays.fill(destState, EMPTY_OUTPUT_POSITION); + final short [] originalKeyArray0 = mainKeySource0.getArray(); + mainKeySource0.setArray(destKeyArray0); + final long [] originalKeyArray1 = mainKeySource1.getArray(); + mainKeySource1.setArray(destKeyArray1); + final int [] originalStateArray = mainOutputPosition.getArray(); + mainOutputPosition.setArray(destState); + for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + continue; + } + final short k0 = originalKeyArray0[sourceBucket]; + final long k1 = originalKeyArray1[sourceBucket]; + final int hash = hash(k0, k1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; + while (true) { + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + break; + } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); + } + } + } + + @Override + public int findPositionForKey(Object key) { + final Object [] ka = (Object[])key; + final short k0 = TypeUtils.unbox((Short)ka[0]); + final long k1 = TypeUtils.unbox((Long)ka[1]); + int hash = hash(k0, k1); + int tableLocation = hashToTableLocation(hash); + final int firstTableLocation = tableLocation; + while (true) { + final int positionValue = mainOutputPosition.getUnsafe(tableLocation); + if (positionValue == EMPTY_OUTPUT_POSITION) { + int alternateTableLocation = hashToTableLocationAlternate(hash); + if (alternateTableLocation >= rehashPointer) { + return -1; + } + final int firstAlternateTableLocation = alternateTableLocation; + while (true) { + final int alternatePositionValue = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (alternatePositionValue == EMPTY_OUTPUT_POSITION) { + return -1; + } + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + return alternatePositionValue; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + return positionValue; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherShortObject.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherShortObject.java new file mode 100644 index 00000000000..6d9effb2a0c --- /dev/null +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherShortObject.java @@ -0,0 +1,390 @@ +// DO NOT EDIT THIS CLASS, AUTOMATICALLY GENERATED BY io.deephaven.engine.table.impl.by.typed.TypedHasherFactory +// Copyright (c) 2016-2022 Deephaven Data Labs and Patent Pending +// +package io.deephaven.engine.table.impl.by.typed.incopenagg.gen; + +import static io.deephaven.util.compare.ObjectComparisons.eq; +import static io.deephaven.util.compare.ShortComparisons.eq; + +import io.deephaven.base.verify.Assert; +import io.deephaven.chunk.Chunk; +import io.deephaven.chunk.ObjectChunk; +import io.deephaven.chunk.ShortChunk; +import io.deephaven.chunk.WritableIntChunk; +import io.deephaven.chunk.attributes.Values; +import io.deephaven.chunk.util.hashing.ObjectChunkHasher; +import io.deephaven.chunk.util.hashing.ShortChunkHasher; +import io.deephaven.engine.rowset.RowSequence; +import io.deephaven.engine.rowset.chunkattributes.RowKeys; +import io.deephaven.engine.table.ColumnSource; +import io.deephaven.engine.table.impl.by.IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableObjectArraySource; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableShortArraySource; +import io.deephaven.util.type.TypeUtils; +import java.lang.Object; +import java.lang.Override; +import java.lang.Short; +import java.util.Arrays; + +final class IncrementalAggOpenHasherShortObject extends IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase { + private ImmutableShortArraySource mainKeySource0; + + private ImmutableShortArraySource alternateKeySource0; + + private ImmutableObjectArraySource mainKeySource1; + + private ImmutableObjectArraySource alternateKeySource1; + + public IncrementalAggOpenHasherShortObject(ColumnSource[] tableKeySources, int tableSize, + double maximumLoadFactor, double targetLoadFactor) { + super(tableKeySources, tableSize, maximumLoadFactor); + this.mainKeySource0 = (ImmutableShortArraySource) super.mainKeySources[0]; + this.mainKeySource0.ensureCapacity(tableSize); + this.mainKeySource1 = (ImmutableObjectArraySource) super.mainKeySources[1]; + this.mainKeySource1.ensureCapacity(tableSize); + } + + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + + private int alternateNextTableLocation(int tableLocation) { + return (tableLocation + 1) & (alternateTableSize - 1); + } + + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final ShortChunk keyChunk0 = sourceKeyChunks[0].asShortChunk(); + final ObjectChunk keyChunk1 = sourceKeyChunks[1].asObjectChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final short k0 = keyChunk0.get(chunkPosition); + final Object k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void buildForUpdate(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk reincarnatedPositions) { + final ShortChunk keyChunk0 = sourceKeyChunks[0].asShortChunk(); + final ObjectChunk keyChunk1 = sourceKeyChunks[1].asObjectChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final short k0 = keyChunk0.get(chunkPosition); + final Object k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void doRemoveProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk emptiedPositions) { + final ShortChunk keyChunk0 = sourceKeyChunks[0].asShortChunk(); + final ObjectChunk keyChunk1 = sourceKeyChunks[1].asObjectChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final short k0 = keyChunk0.get(chunkPosition); + final Object k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + protected void doModifyProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final ShortChunk keyChunk0 = sourceKeyChunks[0].asShortChunk(); + final ObjectChunk keyChunk1 = sourceKeyChunks[1].asObjectChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final short k0 = keyChunk0.get(chunkPosition); + final Object k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + private static int hash(short k0, Object k1) { + int hash = ShortChunkHasher.hashInitialSingle(k0); + hash = ObjectChunkHasher.hashUpdateSingle(hash, k1); + return hash; + } + + private boolean migrateOneLocation(int locationToMigrate) { + final int currentStateValue = alternateOutputPosition.getUnsafe(locationToMigrate); + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + return false; + } + final short k0 = alternateKeySource0.getUnsafe(locationToMigrate); + final Object k1 = alternateKeySource1.getUnsafe(locationToMigrate); + final int hash = hash(k0, k1); + int destinationTableLocation = hashToTableLocation(hash); + while (mainOutputPosition.getUnsafe(destinationTableLocation) != EMPTY_OUTPUT_POSITION) { + destinationTableLocation = nextTableLocation(destinationTableLocation); + } + mainKeySource0.set(destinationTableLocation, k0); + mainKeySource1.set(destinationTableLocation, k1); + alternateKeySource1.set(locationToMigrate, null); + mainOutputPosition.set(destinationTableLocation, currentStateValue); + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + alternateOutputPosition.set(locationToMigrate, EMPTY_OUTPUT_POSITION); + return true; + } + + @Override + protected int rehashInternalPartial(int entriesToRehash) { + int rehashedEntries = 0; + while (rehashPointer > 0 && rehashedEntries < entriesToRehash) { + if (migrateOneLocation(--rehashPointer)) { + rehashedEntries++; + } + } + return rehashedEntries; + } + + @Override + protected void newAlternate() { + super.newAlternate(); + this.mainKeySource0 = (ImmutableShortArraySource)super.mainKeySources[0]; + this.alternateKeySource0 = (ImmutableShortArraySource)super.alternateKeySources[0]; + this.mainKeySource1 = (ImmutableObjectArraySource)super.mainKeySources[1]; + this.alternateKeySource1 = (ImmutableObjectArraySource)super.alternateKeySources[1]; + } + + @Override + protected void clearAlternate() { + super.clearAlternate(); + this.alternateKeySource0 = null; + this.alternateKeySource1 = null; + } + + @Override + protected void migrateFront() { + int location = 0; + while (migrateOneLocation(location++)); + } + + @Override + protected void rehashInternalFull(final int oldSize) { + final short[] destKeyArray0 = new short[tableSize]; + final Object[] destKeyArray1 = new Object[tableSize]; + final int[] destState = new int[tableSize]; + Arrays.fill(destState, EMPTY_OUTPUT_POSITION); + final short [] originalKeyArray0 = mainKeySource0.getArray(); + mainKeySource0.setArray(destKeyArray0); + final Object [] originalKeyArray1 = mainKeySource1.getArray(); + mainKeySource1.setArray(destKeyArray1); + final int [] originalStateArray = mainOutputPosition.getArray(); + mainOutputPosition.setArray(destState); + for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + continue; + } + final short k0 = originalKeyArray0[sourceBucket]; + final Object k1 = originalKeyArray1[sourceBucket]; + final int hash = hash(k0, k1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; + while (true) { + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + break; + } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); + } + } + } + + @Override + public int findPositionForKey(Object key) { + final Object [] ka = (Object[])key; + final short k0 = TypeUtils.unbox((Short)ka[0]); + final Object k1 = ka[1]; + int hash = hash(k0, k1); + int tableLocation = hashToTableLocation(hash); + final int firstTableLocation = tableLocation; + while (true) { + final int positionValue = mainOutputPosition.getUnsafe(tableLocation); + if (positionValue == EMPTY_OUTPUT_POSITION) { + int alternateTableLocation = hashToTableLocationAlternate(hash); + if (alternateTableLocation >= rehashPointer) { + return -1; + } + final int firstAlternateTableLocation = alternateTableLocation; + while (true) { + final int alternatePositionValue = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (alternatePositionValue == EMPTY_OUTPUT_POSITION) { + return -1; + } + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + return alternatePositionValue; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + return positionValue; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherShortShort.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherShortShort.java new file mode 100644 index 00000000000..b18cba7c5c1 --- /dev/null +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/IncrementalAggOpenHasherShortShort.java @@ -0,0 +1,385 @@ +// DO NOT EDIT THIS CLASS, AUTOMATICALLY GENERATED BY io.deephaven.engine.table.impl.by.typed.TypedHasherFactory +// Copyright (c) 2016-2022 Deephaven Data Labs and Patent Pending +// +package io.deephaven.engine.table.impl.by.typed.incopenagg.gen; + +import static io.deephaven.util.compare.ShortComparisons.eq; + +import io.deephaven.base.verify.Assert; +import io.deephaven.chunk.Chunk; +import io.deephaven.chunk.ShortChunk; +import io.deephaven.chunk.WritableIntChunk; +import io.deephaven.chunk.attributes.Values; +import io.deephaven.chunk.util.hashing.ShortChunkHasher; +import io.deephaven.engine.rowset.RowSequence; +import io.deephaven.engine.rowset.chunkattributes.RowKeys; +import io.deephaven.engine.table.ColumnSource; +import io.deephaven.engine.table.impl.by.IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase; +import io.deephaven.engine.table.impl.sources.immutable.ImmutableShortArraySource; +import io.deephaven.util.type.TypeUtils; +import java.lang.Object; +import java.lang.Override; +import java.lang.Short; +import java.util.Arrays; + +final class IncrementalAggOpenHasherShortShort extends IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase { + private ImmutableShortArraySource mainKeySource0; + + private ImmutableShortArraySource alternateKeySource0; + + private ImmutableShortArraySource mainKeySource1; + + private ImmutableShortArraySource alternateKeySource1; + + public IncrementalAggOpenHasherShortShort(ColumnSource[] tableKeySources, int tableSize, + double maximumLoadFactor, double targetLoadFactor) { + super(tableKeySources, tableSize, maximumLoadFactor); + this.mainKeySource0 = (ImmutableShortArraySource) super.mainKeySources[0]; + this.mainKeySource0.ensureCapacity(tableSize); + this.mainKeySource1 = (ImmutableShortArraySource) super.mainKeySources[1]; + this.mainKeySource1.ensureCapacity(tableSize); + } + + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + + private int alternateNextTableLocation(int tableLocation) { + return (tableLocation + 1) & (alternateTableSize - 1); + } + + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final ShortChunk keyChunk0 = sourceKeyChunks[0].asShortChunk(); + final ShortChunk keyChunk1 = sourceKeyChunks[1].asShortChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final short k0 = keyChunk0.get(chunkPosition); + final short k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + Assert.gtZero(oldRowCount, "oldRowCount"); + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void buildForUpdate(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk reincarnatedPositions) { + final ShortChunk keyChunk0 = sourceKeyChunks[0].asShortChunk(); + final ShortChunk keyChunk1 = sourceKeyChunks[1].asShortChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final short k0 = keyChunk0.get(chunkPosition); + final short k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; + MAIN_SEARCH: while (true) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + int alternateTableLocation = firstAlternateTableLocation; + while (alternateTableLocation < rehashPointer) { + outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { + break; + } else if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break MAIN_SEARCH; + } else { + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + numEntries++; + mainKeySource0.set(tableLocation, k0); + mainKeySource1.set(tableLocation, k1); + outputPosition = nextOutputPosition.getAndIncrement(); + outputPositions.set(chunkPosition, outputPosition); + mainOutputPosition.set(tableLocation, outputPosition); + outputPositionToHashSlot.set(outputPosition, mainInsertMask | tableLocation); + rowCountSource.set(outputPosition, 1L); + break; + } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, 1); + if (oldRowCount == 0) { + reincarnatedPositions.add(outputPosition); + } + break; + } else { + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } + } + } + + protected void doRemoveProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks, + WritableIntChunk emptiedPositions) { + final ShortChunk keyChunk0 = sourceKeyChunks[0].asShortChunk(); + final ShortChunk keyChunk1 = sourceKeyChunks[1].asShortChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final short k0 = keyChunk0.get(chunkPosition); + final short k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + final long oldRowCount = rowCountSource.getAndAddUnsafe(outputPosition, -1); + Assert.gtZero(oldRowCount, "oldRowCount"); + if (oldRowCount == 1) { + emptiedPositions.add(outputPosition); + } + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + protected void doModifyProbe(RowSequence rowSequence, Chunk[] sourceKeyChunks) { + final ShortChunk keyChunk0 = sourceKeyChunks[0].asShortChunk(); + final ShortChunk keyChunk1 = sourceKeyChunks[1].asShortChunk(); + final int chunkSize = keyChunk0.size(); + for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { + final short k0 = keyChunk0.get(chunkPosition); + final short k1 = keyChunk1.get(chunkPosition); + final int hash = hash(k0, k1); + final int firstTableLocation = hashToTableLocation(hash); + boolean found = false; + int tableLocation = firstTableLocation; + int outputPosition; + while ((outputPosition = mainOutputPosition.getUnsafe(tableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + found = true; + break; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + if (!found) { + final int firstAlternateTableLocation = hashToTableLocationAlternate(hash); + boolean alternateFound = false; + if (firstAlternateTableLocation < rehashPointer) { + int alternateTableLocation = firstAlternateTableLocation; + while ((outputPosition = alternateOutputPosition.getUnsafe(alternateTableLocation)) != EMPTY_OUTPUT_POSITION) { + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + outputPositions.set(chunkPosition, outputPosition); + alternateFound = true; + break; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (!alternateFound) { + throw new IllegalStateException("Missing value in probe"); + } + } + } + } + + private static int hash(short k0, short k1) { + int hash = ShortChunkHasher.hashInitialSingle(k0); + hash = ShortChunkHasher.hashUpdateSingle(hash, k1); + return hash; + } + + private boolean migrateOneLocation(int locationToMigrate) { + final int currentStateValue = alternateOutputPosition.getUnsafe(locationToMigrate); + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + return false; + } + final short k0 = alternateKeySource0.getUnsafe(locationToMigrate); + final short k1 = alternateKeySource1.getUnsafe(locationToMigrate); + final int hash = hash(k0, k1); + int destinationTableLocation = hashToTableLocation(hash); + while (mainOutputPosition.getUnsafe(destinationTableLocation) != EMPTY_OUTPUT_POSITION) { + destinationTableLocation = nextTableLocation(destinationTableLocation); + } + mainKeySource0.set(destinationTableLocation, k0); + mainKeySource1.set(destinationTableLocation, k1); + mainOutputPosition.set(destinationTableLocation, currentStateValue); + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + alternateOutputPosition.set(locationToMigrate, EMPTY_OUTPUT_POSITION); + return true; + } + + @Override + protected int rehashInternalPartial(int entriesToRehash) { + int rehashedEntries = 0; + while (rehashPointer > 0 && rehashedEntries < entriesToRehash) { + if (migrateOneLocation(--rehashPointer)) { + rehashedEntries++; + } + } + return rehashedEntries; + } + + @Override + protected void newAlternate() { + super.newAlternate(); + this.mainKeySource0 = (ImmutableShortArraySource)super.mainKeySources[0]; + this.alternateKeySource0 = (ImmutableShortArraySource)super.alternateKeySources[0]; + this.mainKeySource1 = (ImmutableShortArraySource)super.mainKeySources[1]; + this.alternateKeySource1 = (ImmutableShortArraySource)super.alternateKeySources[1]; + } + + @Override + protected void clearAlternate() { + super.clearAlternate(); + this.alternateKeySource0 = null; + this.alternateKeySource1 = null; + } + + @Override + protected void migrateFront() { + int location = 0; + while (migrateOneLocation(location++)); + } + + @Override + protected void rehashInternalFull(final int oldSize) { + final short[] destKeyArray0 = new short[tableSize]; + final short[] destKeyArray1 = new short[tableSize]; + final int[] destState = new int[tableSize]; + Arrays.fill(destState, EMPTY_OUTPUT_POSITION); + final short [] originalKeyArray0 = mainKeySource0.getArray(); + mainKeySource0.setArray(destKeyArray0); + final short [] originalKeyArray1 = mainKeySource1.getArray(); + mainKeySource1.setArray(destKeyArray1); + final int [] originalStateArray = mainOutputPosition.getArray(); + mainOutputPosition.setArray(destState); + for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { + continue; + } + final short k0 = originalKeyArray0[sourceBucket]; + final short k1 = originalKeyArray1[sourceBucket]; + final int hash = hash(k0, k1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; + while (true) { + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + outputPositionToHashSlot.set(currentStateValue, mainInsertMask | destinationTableLocation); + break; + } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); + } + } + } + + @Override + public int findPositionForKey(Object key) { + final Object [] ka = (Object[])key; + final short k0 = TypeUtils.unbox((Short)ka[0]); + final short k1 = TypeUtils.unbox((Short)ka[1]); + int hash = hash(k0, k1); + int tableLocation = hashToTableLocation(hash); + final int firstTableLocation = tableLocation; + while (true) { + final int positionValue = mainOutputPosition.getUnsafe(tableLocation); + if (positionValue == EMPTY_OUTPUT_POSITION) { + int alternateTableLocation = hashToTableLocationAlternate(hash); + if (alternateTableLocation >= rehashPointer) { + return -1; + } + final int firstAlternateTableLocation = alternateTableLocation; + while (true) { + final int alternatePositionValue = alternateOutputPosition.getUnsafe(alternateTableLocation); + if (alternatePositionValue == EMPTY_OUTPUT_POSITION) { + return -1; + } + if (eq(alternateKeySource0.getUnsafe(alternateTableLocation), k0) && eq(alternateKeySource1.getUnsafe(alternateTableLocation), k1)) { + return alternatePositionValue; + } + alternateTableLocation = alternateNextTableLocation(alternateTableLocation); + Assert.neq(alternateTableLocation, "alternateTableLocation", firstAlternateTableLocation, "firstAlternateTableLocation"); + } + } + if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { + return positionValue; + } + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); + } + } +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/TypedHashDispatcher.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/TypedHashDispatcher.java new file mode 100644 index 00000000000..d98591dcf08 --- /dev/null +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/incopenagg/gen/TypedHashDispatcher.java @@ -0,0 +1,141 @@ +// DO NOT EDIT THIS CLASS, AUTOMATICALLY GENERATED BY io.deephaven.replicators.ReplicateTypedHashers +// Copyright (c) 2016-2022 Deephaven Data Labs and Patent Pending +// +package io.deephaven.engine.table.impl.by.typed.incopenagg.gen; + +import io.deephaven.chunk.ChunkType; +import io.deephaven.engine.table.ColumnSource; +import io.deephaven.engine.table.impl.by.IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase; +import java.util.Arrays; + +/** + * The TypedHashDispatcher returns a pre-generated and precompiled hasher instance suitable for the provided column sources, or null if there is not a precompiled hasher suitable for the specified sources. */ +public class TypedHashDispatcher { + private TypedHashDispatcher() { + // static use only + } + + public static IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase dispatch(ColumnSource[] tableKeySources, + int tableSize, double maximumLoadFactor, double targetLoadFactor) { + final ChunkType[] chunkTypes = Arrays.stream(tableKeySources).map(ColumnSource::getChunkType).toArray(ChunkType[]::new);; + if (chunkTypes.length == 1) { + return dispatchSingle(chunkTypes[0], tableKeySources, tableSize, maximumLoadFactor, targetLoadFactor); + } + if (chunkTypes.length == 2) { + return dispatchDouble(chunkTypes[0], chunkTypes[1], tableKeySources, tableSize, maximumLoadFactor, targetLoadFactor); + } + return null; + } + + private static IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase dispatchSingle(ChunkType chunkType, + ColumnSource[] tableKeySources, int tableSize, double maximumLoadFactor, + double targetLoadFactor) { + switch (chunkType) { + default: throw new UnsupportedOperationException("Invalid chunk type for typed hashers: " + chunkType); + case Char: return new IncrementalAggOpenHasherChar(tableKeySources, tableSize, maximumLoadFactor, targetLoadFactor); + case Byte: return new IncrementalAggOpenHasherByte(tableKeySources, tableSize, maximumLoadFactor, targetLoadFactor); + case Short: return new IncrementalAggOpenHasherShort(tableKeySources, tableSize, maximumLoadFactor, targetLoadFactor); + case Int: return new IncrementalAggOpenHasherInt(tableKeySources, tableSize, maximumLoadFactor, targetLoadFactor); + case Long: return new IncrementalAggOpenHasherLong(tableKeySources, tableSize, maximumLoadFactor, targetLoadFactor); + case Float: return new IncrementalAggOpenHasherFloat(tableKeySources, tableSize, maximumLoadFactor, targetLoadFactor); + case Double: return new IncrementalAggOpenHasherDouble(tableKeySources, tableSize, maximumLoadFactor, targetLoadFactor); + case Object: return new IncrementalAggOpenHasherObject(tableKeySources, tableSize, maximumLoadFactor, targetLoadFactor); + } + } + + private static IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase dispatchDouble(ChunkType chunkType0, + ChunkType chunkType1, ColumnSource[] tableKeySources, int tableSize, + double maximumLoadFactor, double targetLoadFactor) { + switch (chunkType0) { + default: throw new UnsupportedOperationException("Invalid chunk type for typed hashers: " + chunkType0); + case Char:switch (chunkType1) { + default: throw new UnsupportedOperationException("Invalid chunk type for typed hashers: " + chunkType1); + case Char: return new IncrementalAggOpenHasherCharChar(tableKeySources, tableSize, maximumLoadFactor, targetLoadFactor); + case Byte: return new IncrementalAggOpenHasherCharByte(tableKeySources, tableSize, maximumLoadFactor, targetLoadFactor); + case Short: return new IncrementalAggOpenHasherCharShort(tableKeySources, tableSize, maximumLoadFactor, targetLoadFactor); + case Int: return new IncrementalAggOpenHasherCharInt(tableKeySources, tableSize, maximumLoadFactor, targetLoadFactor); + case Long: return new IncrementalAggOpenHasherCharLong(tableKeySources, tableSize, maximumLoadFactor, targetLoadFactor); + case Float: return new IncrementalAggOpenHasherCharFloat(tableKeySources, tableSize, maximumLoadFactor, targetLoadFactor); + case Double: return new IncrementalAggOpenHasherCharDouble(tableKeySources, tableSize, maximumLoadFactor, targetLoadFactor); + case Object: return new IncrementalAggOpenHasherCharObject(tableKeySources, tableSize, maximumLoadFactor, targetLoadFactor); + } + case Byte:switch (chunkType1) { + default: throw new UnsupportedOperationException("Invalid chunk type for typed hashers: " + chunkType1); + case Char: return new IncrementalAggOpenHasherByteChar(tableKeySources, tableSize, maximumLoadFactor, targetLoadFactor); + case Byte: return new IncrementalAggOpenHasherByteByte(tableKeySources, tableSize, maximumLoadFactor, targetLoadFactor); + case Short: return new IncrementalAggOpenHasherByteShort(tableKeySources, tableSize, maximumLoadFactor, targetLoadFactor); + case Int: return new IncrementalAggOpenHasherByteInt(tableKeySources, tableSize, maximumLoadFactor, targetLoadFactor); + case Long: return new IncrementalAggOpenHasherByteLong(tableKeySources, tableSize, maximumLoadFactor, targetLoadFactor); + case Float: return new IncrementalAggOpenHasherByteFloat(tableKeySources, tableSize, maximumLoadFactor, targetLoadFactor); + case Double: return new IncrementalAggOpenHasherByteDouble(tableKeySources, tableSize, maximumLoadFactor, targetLoadFactor); + case Object: return new IncrementalAggOpenHasherByteObject(tableKeySources, tableSize, maximumLoadFactor, targetLoadFactor); + } + case Short:switch (chunkType1) { + default: throw new UnsupportedOperationException("Invalid chunk type for typed hashers: " + chunkType1); + case Char: return new IncrementalAggOpenHasherShortChar(tableKeySources, tableSize, maximumLoadFactor, targetLoadFactor); + case Byte: return new IncrementalAggOpenHasherShortByte(tableKeySources, tableSize, maximumLoadFactor, targetLoadFactor); + case Short: return new IncrementalAggOpenHasherShortShort(tableKeySources, tableSize, maximumLoadFactor, targetLoadFactor); + case Int: return new IncrementalAggOpenHasherShortInt(tableKeySources, tableSize, maximumLoadFactor, targetLoadFactor); + case Long: return new IncrementalAggOpenHasherShortLong(tableKeySources, tableSize, maximumLoadFactor, targetLoadFactor); + case Float: return new IncrementalAggOpenHasherShortFloat(tableKeySources, tableSize, maximumLoadFactor, targetLoadFactor); + case Double: return new IncrementalAggOpenHasherShortDouble(tableKeySources, tableSize, maximumLoadFactor, targetLoadFactor); + case Object: return new IncrementalAggOpenHasherShortObject(tableKeySources, tableSize, maximumLoadFactor, targetLoadFactor); + } + case Int:switch (chunkType1) { + default: throw new UnsupportedOperationException("Invalid chunk type for typed hashers: " + chunkType1); + case Char: return new IncrementalAggOpenHasherIntChar(tableKeySources, tableSize, maximumLoadFactor, targetLoadFactor); + case Byte: return new IncrementalAggOpenHasherIntByte(tableKeySources, tableSize, maximumLoadFactor, targetLoadFactor); + case Short: return new IncrementalAggOpenHasherIntShort(tableKeySources, tableSize, maximumLoadFactor, targetLoadFactor); + case Int: return new IncrementalAggOpenHasherIntInt(tableKeySources, tableSize, maximumLoadFactor, targetLoadFactor); + case Long: return new IncrementalAggOpenHasherIntLong(tableKeySources, tableSize, maximumLoadFactor, targetLoadFactor); + case Float: return new IncrementalAggOpenHasherIntFloat(tableKeySources, tableSize, maximumLoadFactor, targetLoadFactor); + case Double: return new IncrementalAggOpenHasherIntDouble(tableKeySources, tableSize, maximumLoadFactor, targetLoadFactor); + case Object: return new IncrementalAggOpenHasherIntObject(tableKeySources, tableSize, maximumLoadFactor, targetLoadFactor); + } + case Long:switch (chunkType1) { + default: throw new UnsupportedOperationException("Invalid chunk type for typed hashers: " + chunkType1); + case Char: return new IncrementalAggOpenHasherLongChar(tableKeySources, tableSize, maximumLoadFactor, targetLoadFactor); + case Byte: return new IncrementalAggOpenHasherLongByte(tableKeySources, tableSize, maximumLoadFactor, targetLoadFactor); + case Short: return new IncrementalAggOpenHasherLongShort(tableKeySources, tableSize, maximumLoadFactor, targetLoadFactor); + case Int: return new IncrementalAggOpenHasherLongInt(tableKeySources, tableSize, maximumLoadFactor, targetLoadFactor); + case Long: return new IncrementalAggOpenHasherLongLong(tableKeySources, tableSize, maximumLoadFactor, targetLoadFactor); + case Float: return new IncrementalAggOpenHasherLongFloat(tableKeySources, tableSize, maximumLoadFactor, targetLoadFactor); + case Double: return new IncrementalAggOpenHasherLongDouble(tableKeySources, tableSize, maximumLoadFactor, targetLoadFactor); + case Object: return new IncrementalAggOpenHasherLongObject(tableKeySources, tableSize, maximumLoadFactor, targetLoadFactor); + } + case Float:switch (chunkType1) { + default: throw new UnsupportedOperationException("Invalid chunk type for typed hashers: " + chunkType1); + case Char: return new IncrementalAggOpenHasherFloatChar(tableKeySources, tableSize, maximumLoadFactor, targetLoadFactor); + case Byte: return new IncrementalAggOpenHasherFloatByte(tableKeySources, tableSize, maximumLoadFactor, targetLoadFactor); + case Short: return new IncrementalAggOpenHasherFloatShort(tableKeySources, tableSize, maximumLoadFactor, targetLoadFactor); + case Int: return new IncrementalAggOpenHasherFloatInt(tableKeySources, tableSize, maximumLoadFactor, targetLoadFactor); + case Long: return new IncrementalAggOpenHasherFloatLong(tableKeySources, tableSize, maximumLoadFactor, targetLoadFactor); + case Float: return new IncrementalAggOpenHasherFloatFloat(tableKeySources, tableSize, maximumLoadFactor, targetLoadFactor); + case Double: return new IncrementalAggOpenHasherFloatDouble(tableKeySources, tableSize, maximumLoadFactor, targetLoadFactor); + case Object: return new IncrementalAggOpenHasherFloatObject(tableKeySources, tableSize, maximumLoadFactor, targetLoadFactor); + } + case Double:switch (chunkType1) { + default: throw new UnsupportedOperationException("Invalid chunk type for typed hashers: " + chunkType1); + case Char: return new IncrementalAggOpenHasherDoubleChar(tableKeySources, tableSize, maximumLoadFactor, targetLoadFactor); + case Byte: return new IncrementalAggOpenHasherDoubleByte(tableKeySources, tableSize, maximumLoadFactor, targetLoadFactor); + case Short: return new IncrementalAggOpenHasherDoubleShort(tableKeySources, tableSize, maximumLoadFactor, targetLoadFactor); + case Int: return new IncrementalAggOpenHasherDoubleInt(tableKeySources, tableSize, maximumLoadFactor, targetLoadFactor); + case Long: return new IncrementalAggOpenHasherDoubleLong(tableKeySources, tableSize, maximumLoadFactor, targetLoadFactor); + case Float: return new IncrementalAggOpenHasherDoubleFloat(tableKeySources, tableSize, maximumLoadFactor, targetLoadFactor); + case Double: return new IncrementalAggOpenHasherDoubleDouble(tableKeySources, tableSize, maximumLoadFactor, targetLoadFactor); + case Object: return new IncrementalAggOpenHasherDoubleObject(tableKeySources, tableSize, maximumLoadFactor, targetLoadFactor); + } + case Object:switch (chunkType1) { + default: throw new UnsupportedOperationException("Invalid chunk type for typed hashers: " + chunkType1); + case Char: return new IncrementalAggOpenHasherObjectChar(tableKeySources, tableSize, maximumLoadFactor, targetLoadFactor); + case Byte: return new IncrementalAggOpenHasherObjectByte(tableKeySources, tableSize, maximumLoadFactor, targetLoadFactor); + case Short: return new IncrementalAggOpenHasherObjectShort(tableKeySources, tableSize, maximumLoadFactor, targetLoadFactor); + case Int: return new IncrementalAggOpenHasherObjectInt(tableKeySources, tableSize, maximumLoadFactor, targetLoadFactor); + case Long: return new IncrementalAggOpenHasherObjectLong(tableKeySources, tableSize, maximumLoadFactor, targetLoadFactor); + case Float: return new IncrementalAggOpenHasherObjectFloat(tableKeySources, tableSize, maximumLoadFactor, targetLoadFactor); + case Double: return new IncrementalAggOpenHasherObjectDouble(tableKeySources, tableSize, maximumLoadFactor, targetLoadFactor); + case Object: return new IncrementalAggOpenHasherObjectObject(tableKeySources, tableSize, maximumLoadFactor, targetLoadFactor); + } + } + } +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherByte.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherByte.java index 4cff761ada0..84e19b034fc 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherByte.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherByte.java @@ -30,31 +30,34 @@ public StaticAggOpenHasherByte(ColumnSource[] tableKeySources, int tableSize, this.mainKeySource0.ensureCapacity(tableSize); } - @Override + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final ByteChunk keyChunk0 = sourceKeyChunks[0].asByteChunk(); final int chunkSize = keyChunk0.size(); for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { final byte k0 = keyChunk0.get(chunkPosition); final int hash = hash(k0); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; while (true) { - int tableState = mainOutputPosition.getUnsafe(tableLocation); - if (tableState == EMPTY_OUTPUT_POSITION) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { numEntries++; mainKeySource0.set(tableLocation, k0); - final int outputPosition = nextOutputPosition.getAndIncrement(); + outputPosition = nextOutputPosition.getAndIncrement(); outputPositions.set(chunkPosition, outputPosition); mainOutputPosition.set(tableLocation, outputPosition); outputPositionToHashSlot.set(outputPosition, tableLocation); break; } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0)) { - outputPositions.set(chunkPosition, tableState); + outputPositions.set(chunkPosition, outputPosition); break; } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } @@ -66,8 +69,7 @@ private static int hash(byte k0) { } @Override - protected void rehashInternal() { - final int oldSize = tableSize >> 1; + protected void rehashInternalFull(final int oldSize) { final byte[] destKeyArray0 = new byte[tableSize]; final int[] destState = new int[tableSize]; Arrays.fill(destState, EMPTY_OUTPUT_POSITION); @@ -76,25 +78,25 @@ protected void rehashInternal() { final int [] originalStateArray = mainOutputPosition.getArray(); mainOutputPosition.setArray(destState); for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { - if (originalStateArray[sourceBucket] == EMPTY_OUTPUT_POSITION) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { continue; } final byte k0 = originalKeyArray0[sourceBucket]; final int hash = hash(k0); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; while (true) { - if (destState[tableLocation] == EMPTY_OUTPUT_POSITION) { - destKeyArray0[tableLocation] = k0; - destState[tableLocation] = originalStateArray[sourceBucket]; - if (sourceBucket != tableLocation) { - outputPositionToHashSlot.set(destState[tableLocation], tableLocation); + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + if (sourceBucket != destinationTableLocation) { + outputPositionToHashSlot.set(currentStateValue, destinationTableLocation); } break; - } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); } } } @@ -104,7 +106,7 @@ public int findPositionForKey(Object key) { final byte k0 = TypeUtils.unbox((Byte)key); int hash = hash(k0); int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = tableLocation; while (true) { final int positionValue = mainOutputPosition.getUnsafe(tableLocation); if (positionValue == EMPTY_OUTPUT_POSITION) { @@ -113,8 +115,8 @@ public int findPositionForKey(Object key) { if (eq(mainKeySource0.getUnsafe(tableLocation), k0)) { return positionValue; } - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherByteByte.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherByteByte.java index a1976a9375c..ac55f8d57bf 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherByteByte.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherByteByte.java @@ -34,7 +34,10 @@ public StaticAggOpenHasherByteByte(ColumnSource[] tableKeySources, int tableSize this.mainKeySource1.ensureCapacity(tableSize); } - @Override + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final ByteChunk keyChunk0 = sourceKeyChunks[0].asByteChunk(); final ByteChunk keyChunk1 = sourceKeyChunks[1].asByteChunk(); @@ -43,25 +46,25 @@ protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final byte k0 = keyChunk0.get(chunkPosition); final byte k1 = keyChunk1.get(chunkPosition); final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; while (true) { - int tableState = mainOutputPosition.getUnsafe(tableLocation); - if (tableState == EMPTY_OUTPUT_POSITION) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { numEntries++; mainKeySource0.set(tableLocation, k0); mainKeySource1.set(tableLocation, k1); - final int outputPosition = nextOutputPosition.getAndIncrement(); + outputPosition = nextOutputPosition.getAndIncrement(); outputPositions.set(chunkPosition, outputPosition); mainOutputPosition.set(tableLocation, outputPosition); outputPositionToHashSlot.set(outputPosition, tableLocation); break; } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { - outputPositions.set(chunkPosition, tableState); + outputPositions.set(chunkPosition, outputPosition); break; } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } @@ -74,8 +77,7 @@ private static int hash(byte k0, byte k1) { } @Override - protected void rehashInternal() { - final int oldSize = tableSize >> 1; + protected void rehashInternalFull(final int oldSize) { final byte[] destKeyArray0 = new byte[tableSize]; final byte[] destKeyArray1 = new byte[tableSize]; final int[] destState = new int[tableSize]; @@ -87,27 +89,27 @@ protected void rehashInternal() { final int [] originalStateArray = mainOutputPosition.getArray(); mainOutputPosition.setArray(destState); for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { - if (originalStateArray[sourceBucket] == EMPTY_OUTPUT_POSITION) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { continue; } final byte k0 = originalKeyArray0[sourceBucket]; final byte k1 = originalKeyArray1[sourceBucket]; final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; while (true) { - if (destState[tableLocation] == EMPTY_OUTPUT_POSITION) { - destKeyArray0[tableLocation] = k0; - destKeyArray1[tableLocation] = k1; - destState[tableLocation] = originalStateArray[sourceBucket]; - if (sourceBucket != tableLocation) { - outputPositionToHashSlot.set(destState[tableLocation], tableLocation); + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + if (sourceBucket != destinationTableLocation) { + outputPositionToHashSlot.set(currentStateValue, destinationTableLocation); } break; - } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); } } } @@ -119,7 +121,7 @@ public int findPositionForKey(Object key) { final byte k1 = TypeUtils.unbox((Byte)ka[1]); int hash = hash(k0, k1); int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = tableLocation; while (true) { final int positionValue = mainOutputPosition.getUnsafe(tableLocation); if (positionValue == EMPTY_OUTPUT_POSITION) { @@ -128,8 +130,8 @@ public int findPositionForKey(Object key) { if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { return positionValue; } - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherByteChar.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherByteChar.java index d8ff51e49da..2962ee2d5db 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherByteChar.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherByteChar.java @@ -39,7 +39,10 @@ public StaticAggOpenHasherByteChar(ColumnSource[] tableKeySources, int tableSize this.mainKeySource1.ensureCapacity(tableSize); } - @Override + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final ByteChunk keyChunk0 = sourceKeyChunks[0].asByteChunk(); final CharChunk keyChunk1 = sourceKeyChunks[1].asCharChunk(); @@ -48,25 +51,25 @@ protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final byte k0 = keyChunk0.get(chunkPosition); final char k1 = keyChunk1.get(chunkPosition); final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; while (true) { - int tableState = mainOutputPosition.getUnsafe(tableLocation); - if (tableState == EMPTY_OUTPUT_POSITION) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { numEntries++; mainKeySource0.set(tableLocation, k0); mainKeySource1.set(tableLocation, k1); - final int outputPosition = nextOutputPosition.getAndIncrement(); + outputPosition = nextOutputPosition.getAndIncrement(); outputPositions.set(chunkPosition, outputPosition); mainOutputPosition.set(tableLocation, outputPosition); outputPositionToHashSlot.set(outputPosition, tableLocation); break; } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { - outputPositions.set(chunkPosition, tableState); + outputPositions.set(chunkPosition, outputPosition); break; } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } @@ -79,8 +82,7 @@ private static int hash(byte k0, char k1) { } @Override - protected void rehashInternal() { - final int oldSize = tableSize >> 1; + protected void rehashInternalFull(final int oldSize) { final byte[] destKeyArray0 = new byte[tableSize]; final char[] destKeyArray1 = new char[tableSize]; final int[] destState = new int[tableSize]; @@ -92,27 +94,27 @@ protected void rehashInternal() { final int [] originalStateArray = mainOutputPosition.getArray(); mainOutputPosition.setArray(destState); for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { - if (originalStateArray[sourceBucket] == EMPTY_OUTPUT_POSITION) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { continue; } final byte k0 = originalKeyArray0[sourceBucket]; final char k1 = originalKeyArray1[sourceBucket]; final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; while (true) { - if (destState[tableLocation] == EMPTY_OUTPUT_POSITION) { - destKeyArray0[tableLocation] = k0; - destKeyArray1[tableLocation] = k1; - destState[tableLocation] = originalStateArray[sourceBucket]; - if (sourceBucket != tableLocation) { - outputPositionToHashSlot.set(destState[tableLocation], tableLocation); + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + if (sourceBucket != destinationTableLocation) { + outputPositionToHashSlot.set(currentStateValue, destinationTableLocation); } break; - } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); } } } @@ -124,7 +126,7 @@ public int findPositionForKey(Object key) { final char k1 = TypeUtils.unbox((Character)ka[1]); int hash = hash(k0, k1); int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = tableLocation; while (true) { final int positionValue = mainOutputPosition.getUnsafe(tableLocation); if (positionValue == EMPTY_OUTPUT_POSITION) { @@ -133,8 +135,8 @@ public int findPositionForKey(Object key) { if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { return positionValue; } - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherByteDouble.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherByteDouble.java index 7a34d1d9167..348fe115ab1 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherByteDouble.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherByteDouble.java @@ -39,7 +39,10 @@ public StaticAggOpenHasherByteDouble(ColumnSource[] tableKeySources, int tableSi this.mainKeySource1.ensureCapacity(tableSize); } - @Override + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final ByteChunk keyChunk0 = sourceKeyChunks[0].asByteChunk(); final DoubleChunk keyChunk1 = sourceKeyChunks[1].asDoubleChunk(); @@ -48,25 +51,25 @@ protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final byte k0 = keyChunk0.get(chunkPosition); final double k1 = keyChunk1.get(chunkPosition); final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; while (true) { - int tableState = mainOutputPosition.getUnsafe(tableLocation); - if (tableState == EMPTY_OUTPUT_POSITION) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { numEntries++; mainKeySource0.set(tableLocation, k0); mainKeySource1.set(tableLocation, k1); - final int outputPosition = nextOutputPosition.getAndIncrement(); + outputPosition = nextOutputPosition.getAndIncrement(); outputPositions.set(chunkPosition, outputPosition); mainOutputPosition.set(tableLocation, outputPosition); outputPositionToHashSlot.set(outputPosition, tableLocation); break; } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { - outputPositions.set(chunkPosition, tableState); + outputPositions.set(chunkPosition, outputPosition); break; } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } @@ -79,8 +82,7 @@ private static int hash(byte k0, double k1) { } @Override - protected void rehashInternal() { - final int oldSize = tableSize >> 1; + protected void rehashInternalFull(final int oldSize) { final byte[] destKeyArray0 = new byte[tableSize]; final double[] destKeyArray1 = new double[tableSize]; final int[] destState = new int[tableSize]; @@ -92,27 +94,27 @@ protected void rehashInternal() { final int [] originalStateArray = mainOutputPosition.getArray(); mainOutputPosition.setArray(destState); for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { - if (originalStateArray[sourceBucket] == EMPTY_OUTPUT_POSITION) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { continue; } final byte k0 = originalKeyArray0[sourceBucket]; final double k1 = originalKeyArray1[sourceBucket]; final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; while (true) { - if (destState[tableLocation] == EMPTY_OUTPUT_POSITION) { - destKeyArray0[tableLocation] = k0; - destKeyArray1[tableLocation] = k1; - destState[tableLocation] = originalStateArray[sourceBucket]; - if (sourceBucket != tableLocation) { - outputPositionToHashSlot.set(destState[tableLocation], tableLocation); + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + if (sourceBucket != destinationTableLocation) { + outputPositionToHashSlot.set(currentStateValue, destinationTableLocation); } break; - } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); } } } @@ -124,7 +126,7 @@ public int findPositionForKey(Object key) { final double k1 = TypeUtils.unbox((Double)ka[1]); int hash = hash(k0, k1); int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = tableLocation; while (true) { final int positionValue = mainOutputPosition.getUnsafe(tableLocation); if (positionValue == EMPTY_OUTPUT_POSITION) { @@ -133,8 +135,8 @@ public int findPositionForKey(Object key) { if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { return positionValue; } - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherByteFloat.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherByteFloat.java index 200a9c7a0b4..f87997df4ce 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherByteFloat.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherByteFloat.java @@ -39,7 +39,10 @@ public StaticAggOpenHasherByteFloat(ColumnSource[] tableKeySources, int tableSiz this.mainKeySource1.ensureCapacity(tableSize); } - @Override + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final ByteChunk keyChunk0 = sourceKeyChunks[0].asByteChunk(); final FloatChunk keyChunk1 = sourceKeyChunks[1].asFloatChunk(); @@ -48,25 +51,25 @@ protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final byte k0 = keyChunk0.get(chunkPosition); final float k1 = keyChunk1.get(chunkPosition); final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; while (true) { - int tableState = mainOutputPosition.getUnsafe(tableLocation); - if (tableState == EMPTY_OUTPUT_POSITION) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { numEntries++; mainKeySource0.set(tableLocation, k0); mainKeySource1.set(tableLocation, k1); - final int outputPosition = nextOutputPosition.getAndIncrement(); + outputPosition = nextOutputPosition.getAndIncrement(); outputPositions.set(chunkPosition, outputPosition); mainOutputPosition.set(tableLocation, outputPosition); outputPositionToHashSlot.set(outputPosition, tableLocation); break; } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { - outputPositions.set(chunkPosition, tableState); + outputPositions.set(chunkPosition, outputPosition); break; } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } @@ -79,8 +82,7 @@ private static int hash(byte k0, float k1) { } @Override - protected void rehashInternal() { - final int oldSize = tableSize >> 1; + protected void rehashInternalFull(final int oldSize) { final byte[] destKeyArray0 = new byte[tableSize]; final float[] destKeyArray1 = new float[tableSize]; final int[] destState = new int[tableSize]; @@ -92,27 +94,27 @@ protected void rehashInternal() { final int [] originalStateArray = mainOutputPosition.getArray(); mainOutputPosition.setArray(destState); for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { - if (originalStateArray[sourceBucket] == EMPTY_OUTPUT_POSITION) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { continue; } final byte k0 = originalKeyArray0[sourceBucket]; final float k1 = originalKeyArray1[sourceBucket]; final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; while (true) { - if (destState[tableLocation] == EMPTY_OUTPUT_POSITION) { - destKeyArray0[tableLocation] = k0; - destKeyArray1[tableLocation] = k1; - destState[tableLocation] = originalStateArray[sourceBucket]; - if (sourceBucket != tableLocation) { - outputPositionToHashSlot.set(destState[tableLocation], tableLocation); + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + if (sourceBucket != destinationTableLocation) { + outputPositionToHashSlot.set(currentStateValue, destinationTableLocation); } break; - } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); } } } @@ -124,7 +126,7 @@ public int findPositionForKey(Object key) { final float k1 = TypeUtils.unbox((Float)ka[1]); int hash = hash(k0, k1); int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = tableLocation; while (true) { final int positionValue = mainOutputPosition.getUnsafe(tableLocation); if (positionValue == EMPTY_OUTPUT_POSITION) { @@ -133,8 +135,8 @@ public int findPositionForKey(Object key) { if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { return positionValue; } - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherByteInt.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherByteInt.java index 1175952d496..76a9e961338 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherByteInt.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherByteInt.java @@ -39,7 +39,10 @@ public StaticAggOpenHasherByteInt(ColumnSource[] tableKeySources, int tableSize, this.mainKeySource1.ensureCapacity(tableSize); } - @Override + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final ByteChunk keyChunk0 = sourceKeyChunks[0].asByteChunk(); final IntChunk keyChunk1 = sourceKeyChunks[1].asIntChunk(); @@ -48,25 +51,25 @@ protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final byte k0 = keyChunk0.get(chunkPosition); final int k1 = keyChunk1.get(chunkPosition); final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; while (true) { - int tableState = mainOutputPosition.getUnsafe(tableLocation); - if (tableState == EMPTY_OUTPUT_POSITION) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { numEntries++; mainKeySource0.set(tableLocation, k0); mainKeySource1.set(tableLocation, k1); - final int outputPosition = nextOutputPosition.getAndIncrement(); + outputPosition = nextOutputPosition.getAndIncrement(); outputPositions.set(chunkPosition, outputPosition); mainOutputPosition.set(tableLocation, outputPosition); outputPositionToHashSlot.set(outputPosition, tableLocation); break; } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { - outputPositions.set(chunkPosition, tableState); + outputPositions.set(chunkPosition, outputPosition); break; } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } @@ -79,8 +82,7 @@ private static int hash(byte k0, int k1) { } @Override - protected void rehashInternal() { - final int oldSize = tableSize >> 1; + protected void rehashInternalFull(final int oldSize) { final byte[] destKeyArray0 = new byte[tableSize]; final int[] destKeyArray1 = new int[tableSize]; final int[] destState = new int[tableSize]; @@ -92,27 +94,27 @@ protected void rehashInternal() { final int [] originalStateArray = mainOutputPosition.getArray(); mainOutputPosition.setArray(destState); for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { - if (originalStateArray[sourceBucket] == EMPTY_OUTPUT_POSITION) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { continue; } final byte k0 = originalKeyArray0[sourceBucket]; final int k1 = originalKeyArray1[sourceBucket]; final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; while (true) { - if (destState[tableLocation] == EMPTY_OUTPUT_POSITION) { - destKeyArray0[tableLocation] = k0; - destKeyArray1[tableLocation] = k1; - destState[tableLocation] = originalStateArray[sourceBucket]; - if (sourceBucket != tableLocation) { - outputPositionToHashSlot.set(destState[tableLocation], tableLocation); + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + if (sourceBucket != destinationTableLocation) { + outputPositionToHashSlot.set(currentStateValue, destinationTableLocation); } break; - } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); } } } @@ -124,7 +126,7 @@ public int findPositionForKey(Object key) { final int k1 = TypeUtils.unbox((Integer)ka[1]); int hash = hash(k0, k1); int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = tableLocation; while (true) { final int positionValue = mainOutputPosition.getUnsafe(tableLocation); if (positionValue == EMPTY_OUTPUT_POSITION) { @@ -133,8 +135,8 @@ public int findPositionForKey(Object key) { if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { return positionValue; } - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherByteLong.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherByteLong.java index ae0618e9f5d..a92ba201374 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherByteLong.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherByteLong.java @@ -39,7 +39,10 @@ public StaticAggOpenHasherByteLong(ColumnSource[] tableKeySources, int tableSize this.mainKeySource1.ensureCapacity(tableSize); } - @Override + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final ByteChunk keyChunk0 = sourceKeyChunks[0].asByteChunk(); final LongChunk keyChunk1 = sourceKeyChunks[1].asLongChunk(); @@ -48,25 +51,25 @@ protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final byte k0 = keyChunk0.get(chunkPosition); final long k1 = keyChunk1.get(chunkPosition); final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; while (true) { - int tableState = mainOutputPosition.getUnsafe(tableLocation); - if (tableState == EMPTY_OUTPUT_POSITION) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { numEntries++; mainKeySource0.set(tableLocation, k0); mainKeySource1.set(tableLocation, k1); - final int outputPosition = nextOutputPosition.getAndIncrement(); + outputPosition = nextOutputPosition.getAndIncrement(); outputPositions.set(chunkPosition, outputPosition); mainOutputPosition.set(tableLocation, outputPosition); outputPositionToHashSlot.set(outputPosition, tableLocation); break; } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { - outputPositions.set(chunkPosition, tableState); + outputPositions.set(chunkPosition, outputPosition); break; } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } @@ -79,8 +82,7 @@ private static int hash(byte k0, long k1) { } @Override - protected void rehashInternal() { - final int oldSize = tableSize >> 1; + protected void rehashInternalFull(final int oldSize) { final byte[] destKeyArray0 = new byte[tableSize]; final long[] destKeyArray1 = new long[tableSize]; final int[] destState = new int[tableSize]; @@ -92,27 +94,27 @@ protected void rehashInternal() { final int [] originalStateArray = mainOutputPosition.getArray(); mainOutputPosition.setArray(destState); for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { - if (originalStateArray[sourceBucket] == EMPTY_OUTPUT_POSITION) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { continue; } final byte k0 = originalKeyArray0[sourceBucket]; final long k1 = originalKeyArray1[sourceBucket]; final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; while (true) { - if (destState[tableLocation] == EMPTY_OUTPUT_POSITION) { - destKeyArray0[tableLocation] = k0; - destKeyArray1[tableLocation] = k1; - destState[tableLocation] = originalStateArray[sourceBucket]; - if (sourceBucket != tableLocation) { - outputPositionToHashSlot.set(destState[tableLocation], tableLocation); + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + if (sourceBucket != destinationTableLocation) { + outputPositionToHashSlot.set(currentStateValue, destinationTableLocation); } break; - } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); } } } @@ -124,7 +126,7 @@ public int findPositionForKey(Object key) { final long k1 = TypeUtils.unbox((Long)ka[1]); int hash = hash(k0, k1); int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = tableLocation; while (true) { final int positionValue = mainOutputPosition.getUnsafe(tableLocation); if (positionValue == EMPTY_OUTPUT_POSITION) { @@ -133,8 +135,8 @@ public int findPositionForKey(Object key) { if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { return positionValue; } - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherByteObject.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherByteObject.java index f0f4b5cc81e..c9730fd990f 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherByteObject.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherByteObject.java @@ -38,7 +38,10 @@ public StaticAggOpenHasherByteObject(ColumnSource[] tableKeySources, int tableSi this.mainKeySource1.ensureCapacity(tableSize); } - @Override + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final ByteChunk keyChunk0 = sourceKeyChunks[0].asByteChunk(); final ObjectChunk keyChunk1 = sourceKeyChunks[1].asObjectChunk(); @@ -47,25 +50,25 @@ protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final byte k0 = keyChunk0.get(chunkPosition); final Object k1 = keyChunk1.get(chunkPosition); final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; while (true) { - int tableState = mainOutputPosition.getUnsafe(tableLocation); - if (tableState == EMPTY_OUTPUT_POSITION) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { numEntries++; mainKeySource0.set(tableLocation, k0); mainKeySource1.set(tableLocation, k1); - final int outputPosition = nextOutputPosition.getAndIncrement(); + outputPosition = nextOutputPosition.getAndIncrement(); outputPositions.set(chunkPosition, outputPosition); mainOutputPosition.set(tableLocation, outputPosition); outputPositionToHashSlot.set(outputPosition, tableLocation); break; } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { - outputPositions.set(chunkPosition, tableState); + outputPositions.set(chunkPosition, outputPosition); break; } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } @@ -78,8 +81,7 @@ private static int hash(byte k0, Object k1) { } @Override - protected void rehashInternal() { - final int oldSize = tableSize >> 1; + protected void rehashInternalFull(final int oldSize) { final byte[] destKeyArray0 = new byte[tableSize]; final Object[] destKeyArray1 = new Object[tableSize]; final int[] destState = new int[tableSize]; @@ -91,27 +93,27 @@ protected void rehashInternal() { final int [] originalStateArray = mainOutputPosition.getArray(); mainOutputPosition.setArray(destState); for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { - if (originalStateArray[sourceBucket] == EMPTY_OUTPUT_POSITION) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { continue; } final byte k0 = originalKeyArray0[sourceBucket]; final Object k1 = originalKeyArray1[sourceBucket]; final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; while (true) { - if (destState[tableLocation] == EMPTY_OUTPUT_POSITION) { - destKeyArray0[tableLocation] = k0; - destKeyArray1[tableLocation] = k1; - destState[tableLocation] = originalStateArray[sourceBucket]; - if (sourceBucket != tableLocation) { - outputPositionToHashSlot.set(destState[tableLocation], tableLocation); + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + if (sourceBucket != destinationTableLocation) { + outputPositionToHashSlot.set(currentStateValue, destinationTableLocation); } break; - } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); } } } @@ -123,7 +125,7 @@ public int findPositionForKey(Object key) { final Object k1 = ka[1]; int hash = hash(k0, k1); int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = tableLocation; while (true) { final int positionValue = mainOutputPosition.getUnsafe(tableLocation); if (positionValue == EMPTY_OUTPUT_POSITION) { @@ -132,8 +134,8 @@ public int findPositionForKey(Object key) { if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { return positionValue; } - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherByteShort.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherByteShort.java index 7d38aebfe7e..77309ed2081 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherByteShort.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherByteShort.java @@ -39,7 +39,10 @@ public StaticAggOpenHasherByteShort(ColumnSource[] tableKeySources, int tableSiz this.mainKeySource1.ensureCapacity(tableSize); } - @Override + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final ByteChunk keyChunk0 = sourceKeyChunks[0].asByteChunk(); final ShortChunk keyChunk1 = sourceKeyChunks[1].asShortChunk(); @@ -48,25 +51,25 @@ protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final byte k0 = keyChunk0.get(chunkPosition); final short k1 = keyChunk1.get(chunkPosition); final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; while (true) { - int tableState = mainOutputPosition.getUnsafe(tableLocation); - if (tableState == EMPTY_OUTPUT_POSITION) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { numEntries++; mainKeySource0.set(tableLocation, k0); mainKeySource1.set(tableLocation, k1); - final int outputPosition = nextOutputPosition.getAndIncrement(); + outputPosition = nextOutputPosition.getAndIncrement(); outputPositions.set(chunkPosition, outputPosition); mainOutputPosition.set(tableLocation, outputPosition); outputPositionToHashSlot.set(outputPosition, tableLocation); break; } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { - outputPositions.set(chunkPosition, tableState); + outputPositions.set(chunkPosition, outputPosition); break; } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } @@ -79,8 +82,7 @@ private static int hash(byte k0, short k1) { } @Override - protected void rehashInternal() { - final int oldSize = tableSize >> 1; + protected void rehashInternalFull(final int oldSize) { final byte[] destKeyArray0 = new byte[tableSize]; final short[] destKeyArray1 = new short[tableSize]; final int[] destState = new int[tableSize]; @@ -92,27 +94,27 @@ protected void rehashInternal() { final int [] originalStateArray = mainOutputPosition.getArray(); mainOutputPosition.setArray(destState); for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { - if (originalStateArray[sourceBucket] == EMPTY_OUTPUT_POSITION) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { continue; } final byte k0 = originalKeyArray0[sourceBucket]; final short k1 = originalKeyArray1[sourceBucket]; final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; while (true) { - if (destState[tableLocation] == EMPTY_OUTPUT_POSITION) { - destKeyArray0[tableLocation] = k0; - destKeyArray1[tableLocation] = k1; - destState[tableLocation] = originalStateArray[sourceBucket]; - if (sourceBucket != tableLocation) { - outputPositionToHashSlot.set(destState[tableLocation], tableLocation); + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + if (sourceBucket != destinationTableLocation) { + outputPositionToHashSlot.set(currentStateValue, destinationTableLocation); } break; - } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); } } } @@ -124,7 +126,7 @@ public int findPositionForKey(Object key) { final short k1 = TypeUtils.unbox((Short)ka[1]); int hash = hash(k0, k1); int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = tableLocation; while (true) { final int positionValue = mainOutputPosition.getUnsafe(tableLocation); if (positionValue == EMPTY_OUTPUT_POSITION) { @@ -133,8 +135,8 @@ public int findPositionForKey(Object key) { if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { return positionValue; } - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherChar.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherChar.java index 55c64348cf9..9043fda4b8e 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherChar.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherChar.java @@ -30,31 +30,34 @@ public StaticAggOpenHasherChar(ColumnSource[] tableKeySources, int tableSize, this.mainKeySource0.ensureCapacity(tableSize); } - @Override + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final CharChunk keyChunk0 = sourceKeyChunks[0].asCharChunk(); final int chunkSize = keyChunk0.size(); for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { final char k0 = keyChunk0.get(chunkPosition); final int hash = hash(k0); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; while (true) { - int tableState = mainOutputPosition.getUnsafe(tableLocation); - if (tableState == EMPTY_OUTPUT_POSITION) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { numEntries++; mainKeySource0.set(tableLocation, k0); - final int outputPosition = nextOutputPosition.getAndIncrement(); + outputPosition = nextOutputPosition.getAndIncrement(); outputPositions.set(chunkPosition, outputPosition); mainOutputPosition.set(tableLocation, outputPosition); outputPositionToHashSlot.set(outputPosition, tableLocation); break; } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0)) { - outputPositions.set(chunkPosition, tableState); + outputPositions.set(chunkPosition, outputPosition); break; } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } @@ -66,8 +69,7 @@ private static int hash(char k0) { } @Override - protected void rehashInternal() { - final int oldSize = tableSize >> 1; + protected void rehashInternalFull(final int oldSize) { final char[] destKeyArray0 = new char[tableSize]; final int[] destState = new int[tableSize]; Arrays.fill(destState, EMPTY_OUTPUT_POSITION); @@ -76,25 +78,25 @@ protected void rehashInternal() { final int [] originalStateArray = mainOutputPosition.getArray(); mainOutputPosition.setArray(destState); for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { - if (originalStateArray[sourceBucket] == EMPTY_OUTPUT_POSITION) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { continue; } final char k0 = originalKeyArray0[sourceBucket]; final int hash = hash(k0); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; while (true) { - if (destState[tableLocation] == EMPTY_OUTPUT_POSITION) { - destKeyArray0[tableLocation] = k0; - destState[tableLocation] = originalStateArray[sourceBucket]; - if (sourceBucket != tableLocation) { - outputPositionToHashSlot.set(destState[tableLocation], tableLocation); + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + if (sourceBucket != destinationTableLocation) { + outputPositionToHashSlot.set(currentStateValue, destinationTableLocation); } break; - } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); } } } @@ -104,7 +106,7 @@ public int findPositionForKey(Object key) { final char k0 = TypeUtils.unbox((Character)key); int hash = hash(k0); int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = tableLocation; while (true) { final int positionValue = mainOutputPosition.getUnsafe(tableLocation); if (positionValue == EMPTY_OUTPUT_POSITION) { @@ -113,8 +115,8 @@ public int findPositionForKey(Object key) { if (eq(mainKeySource0.getUnsafe(tableLocation), k0)) { return positionValue; } - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherCharByte.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherCharByte.java index a122fd8dd0f..d79f452736f 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherCharByte.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherCharByte.java @@ -39,7 +39,10 @@ public StaticAggOpenHasherCharByte(ColumnSource[] tableKeySources, int tableSize this.mainKeySource1.ensureCapacity(tableSize); } - @Override + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final CharChunk keyChunk0 = sourceKeyChunks[0].asCharChunk(); final ByteChunk keyChunk1 = sourceKeyChunks[1].asByteChunk(); @@ -48,25 +51,25 @@ protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final char k0 = keyChunk0.get(chunkPosition); final byte k1 = keyChunk1.get(chunkPosition); final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; while (true) { - int tableState = mainOutputPosition.getUnsafe(tableLocation); - if (tableState == EMPTY_OUTPUT_POSITION) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { numEntries++; mainKeySource0.set(tableLocation, k0); mainKeySource1.set(tableLocation, k1); - final int outputPosition = nextOutputPosition.getAndIncrement(); + outputPosition = nextOutputPosition.getAndIncrement(); outputPositions.set(chunkPosition, outputPosition); mainOutputPosition.set(tableLocation, outputPosition); outputPositionToHashSlot.set(outputPosition, tableLocation); break; } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { - outputPositions.set(chunkPosition, tableState); + outputPositions.set(chunkPosition, outputPosition); break; } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } @@ -79,8 +82,7 @@ private static int hash(char k0, byte k1) { } @Override - protected void rehashInternal() { - final int oldSize = tableSize >> 1; + protected void rehashInternalFull(final int oldSize) { final char[] destKeyArray0 = new char[tableSize]; final byte[] destKeyArray1 = new byte[tableSize]; final int[] destState = new int[tableSize]; @@ -92,27 +94,27 @@ protected void rehashInternal() { final int [] originalStateArray = mainOutputPosition.getArray(); mainOutputPosition.setArray(destState); for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { - if (originalStateArray[sourceBucket] == EMPTY_OUTPUT_POSITION) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { continue; } final char k0 = originalKeyArray0[sourceBucket]; final byte k1 = originalKeyArray1[sourceBucket]; final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; while (true) { - if (destState[tableLocation] == EMPTY_OUTPUT_POSITION) { - destKeyArray0[tableLocation] = k0; - destKeyArray1[tableLocation] = k1; - destState[tableLocation] = originalStateArray[sourceBucket]; - if (sourceBucket != tableLocation) { - outputPositionToHashSlot.set(destState[tableLocation], tableLocation); + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + if (sourceBucket != destinationTableLocation) { + outputPositionToHashSlot.set(currentStateValue, destinationTableLocation); } break; - } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); } } } @@ -124,7 +126,7 @@ public int findPositionForKey(Object key) { final byte k1 = TypeUtils.unbox((Byte)ka[1]); int hash = hash(k0, k1); int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = tableLocation; while (true) { final int positionValue = mainOutputPosition.getUnsafe(tableLocation); if (positionValue == EMPTY_OUTPUT_POSITION) { @@ -133,8 +135,8 @@ public int findPositionForKey(Object key) { if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { return positionValue; } - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherCharChar.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherCharChar.java index 2f7a33f33b8..252ebc940aa 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherCharChar.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherCharChar.java @@ -34,7 +34,10 @@ public StaticAggOpenHasherCharChar(ColumnSource[] tableKeySources, int tableSize this.mainKeySource1.ensureCapacity(tableSize); } - @Override + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final CharChunk keyChunk0 = sourceKeyChunks[0].asCharChunk(); final CharChunk keyChunk1 = sourceKeyChunks[1].asCharChunk(); @@ -43,25 +46,25 @@ protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final char k0 = keyChunk0.get(chunkPosition); final char k1 = keyChunk1.get(chunkPosition); final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; while (true) { - int tableState = mainOutputPosition.getUnsafe(tableLocation); - if (tableState == EMPTY_OUTPUT_POSITION) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { numEntries++; mainKeySource0.set(tableLocation, k0); mainKeySource1.set(tableLocation, k1); - final int outputPosition = nextOutputPosition.getAndIncrement(); + outputPosition = nextOutputPosition.getAndIncrement(); outputPositions.set(chunkPosition, outputPosition); mainOutputPosition.set(tableLocation, outputPosition); outputPositionToHashSlot.set(outputPosition, tableLocation); break; } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { - outputPositions.set(chunkPosition, tableState); + outputPositions.set(chunkPosition, outputPosition); break; } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } @@ -74,8 +77,7 @@ private static int hash(char k0, char k1) { } @Override - protected void rehashInternal() { - final int oldSize = tableSize >> 1; + protected void rehashInternalFull(final int oldSize) { final char[] destKeyArray0 = new char[tableSize]; final char[] destKeyArray1 = new char[tableSize]; final int[] destState = new int[tableSize]; @@ -87,27 +89,27 @@ protected void rehashInternal() { final int [] originalStateArray = mainOutputPosition.getArray(); mainOutputPosition.setArray(destState); for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { - if (originalStateArray[sourceBucket] == EMPTY_OUTPUT_POSITION) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { continue; } final char k0 = originalKeyArray0[sourceBucket]; final char k1 = originalKeyArray1[sourceBucket]; final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; while (true) { - if (destState[tableLocation] == EMPTY_OUTPUT_POSITION) { - destKeyArray0[tableLocation] = k0; - destKeyArray1[tableLocation] = k1; - destState[tableLocation] = originalStateArray[sourceBucket]; - if (sourceBucket != tableLocation) { - outputPositionToHashSlot.set(destState[tableLocation], tableLocation); + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + if (sourceBucket != destinationTableLocation) { + outputPositionToHashSlot.set(currentStateValue, destinationTableLocation); } break; - } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); } } } @@ -119,7 +121,7 @@ public int findPositionForKey(Object key) { final char k1 = TypeUtils.unbox((Character)ka[1]); int hash = hash(k0, k1); int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = tableLocation; while (true) { final int positionValue = mainOutputPosition.getUnsafe(tableLocation); if (positionValue == EMPTY_OUTPUT_POSITION) { @@ -128,8 +130,8 @@ public int findPositionForKey(Object key) { if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { return positionValue; } - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherCharDouble.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherCharDouble.java index 03f78d119d9..76cbd3a86bf 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherCharDouble.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherCharDouble.java @@ -39,7 +39,10 @@ public StaticAggOpenHasherCharDouble(ColumnSource[] tableKeySources, int tableSi this.mainKeySource1.ensureCapacity(tableSize); } - @Override + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final CharChunk keyChunk0 = sourceKeyChunks[0].asCharChunk(); final DoubleChunk keyChunk1 = sourceKeyChunks[1].asDoubleChunk(); @@ -48,25 +51,25 @@ protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final char k0 = keyChunk0.get(chunkPosition); final double k1 = keyChunk1.get(chunkPosition); final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; while (true) { - int tableState = mainOutputPosition.getUnsafe(tableLocation); - if (tableState == EMPTY_OUTPUT_POSITION) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { numEntries++; mainKeySource0.set(tableLocation, k0); mainKeySource1.set(tableLocation, k1); - final int outputPosition = nextOutputPosition.getAndIncrement(); + outputPosition = nextOutputPosition.getAndIncrement(); outputPositions.set(chunkPosition, outputPosition); mainOutputPosition.set(tableLocation, outputPosition); outputPositionToHashSlot.set(outputPosition, tableLocation); break; } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { - outputPositions.set(chunkPosition, tableState); + outputPositions.set(chunkPosition, outputPosition); break; } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } @@ -79,8 +82,7 @@ private static int hash(char k0, double k1) { } @Override - protected void rehashInternal() { - final int oldSize = tableSize >> 1; + protected void rehashInternalFull(final int oldSize) { final char[] destKeyArray0 = new char[tableSize]; final double[] destKeyArray1 = new double[tableSize]; final int[] destState = new int[tableSize]; @@ -92,27 +94,27 @@ protected void rehashInternal() { final int [] originalStateArray = mainOutputPosition.getArray(); mainOutputPosition.setArray(destState); for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { - if (originalStateArray[sourceBucket] == EMPTY_OUTPUT_POSITION) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { continue; } final char k0 = originalKeyArray0[sourceBucket]; final double k1 = originalKeyArray1[sourceBucket]; final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; while (true) { - if (destState[tableLocation] == EMPTY_OUTPUT_POSITION) { - destKeyArray0[tableLocation] = k0; - destKeyArray1[tableLocation] = k1; - destState[tableLocation] = originalStateArray[sourceBucket]; - if (sourceBucket != tableLocation) { - outputPositionToHashSlot.set(destState[tableLocation], tableLocation); + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + if (sourceBucket != destinationTableLocation) { + outputPositionToHashSlot.set(currentStateValue, destinationTableLocation); } break; - } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); } } } @@ -124,7 +126,7 @@ public int findPositionForKey(Object key) { final double k1 = TypeUtils.unbox((Double)ka[1]); int hash = hash(k0, k1); int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = tableLocation; while (true) { final int positionValue = mainOutputPosition.getUnsafe(tableLocation); if (positionValue == EMPTY_OUTPUT_POSITION) { @@ -133,8 +135,8 @@ public int findPositionForKey(Object key) { if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { return positionValue; } - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherCharFloat.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherCharFloat.java index 0f58e10c3ff..a45fe415af1 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherCharFloat.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherCharFloat.java @@ -39,7 +39,10 @@ public StaticAggOpenHasherCharFloat(ColumnSource[] tableKeySources, int tableSiz this.mainKeySource1.ensureCapacity(tableSize); } - @Override + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final CharChunk keyChunk0 = sourceKeyChunks[0].asCharChunk(); final FloatChunk keyChunk1 = sourceKeyChunks[1].asFloatChunk(); @@ -48,25 +51,25 @@ protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final char k0 = keyChunk0.get(chunkPosition); final float k1 = keyChunk1.get(chunkPosition); final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; while (true) { - int tableState = mainOutputPosition.getUnsafe(tableLocation); - if (tableState == EMPTY_OUTPUT_POSITION) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { numEntries++; mainKeySource0.set(tableLocation, k0); mainKeySource1.set(tableLocation, k1); - final int outputPosition = nextOutputPosition.getAndIncrement(); + outputPosition = nextOutputPosition.getAndIncrement(); outputPositions.set(chunkPosition, outputPosition); mainOutputPosition.set(tableLocation, outputPosition); outputPositionToHashSlot.set(outputPosition, tableLocation); break; } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { - outputPositions.set(chunkPosition, tableState); + outputPositions.set(chunkPosition, outputPosition); break; } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } @@ -79,8 +82,7 @@ private static int hash(char k0, float k1) { } @Override - protected void rehashInternal() { - final int oldSize = tableSize >> 1; + protected void rehashInternalFull(final int oldSize) { final char[] destKeyArray0 = new char[tableSize]; final float[] destKeyArray1 = new float[tableSize]; final int[] destState = new int[tableSize]; @@ -92,27 +94,27 @@ protected void rehashInternal() { final int [] originalStateArray = mainOutputPosition.getArray(); mainOutputPosition.setArray(destState); for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { - if (originalStateArray[sourceBucket] == EMPTY_OUTPUT_POSITION) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { continue; } final char k0 = originalKeyArray0[sourceBucket]; final float k1 = originalKeyArray1[sourceBucket]; final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; while (true) { - if (destState[tableLocation] == EMPTY_OUTPUT_POSITION) { - destKeyArray0[tableLocation] = k0; - destKeyArray1[tableLocation] = k1; - destState[tableLocation] = originalStateArray[sourceBucket]; - if (sourceBucket != tableLocation) { - outputPositionToHashSlot.set(destState[tableLocation], tableLocation); + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + if (sourceBucket != destinationTableLocation) { + outputPositionToHashSlot.set(currentStateValue, destinationTableLocation); } break; - } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); } } } @@ -124,7 +126,7 @@ public int findPositionForKey(Object key) { final float k1 = TypeUtils.unbox((Float)ka[1]); int hash = hash(k0, k1); int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = tableLocation; while (true) { final int positionValue = mainOutputPosition.getUnsafe(tableLocation); if (positionValue == EMPTY_OUTPUT_POSITION) { @@ -133,8 +135,8 @@ public int findPositionForKey(Object key) { if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { return positionValue; } - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherCharInt.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherCharInt.java index 607f3631cce..4dacdd9a633 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherCharInt.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherCharInt.java @@ -39,7 +39,10 @@ public StaticAggOpenHasherCharInt(ColumnSource[] tableKeySources, int tableSize, this.mainKeySource1.ensureCapacity(tableSize); } - @Override + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final CharChunk keyChunk0 = sourceKeyChunks[0].asCharChunk(); final IntChunk keyChunk1 = sourceKeyChunks[1].asIntChunk(); @@ -48,25 +51,25 @@ protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final char k0 = keyChunk0.get(chunkPosition); final int k1 = keyChunk1.get(chunkPosition); final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; while (true) { - int tableState = mainOutputPosition.getUnsafe(tableLocation); - if (tableState == EMPTY_OUTPUT_POSITION) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { numEntries++; mainKeySource0.set(tableLocation, k0); mainKeySource1.set(tableLocation, k1); - final int outputPosition = nextOutputPosition.getAndIncrement(); + outputPosition = nextOutputPosition.getAndIncrement(); outputPositions.set(chunkPosition, outputPosition); mainOutputPosition.set(tableLocation, outputPosition); outputPositionToHashSlot.set(outputPosition, tableLocation); break; } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { - outputPositions.set(chunkPosition, tableState); + outputPositions.set(chunkPosition, outputPosition); break; } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } @@ -79,8 +82,7 @@ private static int hash(char k0, int k1) { } @Override - protected void rehashInternal() { - final int oldSize = tableSize >> 1; + protected void rehashInternalFull(final int oldSize) { final char[] destKeyArray0 = new char[tableSize]; final int[] destKeyArray1 = new int[tableSize]; final int[] destState = new int[tableSize]; @@ -92,27 +94,27 @@ protected void rehashInternal() { final int [] originalStateArray = mainOutputPosition.getArray(); mainOutputPosition.setArray(destState); for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { - if (originalStateArray[sourceBucket] == EMPTY_OUTPUT_POSITION) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { continue; } final char k0 = originalKeyArray0[sourceBucket]; final int k1 = originalKeyArray1[sourceBucket]; final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; while (true) { - if (destState[tableLocation] == EMPTY_OUTPUT_POSITION) { - destKeyArray0[tableLocation] = k0; - destKeyArray1[tableLocation] = k1; - destState[tableLocation] = originalStateArray[sourceBucket]; - if (sourceBucket != tableLocation) { - outputPositionToHashSlot.set(destState[tableLocation], tableLocation); + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + if (sourceBucket != destinationTableLocation) { + outputPositionToHashSlot.set(currentStateValue, destinationTableLocation); } break; - } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); } } } @@ -124,7 +126,7 @@ public int findPositionForKey(Object key) { final int k1 = TypeUtils.unbox((Integer)ka[1]); int hash = hash(k0, k1); int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = tableLocation; while (true) { final int positionValue = mainOutputPosition.getUnsafe(tableLocation); if (positionValue == EMPTY_OUTPUT_POSITION) { @@ -133,8 +135,8 @@ public int findPositionForKey(Object key) { if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { return positionValue; } - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherCharLong.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherCharLong.java index 972447185fc..019ba233c1f 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherCharLong.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherCharLong.java @@ -39,7 +39,10 @@ public StaticAggOpenHasherCharLong(ColumnSource[] tableKeySources, int tableSize this.mainKeySource1.ensureCapacity(tableSize); } - @Override + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final CharChunk keyChunk0 = sourceKeyChunks[0].asCharChunk(); final LongChunk keyChunk1 = sourceKeyChunks[1].asLongChunk(); @@ -48,25 +51,25 @@ protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final char k0 = keyChunk0.get(chunkPosition); final long k1 = keyChunk1.get(chunkPosition); final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; while (true) { - int tableState = mainOutputPosition.getUnsafe(tableLocation); - if (tableState == EMPTY_OUTPUT_POSITION) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { numEntries++; mainKeySource0.set(tableLocation, k0); mainKeySource1.set(tableLocation, k1); - final int outputPosition = nextOutputPosition.getAndIncrement(); + outputPosition = nextOutputPosition.getAndIncrement(); outputPositions.set(chunkPosition, outputPosition); mainOutputPosition.set(tableLocation, outputPosition); outputPositionToHashSlot.set(outputPosition, tableLocation); break; } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { - outputPositions.set(chunkPosition, tableState); + outputPositions.set(chunkPosition, outputPosition); break; } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } @@ -79,8 +82,7 @@ private static int hash(char k0, long k1) { } @Override - protected void rehashInternal() { - final int oldSize = tableSize >> 1; + protected void rehashInternalFull(final int oldSize) { final char[] destKeyArray0 = new char[tableSize]; final long[] destKeyArray1 = new long[tableSize]; final int[] destState = new int[tableSize]; @@ -92,27 +94,27 @@ protected void rehashInternal() { final int [] originalStateArray = mainOutputPosition.getArray(); mainOutputPosition.setArray(destState); for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { - if (originalStateArray[sourceBucket] == EMPTY_OUTPUT_POSITION) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { continue; } final char k0 = originalKeyArray0[sourceBucket]; final long k1 = originalKeyArray1[sourceBucket]; final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; while (true) { - if (destState[tableLocation] == EMPTY_OUTPUT_POSITION) { - destKeyArray0[tableLocation] = k0; - destKeyArray1[tableLocation] = k1; - destState[tableLocation] = originalStateArray[sourceBucket]; - if (sourceBucket != tableLocation) { - outputPositionToHashSlot.set(destState[tableLocation], tableLocation); + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + if (sourceBucket != destinationTableLocation) { + outputPositionToHashSlot.set(currentStateValue, destinationTableLocation); } break; - } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); } } } @@ -124,7 +126,7 @@ public int findPositionForKey(Object key) { final long k1 = TypeUtils.unbox((Long)ka[1]); int hash = hash(k0, k1); int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = tableLocation; while (true) { final int positionValue = mainOutputPosition.getUnsafe(tableLocation); if (positionValue == EMPTY_OUTPUT_POSITION) { @@ -133,8 +135,8 @@ public int findPositionForKey(Object key) { if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { return positionValue; } - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherCharObject.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherCharObject.java index d8ec17288c7..7dc67c601a8 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherCharObject.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherCharObject.java @@ -38,7 +38,10 @@ public StaticAggOpenHasherCharObject(ColumnSource[] tableKeySources, int tableSi this.mainKeySource1.ensureCapacity(tableSize); } - @Override + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final CharChunk keyChunk0 = sourceKeyChunks[0].asCharChunk(); final ObjectChunk keyChunk1 = sourceKeyChunks[1].asObjectChunk(); @@ -47,25 +50,25 @@ protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final char k0 = keyChunk0.get(chunkPosition); final Object k1 = keyChunk1.get(chunkPosition); final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; while (true) { - int tableState = mainOutputPosition.getUnsafe(tableLocation); - if (tableState == EMPTY_OUTPUT_POSITION) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { numEntries++; mainKeySource0.set(tableLocation, k0); mainKeySource1.set(tableLocation, k1); - final int outputPosition = nextOutputPosition.getAndIncrement(); + outputPosition = nextOutputPosition.getAndIncrement(); outputPositions.set(chunkPosition, outputPosition); mainOutputPosition.set(tableLocation, outputPosition); outputPositionToHashSlot.set(outputPosition, tableLocation); break; } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { - outputPositions.set(chunkPosition, tableState); + outputPositions.set(chunkPosition, outputPosition); break; } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } @@ -78,8 +81,7 @@ private static int hash(char k0, Object k1) { } @Override - protected void rehashInternal() { - final int oldSize = tableSize >> 1; + protected void rehashInternalFull(final int oldSize) { final char[] destKeyArray0 = new char[tableSize]; final Object[] destKeyArray1 = new Object[tableSize]; final int[] destState = new int[tableSize]; @@ -91,27 +93,27 @@ protected void rehashInternal() { final int [] originalStateArray = mainOutputPosition.getArray(); mainOutputPosition.setArray(destState); for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { - if (originalStateArray[sourceBucket] == EMPTY_OUTPUT_POSITION) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { continue; } final char k0 = originalKeyArray0[sourceBucket]; final Object k1 = originalKeyArray1[sourceBucket]; final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; while (true) { - if (destState[tableLocation] == EMPTY_OUTPUT_POSITION) { - destKeyArray0[tableLocation] = k0; - destKeyArray1[tableLocation] = k1; - destState[tableLocation] = originalStateArray[sourceBucket]; - if (sourceBucket != tableLocation) { - outputPositionToHashSlot.set(destState[tableLocation], tableLocation); + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + if (sourceBucket != destinationTableLocation) { + outputPositionToHashSlot.set(currentStateValue, destinationTableLocation); } break; - } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); } } } @@ -123,7 +125,7 @@ public int findPositionForKey(Object key) { final Object k1 = ka[1]; int hash = hash(k0, k1); int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = tableLocation; while (true) { final int positionValue = mainOutputPosition.getUnsafe(tableLocation); if (positionValue == EMPTY_OUTPUT_POSITION) { @@ -132,8 +134,8 @@ public int findPositionForKey(Object key) { if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { return positionValue; } - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherCharShort.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherCharShort.java index 85a2e8a1df8..257dacc7dba 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherCharShort.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherCharShort.java @@ -39,7 +39,10 @@ public StaticAggOpenHasherCharShort(ColumnSource[] tableKeySources, int tableSiz this.mainKeySource1.ensureCapacity(tableSize); } - @Override + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final CharChunk keyChunk0 = sourceKeyChunks[0].asCharChunk(); final ShortChunk keyChunk1 = sourceKeyChunks[1].asShortChunk(); @@ -48,25 +51,25 @@ protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final char k0 = keyChunk0.get(chunkPosition); final short k1 = keyChunk1.get(chunkPosition); final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; while (true) { - int tableState = mainOutputPosition.getUnsafe(tableLocation); - if (tableState == EMPTY_OUTPUT_POSITION) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { numEntries++; mainKeySource0.set(tableLocation, k0); mainKeySource1.set(tableLocation, k1); - final int outputPosition = nextOutputPosition.getAndIncrement(); + outputPosition = nextOutputPosition.getAndIncrement(); outputPositions.set(chunkPosition, outputPosition); mainOutputPosition.set(tableLocation, outputPosition); outputPositionToHashSlot.set(outputPosition, tableLocation); break; } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { - outputPositions.set(chunkPosition, tableState); + outputPositions.set(chunkPosition, outputPosition); break; } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } @@ -79,8 +82,7 @@ private static int hash(char k0, short k1) { } @Override - protected void rehashInternal() { - final int oldSize = tableSize >> 1; + protected void rehashInternalFull(final int oldSize) { final char[] destKeyArray0 = new char[tableSize]; final short[] destKeyArray1 = new short[tableSize]; final int[] destState = new int[tableSize]; @@ -92,27 +94,27 @@ protected void rehashInternal() { final int [] originalStateArray = mainOutputPosition.getArray(); mainOutputPosition.setArray(destState); for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { - if (originalStateArray[sourceBucket] == EMPTY_OUTPUT_POSITION) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { continue; } final char k0 = originalKeyArray0[sourceBucket]; final short k1 = originalKeyArray1[sourceBucket]; final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; while (true) { - if (destState[tableLocation] == EMPTY_OUTPUT_POSITION) { - destKeyArray0[tableLocation] = k0; - destKeyArray1[tableLocation] = k1; - destState[tableLocation] = originalStateArray[sourceBucket]; - if (sourceBucket != tableLocation) { - outputPositionToHashSlot.set(destState[tableLocation], tableLocation); + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + if (sourceBucket != destinationTableLocation) { + outputPositionToHashSlot.set(currentStateValue, destinationTableLocation); } break; - } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); } } } @@ -124,7 +126,7 @@ public int findPositionForKey(Object key) { final short k1 = TypeUtils.unbox((Short)ka[1]); int hash = hash(k0, k1); int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = tableLocation; while (true) { final int positionValue = mainOutputPosition.getUnsafe(tableLocation); if (positionValue == EMPTY_OUTPUT_POSITION) { @@ -133,8 +135,8 @@ public int findPositionForKey(Object key) { if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { return positionValue; } - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherDouble.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherDouble.java index a74dc5eb2d1..cca33384257 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherDouble.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherDouble.java @@ -30,31 +30,34 @@ public StaticAggOpenHasherDouble(ColumnSource[] tableKeySources, int tableSize, this.mainKeySource0.ensureCapacity(tableSize); } - @Override + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final DoubleChunk keyChunk0 = sourceKeyChunks[0].asDoubleChunk(); final int chunkSize = keyChunk0.size(); for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { final double k0 = keyChunk0.get(chunkPosition); final int hash = hash(k0); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; while (true) { - int tableState = mainOutputPosition.getUnsafe(tableLocation); - if (tableState == EMPTY_OUTPUT_POSITION) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { numEntries++; mainKeySource0.set(tableLocation, k0); - final int outputPosition = nextOutputPosition.getAndIncrement(); + outputPosition = nextOutputPosition.getAndIncrement(); outputPositions.set(chunkPosition, outputPosition); mainOutputPosition.set(tableLocation, outputPosition); outputPositionToHashSlot.set(outputPosition, tableLocation); break; } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0)) { - outputPositions.set(chunkPosition, tableState); + outputPositions.set(chunkPosition, outputPosition); break; } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } @@ -66,8 +69,7 @@ private static int hash(double k0) { } @Override - protected void rehashInternal() { - final int oldSize = tableSize >> 1; + protected void rehashInternalFull(final int oldSize) { final double[] destKeyArray0 = new double[tableSize]; final int[] destState = new int[tableSize]; Arrays.fill(destState, EMPTY_OUTPUT_POSITION); @@ -76,25 +78,25 @@ protected void rehashInternal() { final int [] originalStateArray = mainOutputPosition.getArray(); mainOutputPosition.setArray(destState); for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { - if (originalStateArray[sourceBucket] == EMPTY_OUTPUT_POSITION) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { continue; } final double k0 = originalKeyArray0[sourceBucket]; final int hash = hash(k0); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; while (true) { - if (destState[tableLocation] == EMPTY_OUTPUT_POSITION) { - destKeyArray0[tableLocation] = k0; - destState[tableLocation] = originalStateArray[sourceBucket]; - if (sourceBucket != tableLocation) { - outputPositionToHashSlot.set(destState[tableLocation], tableLocation); + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + if (sourceBucket != destinationTableLocation) { + outputPositionToHashSlot.set(currentStateValue, destinationTableLocation); } break; - } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); } } } @@ -104,7 +106,7 @@ public int findPositionForKey(Object key) { final double k0 = TypeUtils.unbox((Double)key); int hash = hash(k0); int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = tableLocation; while (true) { final int positionValue = mainOutputPosition.getUnsafe(tableLocation); if (positionValue == EMPTY_OUTPUT_POSITION) { @@ -113,8 +115,8 @@ public int findPositionForKey(Object key) { if (eq(mainKeySource0.getUnsafe(tableLocation), k0)) { return positionValue; } - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherDoubleByte.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherDoubleByte.java index 43c2c04df5f..03437194890 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherDoubleByte.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherDoubleByte.java @@ -39,7 +39,10 @@ public StaticAggOpenHasherDoubleByte(ColumnSource[] tableKeySources, int tableSi this.mainKeySource1.ensureCapacity(tableSize); } - @Override + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final DoubleChunk keyChunk0 = sourceKeyChunks[0].asDoubleChunk(); final ByteChunk keyChunk1 = sourceKeyChunks[1].asByteChunk(); @@ -48,25 +51,25 @@ protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final double k0 = keyChunk0.get(chunkPosition); final byte k1 = keyChunk1.get(chunkPosition); final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; while (true) { - int tableState = mainOutputPosition.getUnsafe(tableLocation); - if (tableState == EMPTY_OUTPUT_POSITION) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { numEntries++; mainKeySource0.set(tableLocation, k0); mainKeySource1.set(tableLocation, k1); - final int outputPosition = nextOutputPosition.getAndIncrement(); + outputPosition = nextOutputPosition.getAndIncrement(); outputPositions.set(chunkPosition, outputPosition); mainOutputPosition.set(tableLocation, outputPosition); outputPositionToHashSlot.set(outputPosition, tableLocation); break; } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { - outputPositions.set(chunkPosition, tableState); + outputPositions.set(chunkPosition, outputPosition); break; } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } @@ -79,8 +82,7 @@ private static int hash(double k0, byte k1) { } @Override - protected void rehashInternal() { - final int oldSize = tableSize >> 1; + protected void rehashInternalFull(final int oldSize) { final double[] destKeyArray0 = new double[tableSize]; final byte[] destKeyArray1 = new byte[tableSize]; final int[] destState = new int[tableSize]; @@ -92,27 +94,27 @@ protected void rehashInternal() { final int [] originalStateArray = mainOutputPosition.getArray(); mainOutputPosition.setArray(destState); for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { - if (originalStateArray[sourceBucket] == EMPTY_OUTPUT_POSITION) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { continue; } final double k0 = originalKeyArray0[sourceBucket]; final byte k1 = originalKeyArray1[sourceBucket]; final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; while (true) { - if (destState[tableLocation] == EMPTY_OUTPUT_POSITION) { - destKeyArray0[tableLocation] = k0; - destKeyArray1[tableLocation] = k1; - destState[tableLocation] = originalStateArray[sourceBucket]; - if (sourceBucket != tableLocation) { - outputPositionToHashSlot.set(destState[tableLocation], tableLocation); + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + if (sourceBucket != destinationTableLocation) { + outputPositionToHashSlot.set(currentStateValue, destinationTableLocation); } break; - } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); } } } @@ -124,7 +126,7 @@ public int findPositionForKey(Object key) { final byte k1 = TypeUtils.unbox((Byte)ka[1]); int hash = hash(k0, k1); int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = tableLocation; while (true) { final int positionValue = mainOutputPosition.getUnsafe(tableLocation); if (positionValue == EMPTY_OUTPUT_POSITION) { @@ -133,8 +135,8 @@ public int findPositionForKey(Object key) { if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { return positionValue; } - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherDoubleChar.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherDoubleChar.java index a94d20d06b6..77a58137dd5 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherDoubleChar.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherDoubleChar.java @@ -39,7 +39,10 @@ public StaticAggOpenHasherDoubleChar(ColumnSource[] tableKeySources, int tableSi this.mainKeySource1.ensureCapacity(tableSize); } - @Override + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final DoubleChunk keyChunk0 = sourceKeyChunks[0].asDoubleChunk(); final CharChunk keyChunk1 = sourceKeyChunks[1].asCharChunk(); @@ -48,25 +51,25 @@ protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final double k0 = keyChunk0.get(chunkPosition); final char k1 = keyChunk1.get(chunkPosition); final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; while (true) { - int tableState = mainOutputPosition.getUnsafe(tableLocation); - if (tableState == EMPTY_OUTPUT_POSITION) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { numEntries++; mainKeySource0.set(tableLocation, k0); mainKeySource1.set(tableLocation, k1); - final int outputPosition = nextOutputPosition.getAndIncrement(); + outputPosition = nextOutputPosition.getAndIncrement(); outputPositions.set(chunkPosition, outputPosition); mainOutputPosition.set(tableLocation, outputPosition); outputPositionToHashSlot.set(outputPosition, tableLocation); break; } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { - outputPositions.set(chunkPosition, tableState); + outputPositions.set(chunkPosition, outputPosition); break; } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } @@ -79,8 +82,7 @@ private static int hash(double k0, char k1) { } @Override - protected void rehashInternal() { - final int oldSize = tableSize >> 1; + protected void rehashInternalFull(final int oldSize) { final double[] destKeyArray0 = new double[tableSize]; final char[] destKeyArray1 = new char[tableSize]; final int[] destState = new int[tableSize]; @@ -92,27 +94,27 @@ protected void rehashInternal() { final int [] originalStateArray = mainOutputPosition.getArray(); mainOutputPosition.setArray(destState); for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { - if (originalStateArray[sourceBucket] == EMPTY_OUTPUT_POSITION) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { continue; } final double k0 = originalKeyArray0[sourceBucket]; final char k1 = originalKeyArray1[sourceBucket]; final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; while (true) { - if (destState[tableLocation] == EMPTY_OUTPUT_POSITION) { - destKeyArray0[tableLocation] = k0; - destKeyArray1[tableLocation] = k1; - destState[tableLocation] = originalStateArray[sourceBucket]; - if (sourceBucket != tableLocation) { - outputPositionToHashSlot.set(destState[tableLocation], tableLocation); + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + if (sourceBucket != destinationTableLocation) { + outputPositionToHashSlot.set(currentStateValue, destinationTableLocation); } break; - } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); } } } @@ -124,7 +126,7 @@ public int findPositionForKey(Object key) { final char k1 = TypeUtils.unbox((Character)ka[1]); int hash = hash(k0, k1); int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = tableLocation; while (true) { final int positionValue = mainOutputPosition.getUnsafe(tableLocation); if (positionValue == EMPTY_OUTPUT_POSITION) { @@ -133,8 +135,8 @@ public int findPositionForKey(Object key) { if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { return positionValue; } - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherDoubleDouble.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherDoubleDouble.java index 74e33caa169..e5a6a2b118c 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherDoubleDouble.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherDoubleDouble.java @@ -34,7 +34,10 @@ public StaticAggOpenHasherDoubleDouble(ColumnSource[] tableKeySources, int table this.mainKeySource1.ensureCapacity(tableSize); } - @Override + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final DoubleChunk keyChunk0 = sourceKeyChunks[0].asDoubleChunk(); final DoubleChunk keyChunk1 = sourceKeyChunks[1].asDoubleChunk(); @@ -43,25 +46,25 @@ protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final double k0 = keyChunk0.get(chunkPosition); final double k1 = keyChunk1.get(chunkPosition); final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; while (true) { - int tableState = mainOutputPosition.getUnsafe(tableLocation); - if (tableState == EMPTY_OUTPUT_POSITION) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { numEntries++; mainKeySource0.set(tableLocation, k0); mainKeySource1.set(tableLocation, k1); - final int outputPosition = nextOutputPosition.getAndIncrement(); + outputPosition = nextOutputPosition.getAndIncrement(); outputPositions.set(chunkPosition, outputPosition); mainOutputPosition.set(tableLocation, outputPosition); outputPositionToHashSlot.set(outputPosition, tableLocation); break; } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { - outputPositions.set(chunkPosition, tableState); + outputPositions.set(chunkPosition, outputPosition); break; } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } @@ -74,8 +77,7 @@ private static int hash(double k0, double k1) { } @Override - protected void rehashInternal() { - final int oldSize = tableSize >> 1; + protected void rehashInternalFull(final int oldSize) { final double[] destKeyArray0 = new double[tableSize]; final double[] destKeyArray1 = new double[tableSize]; final int[] destState = new int[tableSize]; @@ -87,27 +89,27 @@ protected void rehashInternal() { final int [] originalStateArray = mainOutputPosition.getArray(); mainOutputPosition.setArray(destState); for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { - if (originalStateArray[sourceBucket] == EMPTY_OUTPUT_POSITION) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { continue; } final double k0 = originalKeyArray0[sourceBucket]; final double k1 = originalKeyArray1[sourceBucket]; final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; while (true) { - if (destState[tableLocation] == EMPTY_OUTPUT_POSITION) { - destKeyArray0[tableLocation] = k0; - destKeyArray1[tableLocation] = k1; - destState[tableLocation] = originalStateArray[sourceBucket]; - if (sourceBucket != tableLocation) { - outputPositionToHashSlot.set(destState[tableLocation], tableLocation); + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + if (sourceBucket != destinationTableLocation) { + outputPositionToHashSlot.set(currentStateValue, destinationTableLocation); } break; - } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); } } } @@ -119,7 +121,7 @@ public int findPositionForKey(Object key) { final double k1 = TypeUtils.unbox((Double)ka[1]); int hash = hash(k0, k1); int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = tableLocation; while (true) { final int positionValue = mainOutputPosition.getUnsafe(tableLocation); if (positionValue == EMPTY_OUTPUT_POSITION) { @@ -128,8 +130,8 @@ public int findPositionForKey(Object key) { if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { return positionValue; } - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherDoubleFloat.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherDoubleFloat.java index 95a96418049..86374e38a6a 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherDoubleFloat.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherDoubleFloat.java @@ -39,7 +39,10 @@ public StaticAggOpenHasherDoubleFloat(ColumnSource[] tableKeySources, int tableS this.mainKeySource1.ensureCapacity(tableSize); } - @Override + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final DoubleChunk keyChunk0 = sourceKeyChunks[0].asDoubleChunk(); final FloatChunk keyChunk1 = sourceKeyChunks[1].asFloatChunk(); @@ -48,25 +51,25 @@ protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final double k0 = keyChunk0.get(chunkPosition); final float k1 = keyChunk1.get(chunkPosition); final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; while (true) { - int tableState = mainOutputPosition.getUnsafe(tableLocation); - if (tableState == EMPTY_OUTPUT_POSITION) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { numEntries++; mainKeySource0.set(tableLocation, k0); mainKeySource1.set(tableLocation, k1); - final int outputPosition = nextOutputPosition.getAndIncrement(); + outputPosition = nextOutputPosition.getAndIncrement(); outputPositions.set(chunkPosition, outputPosition); mainOutputPosition.set(tableLocation, outputPosition); outputPositionToHashSlot.set(outputPosition, tableLocation); break; } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { - outputPositions.set(chunkPosition, tableState); + outputPositions.set(chunkPosition, outputPosition); break; } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } @@ -79,8 +82,7 @@ private static int hash(double k0, float k1) { } @Override - protected void rehashInternal() { - final int oldSize = tableSize >> 1; + protected void rehashInternalFull(final int oldSize) { final double[] destKeyArray0 = new double[tableSize]; final float[] destKeyArray1 = new float[tableSize]; final int[] destState = new int[tableSize]; @@ -92,27 +94,27 @@ protected void rehashInternal() { final int [] originalStateArray = mainOutputPosition.getArray(); mainOutputPosition.setArray(destState); for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { - if (originalStateArray[sourceBucket] == EMPTY_OUTPUT_POSITION) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { continue; } final double k0 = originalKeyArray0[sourceBucket]; final float k1 = originalKeyArray1[sourceBucket]; final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; while (true) { - if (destState[tableLocation] == EMPTY_OUTPUT_POSITION) { - destKeyArray0[tableLocation] = k0; - destKeyArray1[tableLocation] = k1; - destState[tableLocation] = originalStateArray[sourceBucket]; - if (sourceBucket != tableLocation) { - outputPositionToHashSlot.set(destState[tableLocation], tableLocation); + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + if (sourceBucket != destinationTableLocation) { + outputPositionToHashSlot.set(currentStateValue, destinationTableLocation); } break; - } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); } } } @@ -124,7 +126,7 @@ public int findPositionForKey(Object key) { final float k1 = TypeUtils.unbox((Float)ka[1]); int hash = hash(k0, k1); int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = tableLocation; while (true) { final int positionValue = mainOutputPosition.getUnsafe(tableLocation); if (positionValue == EMPTY_OUTPUT_POSITION) { @@ -133,8 +135,8 @@ public int findPositionForKey(Object key) { if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { return positionValue; } - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherDoubleInt.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherDoubleInt.java index 5ae489b8491..19e24f19b5d 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherDoubleInt.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherDoubleInt.java @@ -39,7 +39,10 @@ public StaticAggOpenHasherDoubleInt(ColumnSource[] tableKeySources, int tableSiz this.mainKeySource1.ensureCapacity(tableSize); } - @Override + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final DoubleChunk keyChunk0 = sourceKeyChunks[0].asDoubleChunk(); final IntChunk keyChunk1 = sourceKeyChunks[1].asIntChunk(); @@ -48,25 +51,25 @@ protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final double k0 = keyChunk0.get(chunkPosition); final int k1 = keyChunk1.get(chunkPosition); final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; while (true) { - int tableState = mainOutputPosition.getUnsafe(tableLocation); - if (tableState == EMPTY_OUTPUT_POSITION) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { numEntries++; mainKeySource0.set(tableLocation, k0); mainKeySource1.set(tableLocation, k1); - final int outputPosition = nextOutputPosition.getAndIncrement(); + outputPosition = nextOutputPosition.getAndIncrement(); outputPositions.set(chunkPosition, outputPosition); mainOutputPosition.set(tableLocation, outputPosition); outputPositionToHashSlot.set(outputPosition, tableLocation); break; } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { - outputPositions.set(chunkPosition, tableState); + outputPositions.set(chunkPosition, outputPosition); break; } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } @@ -79,8 +82,7 @@ private static int hash(double k0, int k1) { } @Override - protected void rehashInternal() { - final int oldSize = tableSize >> 1; + protected void rehashInternalFull(final int oldSize) { final double[] destKeyArray0 = new double[tableSize]; final int[] destKeyArray1 = new int[tableSize]; final int[] destState = new int[tableSize]; @@ -92,27 +94,27 @@ protected void rehashInternal() { final int [] originalStateArray = mainOutputPosition.getArray(); mainOutputPosition.setArray(destState); for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { - if (originalStateArray[sourceBucket] == EMPTY_OUTPUT_POSITION) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { continue; } final double k0 = originalKeyArray0[sourceBucket]; final int k1 = originalKeyArray1[sourceBucket]; final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; while (true) { - if (destState[tableLocation] == EMPTY_OUTPUT_POSITION) { - destKeyArray0[tableLocation] = k0; - destKeyArray1[tableLocation] = k1; - destState[tableLocation] = originalStateArray[sourceBucket]; - if (sourceBucket != tableLocation) { - outputPositionToHashSlot.set(destState[tableLocation], tableLocation); + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + if (sourceBucket != destinationTableLocation) { + outputPositionToHashSlot.set(currentStateValue, destinationTableLocation); } break; - } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); } } } @@ -124,7 +126,7 @@ public int findPositionForKey(Object key) { final int k1 = TypeUtils.unbox((Integer)ka[1]); int hash = hash(k0, k1); int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = tableLocation; while (true) { final int positionValue = mainOutputPosition.getUnsafe(tableLocation); if (positionValue == EMPTY_OUTPUT_POSITION) { @@ -133,8 +135,8 @@ public int findPositionForKey(Object key) { if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { return positionValue; } - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherDoubleLong.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherDoubleLong.java index b39bf70630a..9732d96e1fb 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherDoubleLong.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherDoubleLong.java @@ -39,7 +39,10 @@ public StaticAggOpenHasherDoubleLong(ColumnSource[] tableKeySources, int tableSi this.mainKeySource1.ensureCapacity(tableSize); } - @Override + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final DoubleChunk keyChunk0 = sourceKeyChunks[0].asDoubleChunk(); final LongChunk keyChunk1 = sourceKeyChunks[1].asLongChunk(); @@ -48,25 +51,25 @@ protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final double k0 = keyChunk0.get(chunkPosition); final long k1 = keyChunk1.get(chunkPosition); final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; while (true) { - int tableState = mainOutputPosition.getUnsafe(tableLocation); - if (tableState == EMPTY_OUTPUT_POSITION) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { numEntries++; mainKeySource0.set(tableLocation, k0); mainKeySource1.set(tableLocation, k1); - final int outputPosition = nextOutputPosition.getAndIncrement(); + outputPosition = nextOutputPosition.getAndIncrement(); outputPositions.set(chunkPosition, outputPosition); mainOutputPosition.set(tableLocation, outputPosition); outputPositionToHashSlot.set(outputPosition, tableLocation); break; } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { - outputPositions.set(chunkPosition, tableState); + outputPositions.set(chunkPosition, outputPosition); break; } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } @@ -79,8 +82,7 @@ private static int hash(double k0, long k1) { } @Override - protected void rehashInternal() { - final int oldSize = tableSize >> 1; + protected void rehashInternalFull(final int oldSize) { final double[] destKeyArray0 = new double[tableSize]; final long[] destKeyArray1 = new long[tableSize]; final int[] destState = new int[tableSize]; @@ -92,27 +94,27 @@ protected void rehashInternal() { final int [] originalStateArray = mainOutputPosition.getArray(); mainOutputPosition.setArray(destState); for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { - if (originalStateArray[sourceBucket] == EMPTY_OUTPUT_POSITION) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { continue; } final double k0 = originalKeyArray0[sourceBucket]; final long k1 = originalKeyArray1[sourceBucket]; final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; while (true) { - if (destState[tableLocation] == EMPTY_OUTPUT_POSITION) { - destKeyArray0[tableLocation] = k0; - destKeyArray1[tableLocation] = k1; - destState[tableLocation] = originalStateArray[sourceBucket]; - if (sourceBucket != tableLocation) { - outputPositionToHashSlot.set(destState[tableLocation], tableLocation); + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + if (sourceBucket != destinationTableLocation) { + outputPositionToHashSlot.set(currentStateValue, destinationTableLocation); } break; - } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); } } } @@ -124,7 +126,7 @@ public int findPositionForKey(Object key) { final long k1 = TypeUtils.unbox((Long)ka[1]); int hash = hash(k0, k1); int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = tableLocation; while (true) { final int positionValue = mainOutputPosition.getUnsafe(tableLocation); if (positionValue == EMPTY_OUTPUT_POSITION) { @@ -133,8 +135,8 @@ public int findPositionForKey(Object key) { if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { return positionValue; } - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherDoubleObject.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherDoubleObject.java index c5a2d8d00c7..2f23f231a3f 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherDoubleObject.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherDoubleObject.java @@ -38,7 +38,10 @@ public StaticAggOpenHasherDoubleObject(ColumnSource[] tableKeySources, int table this.mainKeySource1.ensureCapacity(tableSize); } - @Override + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final DoubleChunk keyChunk0 = sourceKeyChunks[0].asDoubleChunk(); final ObjectChunk keyChunk1 = sourceKeyChunks[1].asObjectChunk(); @@ -47,25 +50,25 @@ protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final double k0 = keyChunk0.get(chunkPosition); final Object k1 = keyChunk1.get(chunkPosition); final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; while (true) { - int tableState = mainOutputPosition.getUnsafe(tableLocation); - if (tableState == EMPTY_OUTPUT_POSITION) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { numEntries++; mainKeySource0.set(tableLocation, k0); mainKeySource1.set(tableLocation, k1); - final int outputPosition = nextOutputPosition.getAndIncrement(); + outputPosition = nextOutputPosition.getAndIncrement(); outputPositions.set(chunkPosition, outputPosition); mainOutputPosition.set(tableLocation, outputPosition); outputPositionToHashSlot.set(outputPosition, tableLocation); break; } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { - outputPositions.set(chunkPosition, tableState); + outputPositions.set(chunkPosition, outputPosition); break; } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } @@ -78,8 +81,7 @@ private static int hash(double k0, Object k1) { } @Override - protected void rehashInternal() { - final int oldSize = tableSize >> 1; + protected void rehashInternalFull(final int oldSize) { final double[] destKeyArray0 = new double[tableSize]; final Object[] destKeyArray1 = new Object[tableSize]; final int[] destState = new int[tableSize]; @@ -91,27 +93,27 @@ protected void rehashInternal() { final int [] originalStateArray = mainOutputPosition.getArray(); mainOutputPosition.setArray(destState); for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { - if (originalStateArray[sourceBucket] == EMPTY_OUTPUT_POSITION) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { continue; } final double k0 = originalKeyArray0[sourceBucket]; final Object k1 = originalKeyArray1[sourceBucket]; final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; while (true) { - if (destState[tableLocation] == EMPTY_OUTPUT_POSITION) { - destKeyArray0[tableLocation] = k0; - destKeyArray1[tableLocation] = k1; - destState[tableLocation] = originalStateArray[sourceBucket]; - if (sourceBucket != tableLocation) { - outputPositionToHashSlot.set(destState[tableLocation], tableLocation); + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + if (sourceBucket != destinationTableLocation) { + outputPositionToHashSlot.set(currentStateValue, destinationTableLocation); } break; - } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); } } } @@ -123,7 +125,7 @@ public int findPositionForKey(Object key) { final Object k1 = ka[1]; int hash = hash(k0, k1); int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = tableLocation; while (true) { final int positionValue = mainOutputPosition.getUnsafe(tableLocation); if (positionValue == EMPTY_OUTPUT_POSITION) { @@ -132,8 +134,8 @@ public int findPositionForKey(Object key) { if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { return positionValue; } - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherDoubleShort.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherDoubleShort.java index aec04845239..2857ceb5ab9 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherDoubleShort.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherDoubleShort.java @@ -39,7 +39,10 @@ public StaticAggOpenHasherDoubleShort(ColumnSource[] tableKeySources, int tableS this.mainKeySource1.ensureCapacity(tableSize); } - @Override + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final DoubleChunk keyChunk0 = sourceKeyChunks[0].asDoubleChunk(); final ShortChunk keyChunk1 = sourceKeyChunks[1].asShortChunk(); @@ -48,25 +51,25 @@ protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final double k0 = keyChunk0.get(chunkPosition); final short k1 = keyChunk1.get(chunkPosition); final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; while (true) { - int tableState = mainOutputPosition.getUnsafe(tableLocation); - if (tableState == EMPTY_OUTPUT_POSITION) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { numEntries++; mainKeySource0.set(tableLocation, k0); mainKeySource1.set(tableLocation, k1); - final int outputPosition = nextOutputPosition.getAndIncrement(); + outputPosition = nextOutputPosition.getAndIncrement(); outputPositions.set(chunkPosition, outputPosition); mainOutputPosition.set(tableLocation, outputPosition); outputPositionToHashSlot.set(outputPosition, tableLocation); break; } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { - outputPositions.set(chunkPosition, tableState); + outputPositions.set(chunkPosition, outputPosition); break; } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } @@ -79,8 +82,7 @@ private static int hash(double k0, short k1) { } @Override - protected void rehashInternal() { - final int oldSize = tableSize >> 1; + protected void rehashInternalFull(final int oldSize) { final double[] destKeyArray0 = new double[tableSize]; final short[] destKeyArray1 = new short[tableSize]; final int[] destState = new int[tableSize]; @@ -92,27 +94,27 @@ protected void rehashInternal() { final int [] originalStateArray = mainOutputPosition.getArray(); mainOutputPosition.setArray(destState); for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { - if (originalStateArray[sourceBucket] == EMPTY_OUTPUT_POSITION) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { continue; } final double k0 = originalKeyArray0[sourceBucket]; final short k1 = originalKeyArray1[sourceBucket]; final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; while (true) { - if (destState[tableLocation] == EMPTY_OUTPUT_POSITION) { - destKeyArray0[tableLocation] = k0; - destKeyArray1[tableLocation] = k1; - destState[tableLocation] = originalStateArray[sourceBucket]; - if (sourceBucket != tableLocation) { - outputPositionToHashSlot.set(destState[tableLocation], tableLocation); + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + if (sourceBucket != destinationTableLocation) { + outputPositionToHashSlot.set(currentStateValue, destinationTableLocation); } break; - } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); } } } @@ -124,7 +126,7 @@ public int findPositionForKey(Object key) { final short k1 = TypeUtils.unbox((Short)ka[1]); int hash = hash(k0, k1); int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = tableLocation; while (true) { final int positionValue = mainOutputPosition.getUnsafe(tableLocation); if (positionValue == EMPTY_OUTPUT_POSITION) { @@ -133,8 +135,8 @@ public int findPositionForKey(Object key) { if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { return positionValue; } - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherFloat.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherFloat.java index d333b5ca8f8..4b3ca65f6ba 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherFloat.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherFloat.java @@ -30,31 +30,34 @@ public StaticAggOpenHasherFloat(ColumnSource[] tableKeySources, int tableSize, this.mainKeySource0.ensureCapacity(tableSize); } - @Override + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final FloatChunk keyChunk0 = sourceKeyChunks[0].asFloatChunk(); final int chunkSize = keyChunk0.size(); for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { final float k0 = keyChunk0.get(chunkPosition); final int hash = hash(k0); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; while (true) { - int tableState = mainOutputPosition.getUnsafe(tableLocation); - if (tableState == EMPTY_OUTPUT_POSITION) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { numEntries++; mainKeySource0.set(tableLocation, k0); - final int outputPosition = nextOutputPosition.getAndIncrement(); + outputPosition = nextOutputPosition.getAndIncrement(); outputPositions.set(chunkPosition, outputPosition); mainOutputPosition.set(tableLocation, outputPosition); outputPositionToHashSlot.set(outputPosition, tableLocation); break; } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0)) { - outputPositions.set(chunkPosition, tableState); + outputPositions.set(chunkPosition, outputPosition); break; } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } @@ -66,8 +69,7 @@ private static int hash(float k0) { } @Override - protected void rehashInternal() { - final int oldSize = tableSize >> 1; + protected void rehashInternalFull(final int oldSize) { final float[] destKeyArray0 = new float[tableSize]; final int[] destState = new int[tableSize]; Arrays.fill(destState, EMPTY_OUTPUT_POSITION); @@ -76,25 +78,25 @@ protected void rehashInternal() { final int [] originalStateArray = mainOutputPosition.getArray(); mainOutputPosition.setArray(destState); for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { - if (originalStateArray[sourceBucket] == EMPTY_OUTPUT_POSITION) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { continue; } final float k0 = originalKeyArray0[sourceBucket]; final int hash = hash(k0); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; while (true) { - if (destState[tableLocation] == EMPTY_OUTPUT_POSITION) { - destKeyArray0[tableLocation] = k0; - destState[tableLocation] = originalStateArray[sourceBucket]; - if (sourceBucket != tableLocation) { - outputPositionToHashSlot.set(destState[tableLocation], tableLocation); + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + if (sourceBucket != destinationTableLocation) { + outputPositionToHashSlot.set(currentStateValue, destinationTableLocation); } break; - } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); } } } @@ -104,7 +106,7 @@ public int findPositionForKey(Object key) { final float k0 = TypeUtils.unbox((Float)key); int hash = hash(k0); int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = tableLocation; while (true) { final int positionValue = mainOutputPosition.getUnsafe(tableLocation); if (positionValue == EMPTY_OUTPUT_POSITION) { @@ -113,8 +115,8 @@ public int findPositionForKey(Object key) { if (eq(mainKeySource0.getUnsafe(tableLocation), k0)) { return positionValue; } - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherFloatByte.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherFloatByte.java index d81a321c303..32e85e1c867 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherFloatByte.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherFloatByte.java @@ -39,7 +39,10 @@ public StaticAggOpenHasherFloatByte(ColumnSource[] tableKeySources, int tableSiz this.mainKeySource1.ensureCapacity(tableSize); } - @Override + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final FloatChunk keyChunk0 = sourceKeyChunks[0].asFloatChunk(); final ByteChunk keyChunk1 = sourceKeyChunks[1].asByteChunk(); @@ -48,25 +51,25 @@ protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final float k0 = keyChunk0.get(chunkPosition); final byte k1 = keyChunk1.get(chunkPosition); final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; while (true) { - int tableState = mainOutputPosition.getUnsafe(tableLocation); - if (tableState == EMPTY_OUTPUT_POSITION) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { numEntries++; mainKeySource0.set(tableLocation, k0); mainKeySource1.set(tableLocation, k1); - final int outputPosition = nextOutputPosition.getAndIncrement(); + outputPosition = nextOutputPosition.getAndIncrement(); outputPositions.set(chunkPosition, outputPosition); mainOutputPosition.set(tableLocation, outputPosition); outputPositionToHashSlot.set(outputPosition, tableLocation); break; } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { - outputPositions.set(chunkPosition, tableState); + outputPositions.set(chunkPosition, outputPosition); break; } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } @@ -79,8 +82,7 @@ private static int hash(float k0, byte k1) { } @Override - protected void rehashInternal() { - final int oldSize = tableSize >> 1; + protected void rehashInternalFull(final int oldSize) { final float[] destKeyArray0 = new float[tableSize]; final byte[] destKeyArray1 = new byte[tableSize]; final int[] destState = new int[tableSize]; @@ -92,27 +94,27 @@ protected void rehashInternal() { final int [] originalStateArray = mainOutputPosition.getArray(); mainOutputPosition.setArray(destState); for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { - if (originalStateArray[sourceBucket] == EMPTY_OUTPUT_POSITION) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { continue; } final float k0 = originalKeyArray0[sourceBucket]; final byte k1 = originalKeyArray1[sourceBucket]; final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; while (true) { - if (destState[tableLocation] == EMPTY_OUTPUT_POSITION) { - destKeyArray0[tableLocation] = k0; - destKeyArray1[tableLocation] = k1; - destState[tableLocation] = originalStateArray[sourceBucket]; - if (sourceBucket != tableLocation) { - outputPositionToHashSlot.set(destState[tableLocation], tableLocation); + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + if (sourceBucket != destinationTableLocation) { + outputPositionToHashSlot.set(currentStateValue, destinationTableLocation); } break; - } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); } } } @@ -124,7 +126,7 @@ public int findPositionForKey(Object key) { final byte k1 = TypeUtils.unbox((Byte)ka[1]); int hash = hash(k0, k1); int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = tableLocation; while (true) { final int positionValue = mainOutputPosition.getUnsafe(tableLocation); if (positionValue == EMPTY_OUTPUT_POSITION) { @@ -133,8 +135,8 @@ public int findPositionForKey(Object key) { if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { return positionValue; } - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherFloatChar.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherFloatChar.java index 9532e0f4ce0..3047546eb98 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherFloatChar.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherFloatChar.java @@ -39,7 +39,10 @@ public StaticAggOpenHasherFloatChar(ColumnSource[] tableKeySources, int tableSiz this.mainKeySource1.ensureCapacity(tableSize); } - @Override + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final FloatChunk keyChunk0 = sourceKeyChunks[0].asFloatChunk(); final CharChunk keyChunk1 = sourceKeyChunks[1].asCharChunk(); @@ -48,25 +51,25 @@ protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final float k0 = keyChunk0.get(chunkPosition); final char k1 = keyChunk1.get(chunkPosition); final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; while (true) { - int tableState = mainOutputPosition.getUnsafe(tableLocation); - if (tableState == EMPTY_OUTPUT_POSITION) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { numEntries++; mainKeySource0.set(tableLocation, k0); mainKeySource1.set(tableLocation, k1); - final int outputPosition = nextOutputPosition.getAndIncrement(); + outputPosition = nextOutputPosition.getAndIncrement(); outputPositions.set(chunkPosition, outputPosition); mainOutputPosition.set(tableLocation, outputPosition); outputPositionToHashSlot.set(outputPosition, tableLocation); break; } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { - outputPositions.set(chunkPosition, tableState); + outputPositions.set(chunkPosition, outputPosition); break; } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } @@ -79,8 +82,7 @@ private static int hash(float k0, char k1) { } @Override - protected void rehashInternal() { - final int oldSize = tableSize >> 1; + protected void rehashInternalFull(final int oldSize) { final float[] destKeyArray0 = new float[tableSize]; final char[] destKeyArray1 = new char[tableSize]; final int[] destState = new int[tableSize]; @@ -92,27 +94,27 @@ protected void rehashInternal() { final int [] originalStateArray = mainOutputPosition.getArray(); mainOutputPosition.setArray(destState); for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { - if (originalStateArray[sourceBucket] == EMPTY_OUTPUT_POSITION) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { continue; } final float k0 = originalKeyArray0[sourceBucket]; final char k1 = originalKeyArray1[sourceBucket]; final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; while (true) { - if (destState[tableLocation] == EMPTY_OUTPUT_POSITION) { - destKeyArray0[tableLocation] = k0; - destKeyArray1[tableLocation] = k1; - destState[tableLocation] = originalStateArray[sourceBucket]; - if (sourceBucket != tableLocation) { - outputPositionToHashSlot.set(destState[tableLocation], tableLocation); + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + if (sourceBucket != destinationTableLocation) { + outputPositionToHashSlot.set(currentStateValue, destinationTableLocation); } break; - } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); } } } @@ -124,7 +126,7 @@ public int findPositionForKey(Object key) { final char k1 = TypeUtils.unbox((Character)ka[1]); int hash = hash(k0, k1); int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = tableLocation; while (true) { final int positionValue = mainOutputPosition.getUnsafe(tableLocation); if (positionValue == EMPTY_OUTPUT_POSITION) { @@ -133,8 +135,8 @@ public int findPositionForKey(Object key) { if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { return positionValue; } - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherFloatDouble.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherFloatDouble.java index e8ce8e7475d..73b0e7d28dd 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherFloatDouble.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherFloatDouble.java @@ -39,7 +39,10 @@ public StaticAggOpenHasherFloatDouble(ColumnSource[] tableKeySources, int tableS this.mainKeySource1.ensureCapacity(tableSize); } - @Override + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final FloatChunk keyChunk0 = sourceKeyChunks[0].asFloatChunk(); final DoubleChunk keyChunk1 = sourceKeyChunks[1].asDoubleChunk(); @@ -48,25 +51,25 @@ protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final float k0 = keyChunk0.get(chunkPosition); final double k1 = keyChunk1.get(chunkPosition); final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; while (true) { - int tableState = mainOutputPosition.getUnsafe(tableLocation); - if (tableState == EMPTY_OUTPUT_POSITION) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { numEntries++; mainKeySource0.set(tableLocation, k0); mainKeySource1.set(tableLocation, k1); - final int outputPosition = nextOutputPosition.getAndIncrement(); + outputPosition = nextOutputPosition.getAndIncrement(); outputPositions.set(chunkPosition, outputPosition); mainOutputPosition.set(tableLocation, outputPosition); outputPositionToHashSlot.set(outputPosition, tableLocation); break; } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { - outputPositions.set(chunkPosition, tableState); + outputPositions.set(chunkPosition, outputPosition); break; } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } @@ -79,8 +82,7 @@ private static int hash(float k0, double k1) { } @Override - protected void rehashInternal() { - final int oldSize = tableSize >> 1; + protected void rehashInternalFull(final int oldSize) { final float[] destKeyArray0 = new float[tableSize]; final double[] destKeyArray1 = new double[tableSize]; final int[] destState = new int[tableSize]; @@ -92,27 +94,27 @@ protected void rehashInternal() { final int [] originalStateArray = mainOutputPosition.getArray(); mainOutputPosition.setArray(destState); for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { - if (originalStateArray[sourceBucket] == EMPTY_OUTPUT_POSITION) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { continue; } final float k0 = originalKeyArray0[sourceBucket]; final double k1 = originalKeyArray1[sourceBucket]; final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; while (true) { - if (destState[tableLocation] == EMPTY_OUTPUT_POSITION) { - destKeyArray0[tableLocation] = k0; - destKeyArray1[tableLocation] = k1; - destState[tableLocation] = originalStateArray[sourceBucket]; - if (sourceBucket != tableLocation) { - outputPositionToHashSlot.set(destState[tableLocation], tableLocation); + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + if (sourceBucket != destinationTableLocation) { + outputPositionToHashSlot.set(currentStateValue, destinationTableLocation); } break; - } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); } } } @@ -124,7 +126,7 @@ public int findPositionForKey(Object key) { final double k1 = TypeUtils.unbox((Double)ka[1]); int hash = hash(k0, k1); int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = tableLocation; while (true) { final int positionValue = mainOutputPosition.getUnsafe(tableLocation); if (positionValue == EMPTY_OUTPUT_POSITION) { @@ -133,8 +135,8 @@ public int findPositionForKey(Object key) { if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { return positionValue; } - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherFloatFloat.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherFloatFloat.java index 54364949147..f10a16773a5 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherFloatFloat.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherFloatFloat.java @@ -34,7 +34,10 @@ public StaticAggOpenHasherFloatFloat(ColumnSource[] tableKeySources, int tableSi this.mainKeySource1.ensureCapacity(tableSize); } - @Override + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final FloatChunk keyChunk0 = sourceKeyChunks[0].asFloatChunk(); final FloatChunk keyChunk1 = sourceKeyChunks[1].asFloatChunk(); @@ -43,25 +46,25 @@ protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final float k0 = keyChunk0.get(chunkPosition); final float k1 = keyChunk1.get(chunkPosition); final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; while (true) { - int tableState = mainOutputPosition.getUnsafe(tableLocation); - if (tableState == EMPTY_OUTPUT_POSITION) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { numEntries++; mainKeySource0.set(tableLocation, k0); mainKeySource1.set(tableLocation, k1); - final int outputPosition = nextOutputPosition.getAndIncrement(); + outputPosition = nextOutputPosition.getAndIncrement(); outputPositions.set(chunkPosition, outputPosition); mainOutputPosition.set(tableLocation, outputPosition); outputPositionToHashSlot.set(outputPosition, tableLocation); break; } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { - outputPositions.set(chunkPosition, tableState); + outputPositions.set(chunkPosition, outputPosition); break; } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } @@ -74,8 +77,7 @@ private static int hash(float k0, float k1) { } @Override - protected void rehashInternal() { - final int oldSize = tableSize >> 1; + protected void rehashInternalFull(final int oldSize) { final float[] destKeyArray0 = new float[tableSize]; final float[] destKeyArray1 = new float[tableSize]; final int[] destState = new int[tableSize]; @@ -87,27 +89,27 @@ protected void rehashInternal() { final int [] originalStateArray = mainOutputPosition.getArray(); mainOutputPosition.setArray(destState); for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { - if (originalStateArray[sourceBucket] == EMPTY_OUTPUT_POSITION) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { continue; } final float k0 = originalKeyArray0[sourceBucket]; final float k1 = originalKeyArray1[sourceBucket]; final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; while (true) { - if (destState[tableLocation] == EMPTY_OUTPUT_POSITION) { - destKeyArray0[tableLocation] = k0; - destKeyArray1[tableLocation] = k1; - destState[tableLocation] = originalStateArray[sourceBucket]; - if (sourceBucket != tableLocation) { - outputPositionToHashSlot.set(destState[tableLocation], tableLocation); + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + if (sourceBucket != destinationTableLocation) { + outputPositionToHashSlot.set(currentStateValue, destinationTableLocation); } break; - } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); } } } @@ -119,7 +121,7 @@ public int findPositionForKey(Object key) { final float k1 = TypeUtils.unbox((Float)ka[1]); int hash = hash(k0, k1); int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = tableLocation; while (true) { final int positionValue = mainOutputPosition.getUnsafe(tableLocation); if (positionValue == EMPTY_OUTPUT_POSITION) { @@ -128,8 +130,8 @@ public int findPositionForKey(Object key) { if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { return positionValue; } - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherFloatInt.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherFloatInt.java index d45b3b5738c..ba16fe11266 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherFloatInt.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherFloatInt.java @@ -39,7 +39,10 @@ public StaticAggOpenHasherFloatInt(ColumnSource[] tableKeySources, int tableSize this.mainKeySource1.ensureCapacity(tableSize); } - @Override + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final FloatChunk keyChunk0 = sourceKeyChunks[0].asFloatChunk(); final IntChunk keyChunk1 = sourceKeyChunks[1].asIntChunk(); @@ -48,25 +51,25 @@ protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final float k0 = keyChunk0.get(chunkPosition); final int k1 = keyChunk1.get(chunkPosition); final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; while (true) { - int tableState = mainOutputPosition.getUnsafe(tableLocation); - if (tableState == EMPTY_OUTPUT_POSITION) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { numEntries++; mainKeySource0.set(tableLocation, k0); mainKeySource1.set(tableLocation, k1); - final int outputPosition = nextOutputPosition.getAndIncrement(); + outputPosition = nextOutputPosition.getAndIncrement(); outputPositions.set(chunkPosition, outputPosition); mainOutputPosition.set(tableLocation, outputPosition); outputPositionToHashSlot.set(outputPosition, tableLocation); break; } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { - outputPositions.set(chunkPosition, tableState); + outputPositions.set(chunkPosition, outputPosition); break; } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } @@ -79,8 +82,7 @@ private static int hash(float k0, int k1) { } @Override - protected void rehashInternal() { - final int oldSize = tableSize >> 1; + protected void rehashInternalFull(final int oldSize) { final float[] destKeyArray0 = new float[tableSize]; final int[] destKeyArray1 = new int[tableSize]; final int[] destState = new int[tableSize]; @@ -92,27 +94,27 @@ protected void rehashInternal() { final int [] originalStateArray = mainOutputPosition.getArray(); mainOutputPosition.setArray(destState); for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { - if (originalStateArray[sourceBucket] == EMPTY_OUTPUT_POSITION) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { continue; } final float k0 = originalKeyArray0[sourceBucket]; final int k1 = originalKeyArray1[sourceBucket]; final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; while (true) { - if (destState[tableLocation] == EMPTY_OUTPUT_POSITION) { - destKeyArray0[tableLocation] = k0; - destKeyArray1[tableLocation] = k1; - destState[tableLocation] = originalStateArray[sourceBucket]; - if (sourceBucket != tableLocation) { - outputPositionToHashSlot.set(destState[tableLocation], tableLocation); + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + if (sourceBucket != destinationTableLocation) { + outputPositionToHashSlot.set(currentStateValue, destinationTableLocation); } break; - } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); } } } @@ -124,7 +126,7 @@ public int findPositionForKey(Object key) { final int k1 = TypeUtils.unbox((Integer)ka[1]); int hash = hash(k0, k1); int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = tableLocation; while (true) { final int positionValue = mainOutputPosition.getUnsafe(tableLocation); if (positionValue == EMPTY_OUTPUT_POSITION) { @@ -133,8 +135,8 @@ public int findPositionForKey(Object key) { if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { return positionValue; } - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherFloatLong.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherFloatLong.java index e80b30ebd91..67b0a5334de 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherFloatLong.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherFloatLong.java @@ -39,7 +39,10 @@ public StaticAggOpenHasherFloatLong(ColumnSource[] tableKeySources, int tableSiz this.mainKeySource1.ensureCapacity(tableSize); } - @Override + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final FloatChunk keyChunk0 = sourceKeyChunks[0].asFloatChunk(); final LongChunk keyChunk1 = sourceKeyChunks[1].asLongChunk(); @@ -48,25 +51,25 @@ protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final float k0 = keyChunk0.get(chunkPosition); final long k1 = keyChunk1.get(chunkPosition); final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; while (true) { - int tableState = mainOutputPosition.getUnsafe(tableLocation); - if (tableState == EMPTY_OUTPUT_POSITION) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { numEntries++; mainKeySource0.set(tableLocation, k0); mainKeySource1.set(tableLocation, k1); - final int outputPosition = nextOutputPosition.getAndIncrement(); + outputPosition = nextOutputPosition.getAndIncrement(); outputPositions.set(chunkPosition, outputPosition); mainOutputPosition.set(tableLocation, outputPosition); outputPositionToHashSlot.set(outputPosition, tableLocation); break; } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { - outputPositions.set(chunkPosition, tableState); + outputPositions.set(chunkPosition, outputPosition); break; } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } @@ -79,8 +82,7 @@ private static int hash(float k0, long k1) { } @Override - protected void rehashInternal() { - final int oldSize = tableSize >> 1; + protected void rehashInternalFull(final int oldSize) { final float[] destKeyArray0 = new float[tableSize]; final long[] destKeyArray1 = new long[tableSize]; final int[] destState = new int[tableSize]; @@ -92,27 +94,27 @@ protected void rehashInternal() { final int [] originalStateArray = mainOutputPosition.getArray(); mainOutputPosition.setArray(destState); for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { - if (originalStateArray[sourceBucket] == EMPTY_OUTPUT_POSITION) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { continue; } final float k0 = originalKeyArray0[sourceBucket]; final long k1 = originalKeyArray1[sourceBucket]; final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; while (true) { - if (destState[tableLocation] == EMPTY_OUTPUT_POSITION) { - destKeyArray0[tableLocation] = k0; - destKeyArray1[tableLocation] = k1; - destState[tableLocation] = originalStateArray[sourceBucket]; - if (sourceBucket != tableLocation) { - outputPositionToHashSlot.set(destState[tableLocation], tableLocation); + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + if (sourceBucket != destinationTableLocation) { + outputPositionToHashSlot.set(currentStateValue, destinationTableLocation); } break; - } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); } } } @@ -124,7 +126,7 @@ public int findPositionForKey(Object key) { final long k1 = TypeUtils.unbox((Long)ka[1]); int hash = hash(k0, k1); int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = tableLocation; while (true) { final int positionValue = mainOutputPosition.getUnsafe(tableLocation); if (positionValue == EMPTY_OUTPUT_POSITION) { @@ -133,8 +135,8 @@ public int findPositionForKey(Object key) { if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { return positionValue; } - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherFloatObject.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherFloatObject.java index 4cf16261240..139d849a06e 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherFloatObject.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherFloatObject.java @@ -38,7 +38,10 @@ public StaticAggOpenHasherFloatObject(ColumnSource[] tableKeySources, int tableS this.mainKeySource1.ensureCapacity(tableSize); } - @Override + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final FloatChunk keyChunk0 = sourceKeyChunks[0].asFloatChunk(); final ObjectChunk keyChunk1 = sourceKeyChunks[1].asObjectChunk(); @@ -47,25 +50,25 @@ protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final float k0 = keyChunk0.get(chunkPosition); final Object k1 = keyChunk1.get(chunkPosition); final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; while (true) { - int tableState = mainOutputPosition.getUnsafe(tableLocation); - if (tableState == EMPTY_OUTPUT_POSITION) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { numEntries++; mainKeySource0.set(tableLocation, k0); mainKeySource1.set(tableLocation, k1); - final int outputPosition = nextOutputPosition.getAndIncrement(); + outputPosition = nextOutputPosition.getAndIncrement(); outputPositions.set(chunkPosition, outputPosition); mainOutputPosition.set(tableLocation, outputPosition); outputPositionToHashSlot.set(outputPosition, tableLocation); break; } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { - outputPositions.set(chunkPosition, tableState); + outputPositions.set(chunkPosition, outputPosition); break; } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } @@ -78,8 +81,7 @@ private static int hash(float k0, Object k1) { } @Override - protected void rehashInternal() { - final int oldSize = tableSize >> 1; + protected void rehashInternalFull(final int oldSize) { final float[] destKeyArray0 = new float[tableSize]; final Object[] destKeyArray1 = new Object[tableSize]; final int[] destState = new int[tableSize]; @@ -91,27 +93,27 @@ protected void rehashInternal() { final int [] originalStateArray = mainOutputPosition.getArray(); mainOutputPosition.setArray(destState); for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { - if (originalStateArray[sourceBucket] == EMPTY_OUTPUT_POSITION) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { continue; } final float k0 = originalKeyArray0[sourceBucket]; final Object k1 = originalKeyArray1[sourceBucket]; final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; while (true) { - if (destState[tableLocation] == EMPTY_OUTPUT_POSITION) { - destKeyArray0[tableLocation] = k0; - destKeyArray1[tableLocation] = k1; - destState[tableLocation] = originalStateArray[sourceBucket]; - if (sourceBucket != tableLocation) { - outputPositionToHashSlot.set(destState[tableLocation], tableLocation); + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + if (sourceBucket != destinationTableLocation) { + outputPositionToHashSlot.set(currentStateValue, destinationTableLocation); } break; - } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); } } } @@ -123,7 +125,7 @@ public int findPositionForKey(Object key) { final Object k1 = ka[1]; int hash = hash(k0, k1); int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = tableLocation; while (true) { final int positionValue = mainOutputPosition.getUnsafe(tableLocation); if (positionValue == EMPTY_OUTPUT_POSITION) { @@ -132,8 +134,8 @@ public int findPositionForKey(Object key) { if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { return positionValue; } - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherFloatShort.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherFloatShort.java index e96efff8ac5..1136d35661e 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherFloatShort.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherFloatShort.java @@ -39,7 +39,10 @@ public StaticAggOpenHasherFloatShort(ColumnSource[] tableKeySources, int tableSi this.mainKeySource1.ensureCapacity(tableSize); } - @Override + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final FloatChunk keyChunk0 = sourceKeyChunks[0].asFloatChunk(); final ShortChunk keyChunk1 = sourceKeyChunks[1].asShortChunk(); @@ -48,25 +51,25 @@ protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final float k0 = keyChunk0.get(chunkPosition); final short k1 = keyChunk1.get(chunkPosition); final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; while (true) { - int tableState = mainOutputPosition.getUnsafe(tableLocation); - if (tableState == EMPTY_OUTPUT_POSITION) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { numEntries++; mainKeySource0.set(tableLocation, k0); mainKeySource1.set(tableLocation, k1); - final int outputPosition = nextOutputPosition.getAndIncrement(); + outputPosition = nextOutputPosition.getAndIncrement(); outputPositions.set(chunkPosition, outputPosition); mainOutputPosition.set(tableLocation, outputPosition); outputPositionToHashSlot.set(outputPosition, tableLocation); break; } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { - outputPositions.set(chunkPosition, tableState); + outputPositions.set(chunkPosition, outputPosition); break; } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } @@ -79,8 +82,7 @@ private static int hash(float k0, short k1) { } @Override - protected void rehashInternal() { - final int oldSize = tableSize >> 1; + protected void rehashInternalFull(final int oldSize) { final float[] destKeyArray0 = new float[tableSize]; final short[] destKeyArray1 = new short[tableSize]; final int[] destState = new int[tableSize]; @@ -92,27 +94,27 @@ protected void rehashInternal() { final int [] originalStateArray = mainOutputPosition.getArray(); mainOutputPosition.setArray(destState); for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { - if (originalStateArray[sourceBucket] == EMPTY_OUTPUT_POSITION) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { continue; } final float k0 = originalKeyArray0[sourceBucket]; final short k1 = originalKeyArray1[sourceBucket]; final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; while (true) { - if (destState[tableLocation] == EMPTY_OUTPUT_POSITION) { - destKeyArray0[tableLocation] = k0; - destKeyArray1[tableLocation] = k1; - destState[tableLocation] = originalStateArray[sourceBucket]; - if (sourceBucket != tableLocation) { - outputPositionToHashSlot.set(destState[tableLocation], tableLocation); + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + if (sourceBucket != destinationTableLocation) { + outputPositionToHashSlot.set(currentStateValue, destinationTableLocation); } break; - } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); } } } @@ -124,7 +126,7 @@ public int findPositionForKey(Object key) { final short k1 = TypeUtils.unbox((Short)ka[1]); int hash = hash(k0, k1); int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = tableLocation; while (true) { final int positionValue = mainOutputPosition.getUnsafe(tableLocation); if (positionValue == EMPTY_OUTPUT_POSITION) { @@ -133,8 +135,8 @@ public int findPositionForKey(Object key) { if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { return positionValue; } - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherInt.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherInt.java index 6e60826249e..3c97fab3629 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherInt.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherInt.java @@ -30,31 +30,34 @@ public StaticAggOpenHasherInt(ColumnSource[] tableKeySources, int tableSize, this.mainKeySource0.ensureCapacity(tableSize); } - @Override + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final IntChunk keyChunk0 = sourceKeyChunks[0].asIntChunk(); final int chunkSize = keyChunk0.size(); for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { final int k0 = keyChunk0.get(chunkPosition); final int hash = hash(k0); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; while (true) { - int tableState = mainOutputPosition.getUnsafe(tableLocation); - if (tableState == EMPTY_OUTPUT_POSITION) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { numEntries++; mainKeySource0.set(tableLocation, k0); - final int outputPosition = nextOutputPosition.getAndIncrement(); + outputPosition = nextOutputPosition.getAndIncrement(); outputPositions.set(chunkPosition, outputPosition); mainOutputPosition.set(tableLocation, outputPosition); outputPositionToHashSlot.set(outputPosition, tableLocation); break; } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0)) { - outputPositions.set(chunkPosition, tableState); + outputPositions.set(chunkPosition, outputPosition); break; } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } @@ -66,8 +69,7 @@ private static int hash(int k0) { } @Override - protected void rehashInternal() { - final int oldSize = tableSize >> 1; + protected void rehashInternalFull(final int oldSize) { final int[] destKeyArray0 = new int[tableSize]; final int[] destState = new int[tableSize]; Arrays.fill(destState, EMPTY_OUTPUT_POSITION); @@ -76,25 +78,25 @@ protected void rehashInternal() { final int [] originalStateArray = mainOutputPosition.getArray(); mainOutputPosition.setArray(destState); for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { - if (originalStateArray[sourceBucket] == EMPTY_OUTPUT_POSITION) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { continue; } final int k0 = originalKeyArray0[sourceBucket]; final int hash = hash(k0); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; while (true) { - if (destState[tableLocation] == EMPTY_OUTPUT_POSITION) { - destKeyArray0[tableLocation] = k0; - destState[tableLocation] = originalStateArray[sourceBucket]; - if (sourceBucket != tableLocation) { - outputPositionToHashSlot.set(destState[tableLocation], tableLocation); + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + if (sourceBucket != destinationTableLocation) { + outputPositionToHashSlot.set(currentStateValue, destinationTableLocation); } break; - } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); } } } @@ -104,7 +106,7 @@ public int findPositionForKey(Object key) { final int k0 = TypeUtils.unbox((Integer)key); int hash = hash(k0); int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = tableLocation; while (true) { final int positionValue = mainOutputPosition.getUnsafe(tableLocation); if (positionValue == EMPTY_OUTPUT_POSITION) { @@ -113,8 +115,8 @@ public int findPositionForKey(Object key) { if (eq(mainKeySource0.getUnsafe(tableLocation), k0)) { return positionValue; } - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherIntByte.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherIntByte.java index 357fcd565a1..6ef8371fd8e 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherIntByte.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherIntByte.java @@ -39,7 +39,10 @@ public StaticAggOpenHasherIntByte(ColumnSource[] tableKeySources, int tableSize, this.mainKeySource1.ensureCapacity(tableSize); } - @Override + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final IntChunk keyChunk0 = sourceKeyChunks[0].asIntChunk(); final ByteChunk keyChunk1 = sourceKeyChunks[1].asByteChunk(); @@ -48,25 +51,25 @@ protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final int k0 = keyChunk0.get(chunkPosition); final byte k1 = keyChunk1.get(chunkPosition); final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; while (true) { - int tableState = mainOutputPosition.getUnsafe(tableLocation); - if (tableState == EMPTY_OUTPUT_POSITION) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { numEntries++; mainKeySource0.set(tableLocation, k0); mainKeySource1.set(tableLocation, k1); - final int outputPosition = nextOutputPosition.getAndIncrement(); + outputPosition = nextOutputPosition.getAndIncrement(); outputPositions.set(chunkPosition, outputPosition); mainOutputPosition.set(tableLocation, outputPosition); outputPositionToHashSlot.set(outputPosition, tableLocation); break; } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { - outputPositions.set(chunkPosition, tableState); + outputPositions.set(chunkPosition, outputPosition); break; } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } @@ -79,8 +82,7 @@ private static int hash(int k0, byte k1) { } @Override - protected void rehashInternal() { - final int oldSize = tableSize >> 1; + protected void rehashInternalFull(final int oldSize) { final int[] destKeyArray0 = new int[tableSize]; final byte[] destKeyArray1 = new byte[tableSize]; final int[] destState = new int[tableSize]; @@ -92,27 +94,27 @@ protected void rehashInternal() { final int [] originalStateArray = mainOutputPosition.getArray(); mainOutputPosition.setArray(destState); for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { - if (originalStateArray[sourceBucket] == EMPTY_OUTPUT_POSITION) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { continue; } final int k0 = originalKeyArray0[sourceBucket]; final byte k1 = originalKeyArray1[sourceBucket]; final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; while (true) { - if (destState[tableLocation] == EMPTY_OUTPUT_POSITION) { - destKeyArray0[tableLocation] = k0; - destKeyArray1[tableLocation] = k1; - destState[tableLocation] = originalStateArray[sourceBucket]; - if (sourceBucket != tableLocation) { - outputPositionToHashSlot.set(destState[tableLocation], tableLocation); + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + if (sourceBucket != destinationTableLocation) { + outputPositionToHashSlot.set(currentStateValue, destinationTableLocation); } break; - } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); } } } @@ -124,7 +126,7 @@ public int findPositionForKey(Object key) { final byte k1 = TypeUtils.unbox((Byte)ka[1]); int hash = hash(k0, k1); int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = tableLocation; while (true) { final int positionValue = mainOutputPosition.getUnsafe(tableLocation); if (positionValue == EMPTY_OUTPUT_POSITION) { @@ -133,8 +135,8 @@ public int findPositionForKey(Object key) { if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { return positionValue; } - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherIntChar.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherIntChar.java index 393213f675e..19807ad9101 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherIntChar.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherIntChar.java @@ -39,7 +39,10 @@ public StaticAggOpenHasherIntChar(ColumnSource[] tableKeySources, int tableSize, this.mainKeySource1.ensureCapacity(tableSize); } - @Override + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final IntChunk keyChunk0 = sourceKeyChunks[0].asIntChunk(); final CharChunk keyChunk1 = sourceKeyChunks[1].asCharChunk(); @@ -48,25 +51,25 @@ protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final int k0 = keyChunk0.get(chunkPosition); final char k1 = keyChunk1.get(chunkPosition); final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; while (true) { - int tableState = mainOutputPosition.getUnsafe(tableLocation); - if (tableState == EMPTY_OUTPUT_POSITION) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { numEntries++; mainKeySource0.set(tableLocation, k0); mainKeySource1.set(tableLocation, k1); - final int outputPosition = nextOutputPosition.getAndIncrement(); + outputPosition = nextOutputPosition.getAndIncrement(); outputPositions.set(chunkPosition, outputPosition); mainOutputPosition.set(tableLocation, outputPosition); outputPositionToHashSlot.set(outputPosition, tableLocation); break; } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { - outputPositions.set(chunkPosition, tableState); + outputPositions.set(chunkPosition, outputPosition); break; } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } @@ -79,8 +82,7 @@ private static int hash(int k0, char k1) { } @Override - protected void rehashInternal() { - final int oldSize = tableSize >> 1; + protected void rehashInternalFull(final int oldSize) { final int[] destKeyArray0 = new int[tableSize]; final char[] destKeyArray1 = new char[tableSize]; final int[] destState = new int[tableSize]; @@ -92,27 +94,27 @@ protected void rehashInternal() { final int [] originalStateArray = mainOutputPosition.getArray(); mainOutputPosition.setArray(destState); for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { - if (originalStateArray[sourceBucket] == EMPTY_OUTPUT_POSITION) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { continue; } final int k0 = originalKeyArray0[sourceBucket]; final char k1 = originalKeyArray1[sourceBucket]; final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; while (true) { - if (destState[tableLocation] == EMPTY_OUTPUT_POSITION) { - destKeyArray0[tableLocation] = k0; - destKeyArray1[tableLocation] = k1; - destState[tableLocation] = originalStateArray[sourceBucket]; - if (sourceBucket != tableLocation) { - outputPositionToHashSlot.set(destState[tableLocation], tableLocation); + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + if (sourceBucket != destinationTableLocation) { + outputPositionToHashSlot.set(currentStateValue, destinationTableLocation); } break; - } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); } } } @@ -124,7 +126,7 @@ public int findPositionForKey(Object key) { final char k1 = TypeUtils.unbox((Character)ka[1]); int hash = hash(k0, k1); int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = tableLocation; while (true) { final int positionValue = mainOutputPosition.getUnsafe(tableLocation); if (positionValue == EMPTY_OUTPUT_POSITION) { @@ -133,8 +135,8 @@ public int findPositionForKey(Object key) { if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { return positionValue; } - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherIntDouble.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherIntDouble.java index 3c4dd65f695..f0f6edd3a01 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherIntDouble.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherIntDouble.java @@ -39,7 +39,10 @@ public StaticAggOpenHasherIntDouble(ColumnSource[] tableKeySources, int tableSiz this.mainKeySource1.ensureCapacity(tableSize); } - @Override + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final IntChunk keyChunk0 = sourceKeyChunks[0].asIntChunk(); final DoubleChunk keyChunk1 = sourceKeyChunks[1].asDoubleChunk(); @@ -48,25 +51,25 @@ protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final int k0 = keyChunk0.get(chunkPosition); final double k1 = keyChunk1.get(chunkPosition); final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; while (true) { - int tableState = mainOutputPosition.getUnsafe(tableLocation); - if (tableState == EMPTY_OUTPUT_POSITION) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { numEntries++; mainKeySource0.set(tableLocation, k0); mainKeySource1.set(tableLocation, k1); - final int outputPosition = nextOutputPosition.getAndIncrement(); + outputPosition = nextOutputPosition.getAndIncrement(); outputPositions.set(chunkPosition, outputPosition); mainOutputPosition.set(tableLocation, outputPosition); outputPositionToHashSlot.set(outputPosition, tableLocation); break; } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { - outputPositions.set(chunkPosition, tableState); + outputPositions.set(chunkPosition, outputPosition); break; } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } @@ -79,8 +82,7 @@ private static int hash(int k0, double k1) { } @Override - protected void rehashInternal() { - final int oldSize = tableSize >> 1; + protected void rehashInternalFull(final int oldSize) { final int[] destKeyArray0 = new int[tableSize]; final double[] destKeyArray1 = new double[tableSize]; final int[] destState = new int[tableSize]; @@ -92,27 +94,27 @@ protected void rehashInternal() { final int [] originalStateArray = mainOutputPosition.getArray(); mainOutputPosition.setArray(destState); for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { - if (originalStateArray[sourceBucket] == EMPTY_OUTPUT_POSITION) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { continue; } final int k0 = originalKeyArray0[sourceBucket]; final double k1 = originalKeyArray1[sourceBucket]; final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; while (true) { - if (destState[tableLocation] == EMPTY_OUTPUT_POSITION) { - destKeyArray0[tableLocation] = k0; - destKeyArray1[tableLocation] = k1; - destState[tableLocation] = originalStateArray[sourceBucket]; - if (sourceBucket != tableLocation) { - outputPositionToHashSlot.set(destState[tableLocation], tableLocation); + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + if (sourceBucket != destinationTableLocation) { + outputPositionToHashSlot.set(currentStateValue, destinationTableLocation); } break; - } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); } } } @@ -124,7 +126,7 @@ public int findPositionForKey(Object key) { final double k1 = TypeUtils.unbox((Double)ka[1]); int hash = hash(k0, k1); int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = tableLocation; while (true) { final int positionValue = mainOutputPosition.getUnsafe(tableLocation); if (positionValue == EMPTY_OUTPUT_POSITION) { @@ -133,8 +135,8 @@ public int findPositionForKey(Object key) { if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { return positionValue; } - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherIntFloat.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherIntFloat.java index 3e270806018..439b94b29b0 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherIntFloat.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherIntFloat.java @@ -39,7 +39,10 @@ public StaticAggOpenHasherIntFloat(ColumnSource[] tableKeySources, int tableSize this.mainKeySource1.ensureCapacity(tableSize); } - @Override + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final IntChunk keyChunk0 = sourceKeyChunks[0].asIntChunk(); final FloatChunk keyChunk1 = sourceKeyChunks[1].asFloatChunk(); @@ -48,25 +51,25 @@ protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final int k0 = keyChunk0.get(chunkPosition); final float k1 = keyChunk1.get(chunkPosition); final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; while (true) { - int tableState = mainOutputPosition.getUnsafe(tableLocation); - if (tableState == EMPTY_OUTPUT_POSITION) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { numEntries++; mainKeySource0.set(tableLocation, k0); mainKeySource1.set(tableLocation, k1); - final int outputPosition = nextOutputPosition.getAndIncrement(); + outputPosition = nextOutputPosition.getAndIncrement(); outputPositions.set(chunkPosition, outputPosition); mainOutputPosition.set(tableLocation, outputPosition); outputPositionToHashSlot.set(outputPosition, tableLocation); break; } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { - outputPositions.set(chunkPosition, tableState); + outputPositions.set(chunkPosition, outputPosition); break; } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } @@ -79,8 +82,7 @@ private static int hash(int k0, float k1) { } @Override - protected void rehashInternal() { - final int oldSize = tableSize >> 1; + protected void rehashInternalFull(final int oldSize) { final int[] destKeyArray0 = new int[tableSize]; final float[] destKeyArray1 = new float[tableSize]; final int[] destState = new int[tableSize]; @@ -92,27 +94,27 @@ protected void rehashInternal() { final int [] originalStateArray = mainOutputPosition.getArray(); mainOutputPosition.setArray(destState); for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { - if (originalStateArray[sourceBucket] == EMPTY_OUTPUT_POSITION) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { continue; } final int k0 = originalKeyArray0[sourceBucket]; final float k1 = originalKeyArray1[sourceBucket]; final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; while (true) { - if (destState[tableLocation] == EMPTY_OUTPUT_POSITION) { - destKeyArray0[tableLocation] = k0; - destKeyArray1[tableLocation] = k1; - destState[tableLocation] = originalStateArray[sourceBucket]; - if (sourceBucket != tableLocation) { - outputPositionToHashSlot.set(destState[tableLocation], tableLocation); + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + if (sourceBucket != destinationTableLocation) { + outputPositionToHashSlot.set(currentStateValue, destinationTableLocation); } break; - } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); } } } @@ -124,7 +126,7 @@ public int findPositionForKey(Object key) { final float k1 = TypeUtils.unbox((Float)ka[1]); int hash = hash(k0, k1); int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = tableLocation; while (true) { final int positionValue = mainOutputPosition.getUnsafe(tableLocation); if (positionValue == EMPTY_OUTPUT_POSITION) { @@ -133,8 +135,8 @@ public int findPositionForKey(Object key) { if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { return positionValue; } - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherIntInt.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherIntInt.java index 5598e8d48f3..583d867ac3b 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherIntInt.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherIntInt.java @@ -34,7 +34,10 @@ public StaticAggOpenHasherIntInt(ColumnSource[] tableKeySources, int tableSize, this.mainKeySource1.ensureCapacity(tableSize); } - @Override + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final IntChunk keyChunk0 = sourceKeyChunks[0].asIntChunk(); final IntChunk keyChunk1 = sourceKeyChunks[1].asIntChunk(); @@ -43,25 +46,25 @@ protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final int k0 = keyChunk0.get(chunkPosition); final int k1 = keyChunk1.get(chunkPosition); final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; while (true) { - int tableState = mainOutputPosition.getUnsafe(tableLocation); - if (tableState == EMPTY_OUTPUT_POSITION) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { numEntries++; mainKeySource0.set(tableLocation, k0); mainKeySource1.set(tableLocation, k1); - final int outputPosition = nextOutputPosition.getAndIncrement(); + outputPosition = nextOutputPosition.getAndIncrement(); outputPositions.set(chunkPosition, outputPosition); mainOutputPosition.set(tableLocation, outputPosition); outputPositionToHashSlot.set(outputPosition, tableLocation); break; } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { - outputPositions.set(chunkPosition, tableState); + outputPositions.set(chunkPosition, outputPosition); break; } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } @@ -74,8 +77,7 @@ private static int hash(int k0, int k1) { } @Override - protected void rehashInternal() { - final int oldSize = tableSize >> 1; + protected void rehashInternalFull(final int oldSize) { final int[] destKeyArray0 = new int[tableSize]; final int[] destKeyArray1 = new int[tableSize]; final int[] destState = new int[tableSize]; @@ -87,27 +89,27 @@ protected void rehashInternal() { final int [] originalStateArray = mainOutputPosition.getArray(); mainOutputPosition.setArray(destState); for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { - if (originalStateArray[sourceBucket] == EMPTY_OUTPUT_POSITION) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { continue; } final int k0 = originalKeyArray0[sourceBucket]; final int k1 = originalKeyArray1[sourceBucket]; final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; while (true) { - if (destState[tableLocation] == EMPTY_OUTPUT_POSITION) { - destKeyArray0[tableLocation] = k0; - destKeyArray1[tableLocation] = k1; - destState[tableLocation] = originalStateArray[sourceBucket]; - if (sourceBucket != tableLocation) { - outputPositionToHashSlot.set(destState[tableLocation], tableLocation); + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + if (sourceBucket != destinationTableLocation) { + outputPositionToHashSlot.set(currentStateValue, destinationTableLocation); } break; - } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); } } } @@ -119,7 +121,7 @@ public int findPositionForKey(Object key) { final int k1 = TypeUtils.unbox((Integer)ka[1]); int hash = hash(k0, k1); int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = tableLocation; while (true) { final int positionValue = mainOutputPosition.getUnsafe(tableLocation); if (positionValue == EMPTY_OUTPUT_POSITION) { @@ -128,8 +130,8 @@ public int findPositionForKey(Object key) { if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { return positionValue; } - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherIntLong.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherIntLong.java index f03f2a1fb68..417e990f7e8 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherIntLong.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherIntLong.java @@ -39,7 +39,10 @@ public StaticAggOpenHasherIntLong(ColumnSource[] tableKeySources, int tableSize, this.mainKeySource1.ensureCapacity(tableSize); } - @Override + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final IntChunk keyChunk0 = sourceKeyChunks[0].asIntChunk(); final LongChunk keyChunk1 = sourceKeyChunks[1].asLongChunk(); @@ -48,25 +51,25 @@ protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final int k0 = keyChunk0.get(chunkPosition); final long k1 = keyChunk1.get(chunkPosition); final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; while (true) { - int tableState = mainOutputPosition.getUnsafe(tableLocation); - if (tableState == EMPTY_OUTPUT_POSITION) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { numEntries++; mainKeySource0.set(tableLocation, k0); mainKeySource1.set(tableLocation, k1); - final int outputPosition = nextOutputPosition.getAndIncrement(); + outputPosition = nextOutputPosition.getAndIncrement(); outputPositions.set(chunkPosition, outputPosition); mainOutputPosition.set(tableLocation, outputPosition); outputPositionToHashSlot.set(outputPosition, tableLocation); break; } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { - outputPositions.set(chunkPosition, tableState); + outputPositions.set(chunkPosition, outputPosition); break; } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } @@ -79,8 +82,7 @@ private static int hash(int k0, long k1) { } @Override - protected void rehashInternal() { - final int oldSize = tableSize >> 1; + protected void rehashInternalFull(final int oldSize) { final int[] destKeyArray0 = new int[tableSize]; final long[] destKeyArray1 = new long[tableSize]; final int[] destState = new int[tableSize]; @@ -92,27 +94,27 @@ protected void rehashInternal() { final int [] originalStateArray = mainOutputPosition.getArray(); mainOutputPosition.setArray(destState); for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { - if (originalStateArray[sourceBucket] == EMPTY_OUTPUT_POSITION) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { continue; } final int k0 = originalKeyArray0[sourceBucket]; final long k1 = originalKeyArray1[sourceBucket]; final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; while (true) { - if (destState[tableLocation] == EMPTY_OUTPUT_POSITION) { - destKeyArray0[tableLocation] = k0; - destKeyArray1[tableLocation] = k1; - destState[tableLocation] = originalStateArray[sourceBucket]; - if (sourceBucket != tableLocation) { - outputPositionToHashSlot.set(destState[tableLocation], tableLocation); + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + if (sourceBucket != destinationTableLocation) { + outputPositionToHashSlot.set(currentStateValue, destinationTableLocation); } break; - } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); } } } @@ -124,7 +126,7 @@ public int findPositionForKey(Object key) { final long k1 = TypeUtils.unbox((Long)ka[1]); int hash = hash(k0, k1); int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = tableLocation; while (true) { final int positionValue = mainOutputPosition.getUnsafe(tableLocation); if (positionValue == EMPTY_OUTPUT_POSITION) { @@ -133,8 +135,8 @@ public int findPositionForKey(Object key) { if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { return positionValue; } - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherIntObject.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherIntObject.java index 043d64164fd..0626d48e16e 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherIntObject.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherIntObject.java @@ -38,7 +38,10 @@ public StaticAggOpenHasherIntObject(ColumnSource[] tableKeySources, int tableSiz this.mainKeySource1.ensureCapacity(tableSize); } - @Override + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final IntChunk keyChunk0 = sourceKeyChunks[0].asIntChunk(); final ObjectChunk keyChunk1 = sourceKeyChunks[1].asObjectChunk(); @@ -47,25 +50,25 @@ protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final int k0 = keyChunk0.get(chunkPosition); final Object k1 = keyChunk1.get(chunkPosition); final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; while (true) { - int tableState = mainOutputPosition.getUnsafe(tableLocation); - if (tableState == EMPTY_OUTPUT_POSITION) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { numEntries++; mainKeySource0.set(tableLocation, k0); mainKeySource1.set(tableLocation, k1); - final int outputPosition = nextOutputPosition.getAndIncrement(); + outputPosition = nextOutputPosition.getAndIncrement(); outputPositions.set(chunkPosition, outputPosition); mainOutputPosition.set(tableLocation, outputPosition); outputPositionToHashSlot.set(outputPosition, tableLocation); break; } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { - outputPositions.set(chunkPosition, tableState); + outputPositions.set(chunkPosition, outputPosition); break; } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } @@ -78,8 +81,7 @@ private static int hash(int k0, Object k1) { } @Override - protected void rehashInternal() { - final int oldSize = tableSize >> 1; + protected void rehashInternalFull(final int oldSize) { final int[] destKeyArray0 = new int[tableSize]; final Object[] destKeyArray1 = new Object[tableSize]; final int[] destState = new int[tableSize]; @@ -91,27 +93,27 @@ protected void rehashInternal() { final int [] originalStateArray = mainOutputPosition.getArray(); mainOutputPosition.setArray(destState); for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { - if (originalStateArray[sourceBucket] == EMPTY_OUTPUT_POSITION) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { continue; } final int k0 = originalKeyArray0[sourceBucket]; final Object k1 = originalKeyArray1[sourceBucket]; final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; while (true) { - if (destState[tableLocation] == EMPTY_OUTPUT_POSITION) { - destKeyArray0[tableLocation] = k0; - destKeyArray1[tableLocation] = k1; - destState[tableLocation] = originalStateArray[sourceBucket]; - if (sourceBucket != tableLocation) { - outputPositionToHashSlot.set(destState[tableLocation], tableLocation); + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + if (sourceBucket != destinationTableLocation) { + outputPositionToHashSlot.set(currentStateValue, destinationTableLocation); } break; - } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); } } } @@ -123,7 +125,7 @@ public int findPositionForKey(Object key) { final Object k1 = ka[1]; int hash = hash(k0, k1); int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = tableLocation; while (true) { final int positionValue = mainOutputPosition.getUnsafe(tableLocation); if (positionValue == EMPTY_OUTPUT_POSITION) { @@ -132,8 +134,8 @@ public int findPositionForKey(Object key) { if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { return positionValue; } - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherIntShort.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherIntShort.java index 779d71160a5..a50b41e3b0a 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherIntShort.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherIntShort.java @@ -39,7 +39,10 @@ public StaticAggOpenHasherIntShort(ColumnSource[] tableKeySources, int tableSize this.mainKeySource1.ensureCapacity(tableSize); } - @Override + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final IntChunk keyChunk0 = sourceKeyChunks[0].asIntChunk(); final ShortChunk keyChunk1 = sourceKeyChunks[1].asShortChunk(); @@ -48,25 +51,25 @@ protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final int k0 = keyChunk0.get(chunkPosition); final short k1 = keyChunk1.get(chunkPosition); final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; while (true) { - int tableState = mainOutputPosition.getUnsafe(tableLocation); - if (tableState == EMPTY_OUTPUT_POSITION) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { numEntries++; mainKeySource0.set(tableLocation, k0); mainKeySource1.set(tableLocation, k1); - final int outputPosition = nextOutputPosition.getAndIncrement(); + outputPosition = nextOutputPosition.getAndIncrement(); outputPositions.set(chunkPosition, outputPosition); mainOutputPosition.set(tableLocation, outputPosition); outputPositionToHashSlot.set(outputPosition, tableLocation); break; } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { - outputPositions.set(chunkPosition, tableState); + outputPositions.set(chunkPosition, outputPosition); break; } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } @@ -79,8 +82,7 @@ private static int hash(int k0, short k1) { } @Override - protected void rehashInternal() { - final int oldSize = tableSize >> 1; + protected void rehashInternalFull(final int oldSize) { final int[] destKeyArray0 = new int[tableSize]; final short[] destKeyArray1 = new short[tableSize]; final int[] destState = new int[tableSize]; @@ -92,27 +94,27 @@ protected void rehashInternal() { final int [] originalStateArray = mainOutputPosition.getArray(); mainOutputPosition.setArray(destState); for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { - if (originalStateArray[sourceBucket] == EMPTY_OUTPUT_POSITION) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { continue; } final int k0 = originalKeyArray0[sourceBucket]; final short k1 = originalKeyArray1[sourceBucket]; final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; while (true) { - if (destState[tableLocation] == EMPTY_OUTPUT_POSITION) { - destKeyArray0[tableLocation] = k0; - destKeyArray1[tableLocation] = k1; - destState[tableLocation] = originalStateArray[sourceBucket]; - if (sourceBucket != tableLocation) { - outputPositionToHashSlot.set(destState[tableLocation], tableLocation); + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + if (sourceBucket != destinationTableLocation) { + outputPositionToHashSlot.set(currentStateValue, destinationTableLocation); } break; - } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); } } } @@ -124,7 +126,7 @@ public int findPositionForKey(Object key) { final short k1 = TypeUtils.unbox((Short)ka[1]); int hash = hash(k0, k1); int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = tableLocation; while (true) { final int positionValue = mainOutputPosition.getUnsafe(tableLocation); if (positionValue == EMPTY_OUTPUT_POSITION) { @@ -133,8 +135,8 @@ public int findPositionForKey(Object key) { if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { return positionValue; } - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherLong.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherLong.java index 074e680dfd7..a83113e75dd 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherLong.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherLong.java @@ -30,31 +30,34 @@ public StaticAggOpenHasherLong(ColumnSource[] tableKeySources, int tableSize, this.mainKeySource0.ensureCapacity(tableSize); } - @Override + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final LongChunk keyChunk0 = sourceKeyChunks[0].asLongChunk(); final int chunkSize = keyChunk0.size(); for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { final long k0 = keyChunk0.get(chunkPosition); final int hash = hash(k0); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; while (true) { - int tableState = mainOutputPosition.getUnsafe(tableLocation); - if (tableState == EMPTY_OUTPUT_POSITION) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { numEntries++; mainKeySource0.set(tableLocation, k0); - final int outputPosition = nextOutputPosition.getAndIncrement(); + outputPosition = nextOutputPosition.getAndIncrement(); outputPositions.set(chunkPosition, outputPosition); mainOutputPosition.set(tableLocation, outputPosition); outputPositionToHashSlot.set(outputPosition, tableLocation); break; } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0)) { - outputPositions.set(chunkPosition, tableState); + outputPositions.set(chunkPosition, outputPosition); break; } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } @@ -66,8 +69,7 @@ private static int hash(long k0) { } @Override - protected void rehashInternal() { - final int oldSize = tableSize >> 1; + protected void rehashInternalFull(final int oldSize) { final long[] destKeyArray0 = new long[tableSize]; final int[] destState = new int[tableSize]; Arrays.fill(destState, EMPTY_OUTPUT_POSITION); @@ -76,25 +78,25 @@ protected void rehashInternal() { final int [] originalStateArray = mainOutputPosition.getArray(); mainOutputPosition.setArray(destState); for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { - if (originalStateArray[sourceBucket] == EMPTY_OUTPUT_POSITION) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { continue; } final long k0 = originalKeyArray0[sourceBucket]; final int hash = hash(k0); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; while (true) { - if (destState[tableLocation] == EMPTY_OUTPUT_POSITION) { - destKeyArray0[tableLocation] = k0; - destState[tableLocation] = originalStateArray[sourceBucket]; - if (sourceBucket != tableLocation) { - outputPositionToHashSlot.set(destState[tableLocation], tableLocation); + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + if (sourceBucket != destinationTableLocation) { + outputPositionToHashSlot.set(currentStateValue, destinationTableLocation); } break; - } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); } } } @@ -104,7 +106,7 @@ public int findPositionForKey(Object key) { final long k0 = TypeUtils.unbox((Long)key); int hash = hash(k0); int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = tableLocation; while (true) { final int positionValue = mainOutputPosition.getUnsafe(tableLocation); if (positionValue == EMPTY_OUTPUT_POSITION) { @@ -113,8 +115,8 @@ public int findPositionForKey(Object key) { if (eq(mainKeySource0.getUnsafe(tableLocation), k0)) { return positionValue; } - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherLongByte.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherLongByte.java index e51906774f5..dbb68260b23 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherLongByte.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherLongByte.java @@ -39,7 +39,10 @@ public StaticAggOpenHasherLongByte(ColumnSource[] tableKeySources, int tableSize this.mainKeySource1.ensureCapacity(tableSize); } - @Override + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final LongChunk keyChunk0 = sourceKeyChunks[0].asLongChunk(); final ByteChunk keyChunk1 = sourceKeyChunks[1].asByteChunk(); @@ -48,25 +51,25 @@ protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final long k0 = keyChunk0.get(chunkPosition); final byte k1 = keyChunk1.get(chunkPosition); final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; while (true) { - int tableState = mainOutputPosition.getUnsafe(tableLocation); - if (tableState == EMPTY_OUTPUT_POSITION) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { numEntries++; mainKeySource0.set(tableLocation, k0); mainKeySource1.set(tableLocation, k1); - final int outputPosition = nextOutputPosition.getAndIncrement(); + outputPosition = nextOutputPosition.getAndIncrement(); outputPositions.set(chunkPosition, outputPosition); mainOutputPosition.set(tableLocation, outputPosition); outputPositionToHashSlot.set(outputPosition, tableLocation); break; } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { - outputPositions.set(chunkPosition, tableState); + outputPositions.set(chunkPosition, outputPosition); break; } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } @@ -79,8 +82,7 @@ private static int hash(long k0, byte k1) { } @Override - protected void rehashInternal() { - final int oldSize = tableSize >> 1; + protected void rehashInternalFull(final int oldSize) { final long[] destKeyArray0 = new long[tableSize]; final byte[] destKeyArray1 = new byte[tableSize]; final int[] destState = new int[tableSize]; @@ -92,27 +94,27 @@ protected void rehashInternal() { final int [] originalStateArray = mainOutputPosition.getArray(); mainOutputPosition.setArray(destState); for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { - if (originalStateArray[sourceBucket] == EMPTY_OUTPUT_POSITION) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { continue; } final long k0 = originalKeyArray0[sourceBucket]; final byte k1 = originalKeyArray1[sourceBucket]; final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; while (true) { - if (destState[tableLocation] == EMPTY_OUTPUT_POSITION) { - destKeyArray0[tableLocation] = k0; - destKeyArray1[tableLocation] = k1; - destState[tableLocation] = originalStateArray[sourceBucket]; - if (sourceBucket != tableLocation) { - outputPositionToHashSlot.set(destState[tableLocation], tableLocation); + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + if (sourceBucket != destinationTableLocation) { + outputPositionToHashSlot.set(currentStateValue, destinationTableLocation); } break; - } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); } } } @@ -124,7 +126,7 @@ public int findPositionForKey(Object key) { final byte k1 = TypeUtils.unbox((Byte)ka[1]); int hash = hash(k0, k1); int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = tableLocation; while (true) { final int positionValue = mainOutputPosition.getUnsafe(tableLocation); if (positionValue == EMPTY_OUTPUT_POSITION) { @@ -133,8 +135,8 @@ public int findPositionForKey(Object key) { if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { return positionValue; } - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherLongChar.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherLongChar.java index 65ff28221fc..9bfccde8b4d 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherLongChar.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherLongChar.java @@ -39,7 +39,10 @@ public StaticAggOpenHasherLongChar(ColumnSource[] tableKeySources, int tableSize this.mainKeySource1.ensureCapacity(tableSize); } - @Override + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final LongChunk keyChunk0 = sourceKeyChunks[0].asLongChunk(); final CharChunk keyChunk1 = sourceKeyChunks[1].asCharChunk(); @@ -48,25 +51,25 @@ protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final long k0 = keyChunk0.get(chunkPosition); final char k1 = keyChunk1.get(chunkPosition); final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; while (true) { - int tableState = mainOutputPosition.getUnsafe(tableLocation); - if (tableState == EMPTY_OUTPUT_POSITION) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { numEntries++; mainKeySource0.set(tableLocation, k0); mainKeySource1.set(tableLocation, k1); - final int outputPosition = nextOutputPosition.getAndIncrement(); + outputPosition = nextOutputPosition.getAndIncrement(); outputPositions.set(chunkPosition, outputPosition); mainOutputPosition.set(tableLocation, outputPosition); outputPositionToHashSlot.set(outputPosition, tableLocation); break; } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { - outputPositions.set(chunkPosition, tableState); + outputPositions.set(chunkPosition, outputPosition); break; } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } @@ -79,8 +82,7 @@ private static int hash(long k0, char k1) { } @Override - protected void rehashInternal() { - final int oldSize = tableSize >> 1; + protected void rehashInternalFull(final int oldSize) { final long[] destKeyArray0 = new long[tableSize]; final char[] destKeyArray1 = new char[tableSize]; final int[] destState = new int[tableSize]; @@ -92,27 +94,27 @@ protected void rehashInternal() { final int [] originalStateArray = mainOutputPosition.getArray(); mainOutputPosition.setArray(destState); for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { - if (originalStateArray[sourceBucket] == EMPTY_OUTPUT_POSITION) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { continue; } final long k0 = originalKeyArray0[sourceBucket]; final char k1 = originalKeyArray1[sourceBucket]; final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; while (true) { - if (destState[tableLocation] == EMPTY_OUTPUT_POSITION) { - destKeyArray0[tableLocation] = k0; - destKeyArray1[tableLocation] = k1; - destState[tableLocation] = originalStateArray[sourceBucket]; - if (sourceBucket != tableLocation) { - outputPositionToHashSlot.set(destState[tableLocation], tableLocation); + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + if (sourceBucket != destinationTableLocation) { + outputPositionToHashSlot.set(currentStateValue, destinationTableLocation); } break; - } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); } } } @@ -124,7 +126,7 @@ public int findPositionForKey(Object key) { final char k1 = TypeUtils.unbox((Character)ka[1]); int hash = hash(k0, k1); int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = tableLocation; while (true) { final int positionValue = mainOutputPosition.getUnsafe(tableLocation); if (positionValue == EMPTY_OUTPUT_POSITION) { @@ -133,8 +135,8 @@ public int findPositionForKey(Object key) { if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { return positionValue; } - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherLongDouble.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherLongDouble.java index be7a5c8215c..dd0a12bbc6a 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherLongDouble.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherLongDouble.java @@ -39,7 +39,10 @@ public StaticAggOpenHasherLongDouble(ColumnSource[] tableKeySources, int tableSi this.mainKeySource1.ensureCapacity(tableSize); } - @Override + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final LongChunk keyChunk0 = sourceKeyChunks[0].asLongChunk(); final DoubleChunk keyChunk1 = sourceKeyChunks[1].asDoubleChunk(); @@ -48,25 +51,25 @@ protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final long k0 = keyChunk0.get(chunkPosition); final double k1 = keyChunk1.get(chunkPosition); final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; while (true) { - int tableState = mainOutputPosition.getUnsafe(tableLocation); - if (tableState == EMPTY_OUTPUT_POSITION) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { numEntries++; mainKeySource0.set(tableLocation, k0); mainKeySource1.set(tableLocation, k1); - final int outputPosition = nextOutputPosition.getAndIncrement(); + outputPosition = nextOutputPosition.getAndIncrement(); outputPositions.set(chunkPosition, outputPosition); mainOutputPosition.set(tableLocation, outputPosition); outputPositionToHashSlot.set(outputPosition, tableLocation); break; } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { - outputPositions.set(chunkPosition, tableState); + outputPositions.set(chunkPosition, outputPosition); break; } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } @@ -79,8 +82,7 @@ private static int hash(long k0, double k1) { } @Override - protected void rehashInternal() { - final int oldSize = tableSize >> 1; + protected void rehashInternalFull(final int oldSize) { final long[] destKeyArray0 = new long[tableSize]; final double[] destKeyArray1 = new double[tableSize]; final int[] destState = new int[tableSize]; @@ -92,27 +94,27 @@ protected void rehashInternal() { final int [] originalStateArray = mainOutputPosition.getArray(); mainOutputPosition.setArray(destState); for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { - if (originalStateArray[sourceBucket] == EMPTY_OUTPUT_POSITION) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { continue; } final long k0 = originalKeyArray0[sourceBucket]; final double k1 = originalKeyArray1[sourceBucket]; final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; while (true) { - if (destState[tableLocation] == EMPTY_OUTPUT_POSITION) { - destKeyArray0[tableLocation] = k0; - destKeyArray1[tableLocation] = k1; - destState[tableLocation] = originalStateArray[sourceBucket]; - if (sourceBucket != tableLocation) { - outputPositionToHashSlot.set(destState[tableLocation], tableLocation); + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + if (sourceBucket != destinationTableLocation) { + outputPositionToHashSlot.set(currentStateValue, destinationTableLocation); } break; - } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); } } } @@ -124,7 +126,7 @@ public int findPositionForKey(Object key) { final double k1 = TypeUtils.unbox((Double)ka[1]); int hash = hash(k0, k1); int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = tableLocation; while (true) { final int positionValue = mainOutputPosition.getUnsafe(tableLocation); if (positionValue == EMPTY_OUTPUT_POSITION) { @@ -133,8 +135,8 @@ public int findPositionForKey(Object key) { if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { return positionValue; } - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherLongFloat.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherLongFloat.java index 9ad81f71c6a..ff20c9a2232 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherLongFloat.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherLongFloat.java @@ -39,7 +39,10 @@ public StaticAggOpenHasherLongFloat(ColumnSource[] tableKeySources, int tableSiz this.mainKeySource1.ensureCapacity(tableSize); } - @Override + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final LongChunk keyChunk0 = sourceKeyChunks[0].asLongChunk(); final FloatChunk keyChunk1 = sourceKeyChunks[1].asFloatChunk(); @@ -48,25 +51,25 @@ protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final long k0 = keyChunk0.get(chunkPosition); final float k1 = keyChunk1.get(chunkPosition); final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; while (true) { - int tableState = mainOutputPosition.getUnsafe(tableLocation); - if (tableState == EMPTY_OUTPUT_POSITION) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { numEntries++; mainKeySource0.set(tableLocation, k0); mainKeySource1.set(tableLocation, k1); - final int outputPosition = nextOutputPosition.getAndIncrement(); + outputPosition = nextOutputPosition.getAndIncrement(); outputPositions.set(chunkPosition, outputPosition); mainOutputPosition.set(tableLocation, outputPosition); outputPositionToHashSlot.set(outputPosition, tableLocation); break; } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { - outputPositions.set(chunkPosition, tableState); + outputPositions.set(chunkPosition, outputPosition); break; } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } @@ -79,8 +82,7 @@ private static int hash(long k0, float k1) { } @Override - protected void rehashInternal() { - final int oldSize = tableSize >> 1; + protected void rehashInternalFull(final int oldSize) { final long[] destKeyArray0 = new long[tableSize]; final float[] destKeyArray1 = new float[tableSize]; final int[] destState = new int[tableSize]; @@ -92,27 +94,27 @@ protected void rehashInternal() { final int [] originalStateArray = mainOutputPosition.getArray(); mainOutputPosition.setArray(destState); for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { - if (originalStateArray[sourceBucket] == EMPTY_OUTPUT_POSITION) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { continue; } final long k0 = originalKeyArray0[sourceBucket]; final float k1 = originalKeyArray1[sourceBucket]; final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; while (true) { - if (destState[tableLocation] == EMPTY_OUTPUT_POSITION) { - destKeyArray0[tableLocation] = k0; - destKeyArray1[tableLocation] = k1; - destState[tableLocation] = originalStateArray[sourceBucket]; - if (sourceBucket != tableLocation) { - outputPositionToHashSlot.set(destState[tableLocation], tableLocation); + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + if (sourceBucket != destinationTableLocation) { + outputPositionToHashSlot.set(currentStateValue, destinationTableLocation); } break; - } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); } } } @@ -124,7 +126,7 @@ public int findPositionForKey(Object key) { final float k1 = TypeUtils.unbox((Float)ka[1]); int hash = hash(k0, k1); int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = tableLocation; while (true) { final int positionValue = mainOutputPosition.getUnsafe(tableLocation); if (positionValue == EMPTY_OUTPUT_POSITION) { @@ -133,8 +135,8 @@ public int findPositionForKey(Object key) { if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { return positionValue; } - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherLongInt.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherLongInt.java index 524b578a5e6..3f5e51e67bb 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherLongInt.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherLongInt.java @@ -39,7 +39,10 @@ public StaticAggOpenHasherLongInt(ColumnSource[] tableKeySources, int tableSize, this.mainKeySource1.ensureCapacity(tableSize); } - @Override + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final LongChunk keyChunk0 = sourceKeyChunks[0].asLongChunk(); final IntChunk keyChunk1 = sourceKeyChunks[1].asIntChunk(); @@ -48,25 +51,25 @@ protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final long k0 = keyChunk0.get(chunkPosition); final int k1 = keyChunk1.get(chunkPosition); final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; while (true) { - int tableState = mainOutputPosition.getUnsafe(tableLocation); - if (tableState == EMPTY_OUTPUT_POSITION) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { numEntries++; mainKeySource0.set(tableLocation, k0); mainKeySource1.set(tableLocation, k1); - final int outputPosition = nextOutputPosition.getAndIncrement(); + outputPosition = nextOutputPosition.getAndIncrement(); outputPositions.set(chunkPosition, outputPosition); mainOutputPosition.set(tableLocation, outputPosition); outputPositionToHashSlot.set(outputPosition, tableLocation); break; } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { - outputPositions.set(chunkPosition, tableState); + outputPositions.set(chunkPosition, outputPosition); break; } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } @@ -79,8 +82,7 @@ private static int hash(long k0, int k1) { } @Override - protected void rehashInternal() { - final int oldSize = tableSize >> 1; + protected void rehashInternalFull(final int oldSize) { final long[] destKeyArray0 = new long[tableSize]; final int[] destKeyArray1 = new int[tableSize]; final int[] destState = new int[tableSize]; @@ -92,27 +94,27 @@ protected void rehashInternal() { final int [] originalStateArray = mainOutputPosition.getArray(); mainOutputPosition.setArray(destState); for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { - if (originalStateArray[sourceBucket] == EMPTY_OUTPUT_POSITION) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { continue; } final long k0 = originalKeyArray0[sourceBucket]; final int k1 = originalKeyArray1[sourceBucket]; final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; while (true) { - if (destState[tableLocation] == EMPTY_OUTPUT_POSITION) { - destKeyArray0[tableLocation] = k0; - destKeyArray1[tableLocation] = k1; - destState[tableLocation] = originalStateArray[sourceBucket]; - if (sourceBucket != tableLocation) { - outputPositionToHashSlot.set(destState[tableLocation], tableLocation); + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + if (sourceBucket != destinationTableLocation) { + outputPositionToHashSlot.set(currentStateValue, destinationTableLocation); } break; - } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); } } } @@ -124,7 +126,7 @@ public int findPositionForKey(Object key) { final int k1 = TypeUtils.unbox((Integer)ka[1]); int hash = hash(k0, k1); int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = tableLocation; while (true) { final int positionValue = mainOutputPosition.getUnsafe(tableLocation); if (positionValue == EMPTY_OUTPUT_POSITION) { @@ -133,8 +135,8 @@ public int findPositionForKey(Object key) { if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { return positionValue; } - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherLongLong.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherLongLong.java index dd5feddbc09..1785d82790e 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherLongLong.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherLongLong.java @@ -34,7 +34,10 @@ public StaticAggOpenHasherLongLong(ColumnSource[] tableKeySources, int tableSize this.mainKeySource1.ensureCapacity(tableSize); } - @Override + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final LongChunk keyChunk0 = sourceKeyChunks[0].asLongChunk(); final LongChunk keyChunk1 = sourceKeyChunks[1].asLongChunk(); @@ -43,25 +46,25 @@ protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final long k0 = keyChunk0.get(chunkPosition); final long k1 = keyChunk1.get(chunkPosition); final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; while (true) { - int tableState = mainOutputPosition.getUnsafe(tableLocation); - if (tableState == EMPTY_OUTPUT_POSITION) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { numEntries++; mainKeySource0.set(tableLocation, k0); mainKeySource1.set(tableLocation, k1); - final int outputPosition = nextOutputPosition.getAndIncrement(); + outputPosition = nextOutputPosition.getAndIncrement(); outputPositions.set(chunkPosition, outputPosition); mainOutputPosition.set(tableLocation, outputPosition); outputPositionToHashSlot.set(outputPosition, tableLocation); break; } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { - outputPositions.set(chunkPosition, tableState); + outputPositions.set(chunkPosition, outputPosition); break; } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } @@ -74,8 +77,7 @@ private static int hash(long k0, long k1) { } @Override - protected void rehashInternal() { - final int oldSize = tableSize >> 1; + protected void rehashInternalFull(final int oldSize) { final long[] destKeyArray0 = new long[tableSize]; final long[] destKeyArray1 = new long[tableSize]; final int[] destState = new int[tableSize]; @@ -87,27 +89,27 @@ protected void rehashInternal() { final int [] originalStateArray = mainOutputPosition.getArray(); mainOutputPosition.setArray(destState); for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { - if (originalStateArray[sourceBucket] == EMPTY_OUTPUT_POSITION) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { continue; } final long k0 = originalKeyArray0[sourceBucket]; final long k1 = originalKeyArray1[sourceBucket]; final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; while (true) { - if (destState[tableLocation] == EMPTY_OUTPUT_POSITION) { - destKeyArray0[tableLocation] = k0; - destKeyArray1[tableLocation] = k1; - destState[tableLocation] = originalStateArray[sourceBucket]; - if (sourceBucket != tableLocation) { - outputPositionToHashSlot.set(destState[tableLocation], tableLocation); + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + if (sourceBucket != destinationTableLocation) { + outputPositionToHashSlot.set(currentStateValue, destinationTableLocation); } break; - } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); } } } @@ -119,7 +121,7 @@ public int findPositionForKey(Object key) { final long k1 = TypeUtils.unbox((Long)ka[1]); int hash = hash(k0, k1); int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = tableLocation; while (true) { final int positionValue = mainOutputPosition.getUnsafe(tableLocation); if (positionValue == EMPTY_OUTPUT_POSITION) { @@ -128,8 +130,8 @@ public int findPositionForKey(Object key) { if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { return positionValue; } - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherLongObject.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherLongObject.java index 19685b65551..ec3ec54d40f 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherLongObject.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherLongObject.java @@ -38,7 +38,10 @@ public StaticAggOpenHasherLongObject(ColumnSource[] tableKeySources, int tableSi this.mainKeySource1.ensureCapacity(tableSize); } - @Override + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final LongChunk keyChunk0 = sourceKeyChunks[0].asLongChunk(); final ObjectChunk keyChunk1 = sourceKeyChunks[1].asObjectChunk(); @@ -47,25 +50,25 @@ protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final long k0 = keyChunk0.get(chunkPosition); final Object k1 = keyChunk1.get(chunkPosition); final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; while (true) { - int tableState = mainOutputPosition.getUnsafe(tableLocation); - if (tableState == EMPTY_OUTPUT_POSITION) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { numEntries++; mainKeySource0.set(tableLocation, k0); mainKeySource1.set(tableLocation, k1); - final int outputPosition = nextOutputPosition.getAndIncrement(); + outputPosition = nextOutputPosition.getAndIncrement(); outputPositions.set(chunkPosition, outputPosition); mainOutputPosition.set(tableLocation, outputPosition); outputPositionToHashSlot.set(outputPosition, tableLocation); break; } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { - outputPositions.set(chunkPosition, tableState); + outputPositions.set(chunkPosition, outputPosition); break; } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } @@ -78,8 +81,7 @@ private static int hash(long k0, Object k1) { } @Override - protected void rehashInternal() { - final int oldSize = tableSize >> 1; + protected void rehashInternalFull(final int oldSize) { final long[] destKeyArray0 = new long[tableSize]; final Object[] destKeyArray1 = new Object[tableSize]; final int[] destState = new int[tableSize]; @@ -91,27 +93,27 @@ protected void rehashInternal() { final int [] originalStateArray = mainOutputPosition.getArray(); mainOutputPosition.setArray(destState); for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { - if (originalStateArray[sourceBucket] == EMPTY_OUTPUT_POSITION) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { continue; } final long k0 = originalKeyArray0[sourceBucket]; final Object k1 = originalKeyArray1[sourceBucket]; final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; while (true) { - if (destState[tableLocation] == EMPTY_OUTPUT_POSITION) { - destKeyArray0[tableLocation] = k0; - destKeyArray1[tableLocation] = k1; - destState[tableLocation] = originalStateArray[sourceBucket]; - if (sourceBucket != tableLocation) { - outputPositionToHashSlot.set(destState[tableLocation], tableLocation); + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + if (sourceBucket != destinationTableLocation) { + outputPositionToHashSlot.set(currentStateValue, destinationTableLocation); } break; - } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); } } } @@ -123,7 +125,7 @@ public int findPositionForKey(Object key) { final Object k1 = ka[1]; int hash = hash(k0, k1); int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = tableLocation; while (true) { final int positionValue = mainOutputPosition.getUnsafe(tableLocation); if (positionValue == EMPTY_OUTPUT_POSITION) { @@ -132,8 +134,8 @@ public int findPositionForKey(Object key) { if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { return positionValue; } - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherLongShort.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherLongShort.java index 78444b07daf..3a3b46f5a8d 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherLongShort.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherLongShort.java @@ -39,7 +39,10 @@ public StaticAggOpenHasherLongShort(ColumnSource[] tableKeySources, int tableSiz this.mainKeySource1.ensureCapacity(tableSize); } - @Override + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final LongChunk keyChunk0 = sourceKeyChunks[0].asLongChunk(); final ShortChunk keyChunk1 = sourceKeyChunks[1].asShortChunk(); @@ -48,25 +51,25 @@ protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final long k0 = keyChunk0.get(chunkPosition); final short k1 = keyChunk1.get(chunkPosition); final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; while (true) { - int tableState = mainOutputPosition.getUnsafe(tableLocation); - if (tableState == EMPTY_OUTPUT_POSITION) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { numEntries++; mainKeySource0.set(tableLocation, k0); mainKeySource1.set(tableLocation, k1); - final int outputPosition = nextOutputPosition.getAndIncrement(); + outputPosition = nextOutputPosition.getAndIncrement(); outputPositions.set(chunkPosition, outputPosition); mainOutputPosition.set(tableLocation, outputPosition); outputPositionToHashSlot.set(outputPosition, tableLocation); break; } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { - outputPositions.set(chunkPosition, tableState); + outputPositions.set(chunkPosition, outputPosition); break; } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } @@ -79,8 +82,7 @@ private static int hash(long k0, short k1) { } @Override - protected void rehashInternal() { - final int oldSize = tableSize >> 1; + protected void rehashInternalFull(final int oldSize) { final long[] destKeyArray0 = new long[tableSize]; final short[] destKeyArray1 = new short[tableSize]; final int[] destState = new int[tableSize]; @@ -92,27 +94,27 @@ protected void rehashInternal() { final int [] originalStateArray = mainOutputPosition.getArray(); mainOutputPosition.setArray(destState); for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { - if (originalStateArray[sourceBucket] == EMPTY_OUTPUT_POSITION) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { continue; } final long k0 = originalKeyArray0[sourceBucket]; final short k1 = originalKeyArray1[sourceBucket]; final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; while (true) { - if (destState[tableLocation] == EMPTY_OUTPUT_POSITION) { - destKeyArray0[tableLocation] = k0; - destKeyArray1[tableLocation] = k1; - destState[tableLocation] = originalStateArray[sourceBucket]; - if (sourceBucket != tableLocation) { - outputPositionToHashSlot.set(destState[tableLocation], tableLocation); + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + if (sourceBucket != destinationTableLocation) { + outputPositionToHashSlot.set(currentStateValue, destinationTableLocation); } break; - } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); } } } @@ -124,7 +126,7 @@ public int findPositionForKey(Object key) { final short k1 = TypeUtils.unbox((Short)ka[1]); int hash = hash(k0, k1); int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = tableLocation; while (true) { final int positionValue = mainOutputPosition.getUnsafe(tableLocation); if (positionValue == EMPTY_OUTPUT_POSITION) { @@ -133,8 +135,8 @@ public int findPositionForKey(Object key) { if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { return positionValue; } - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherObject.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherObject.java index bbeeb8fd703..4cc7163cdec 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherObject.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherObject.java @@ -28,31 +28,34 @@ public StaticAggOpenHasherObject(ColumnSource[] tableKeySources, int tableSize, this.mainKeySource0.ensureCapacity(tableSize); } - @Override + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final ObjectChunk keyChunk0 = sourceKeyChunks[0].asObjectChunk(); final int chunkSize = keyChunk0.size(); for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { final Object k0 = keyChunk0.get(chunkPosition); final int hash = hash(k0); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; while (true) { - int tableState = mainOutputPosition.getUnsafe(tableLocation); - if (tableState == EMPTY_OUTPUT_POSITION) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { numEntries++; mainKeySource0.set(tableLocation, k0); - final int outputPosition = nextOutputPosition.getAndIncrement(); + outputPosition = nextOutputPosition.getAndIncrement(); outputPositions.set(chunkPosition, outputPosition); mainOutputPosition.set(tableLocation, outputPosition); outputPositionToHashSlot.set(outputPosition, tableLocation); break; } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0)) { - outputPositions.set(chunkPosition, tableState); + outputPositions.set(chunkPosition, outputPosition); break; } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } @@ -64,8 +67,7 @@ private static int hash(Object k0) { } @Override - protected void rehashInternal() { - final int oldSize = tableSize >> 1; + protected void rehashInternalFull(final int oldSize) { final Object[] destKeyArray0 = new Object[tableSize]; final int[] destState = new int[tableSize]; Arrays.fill(destState, EMPTY_OUTPUT_POSITION); @@ -74,25 +76,25 @@ protected void rehashInternal() { final int [] originalStateArray = mainOutputPosition.getArray(); mainOutputPosition.setArray(destState); for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { - if (originalStateArray[sourceBucket] == EMPTY_OUTPUT_POSITION) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { continue; } final Object k0 = originalKeyArray0[sourceBucket]; final int hash = hash(k0); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; while (true) { - if (destState[tableLocation] == EMPTY_OUTPUT_POSITION) { - destKeyArray0[tableLocation] = k0; - destState[tableLocation] = originalStateArray[sourceBucket]; - if (sourceBucket != tableLocation) { - outputPositionToHashSlot.set(destState[tableLocation], tableLocation); + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + if (sourceBucket != destinationTableLocation) { + outputPositionToHashSlot.set(currentStateValue, destinationTableLocation); } break; - } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); } } } @@ -102,7 +104,7 @@ public int findPositionForKey(Object key) { final Object k0 = key; int hash = hash(k0); int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = tableLocation; while (true) { final int positionValue = mainOutputPosition.getUnsafe(tableLocation); if (positionValue == EMPTY_OUTPUT_POSITION) { @@ -111,8 +113,8 @@ public int findPositionForKey(Object key) { if (eq(mainKeySource0.getUnsafe(tableLocation), k0)) { return positionValue; } - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherObjectByte.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherObjectByte.java index 4ba2e73cd27..2c68cbb9b03 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherObjectByte.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherObjectByte.java @@ -38,7 +38,10 @@ public StaticAggOpenHasherObjectByte(ColumnSource[] tableKeySources, int tableSi this.mainKeySource1.ensureCapacity(tableSize); } - @Override + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final ObjectChunk keyChunk0 = sourceKeyChunks[0].asObjectChunk(); final ByteChunk keyChunk1 = sourceKeyChunks[1].asByteChunk(); @@ -47,25 +50,25 @@ protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final Object k0 = keyChunk0.get(chunkPosition); final byte k1 = keyChunk1.get(chunkPosition); final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; while (true) { - int tableState = mainOutputPosition.getUnsafe(tableLocation); - if (tableState == EMPTY_OUTPUT_POSITION) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { numEntries++; mainKeySource0.set(tableLocation, k0); mainKeySource1.set(tableLocation, k1); - final int outputPosition = nextOutputPosition.getAndIncrement(); + outputPosition = nextOutputPosition.getAndIncrement(); outputPositions.set(chunkPosition, outputPosition); mainOutputPosition.set(tableLocation, outputPosition); outputPositionToHashSlot.set(outputPosition, tableLocation); break; } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { - outputPositions.set(chunkPosition, tableState); + outputPositions.set(chunkPosition, outputPosition); break; } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } @@ -78,8 +81,7 @@ private static int hash(Object k0, byte k1) { } @Override - protected void rehashInternal() { - final int oldSize = tableSize >> 1; + protected void rehashInternalFull(final int oldSize) { final Object[] destKeyArray0 = new Object[tableSize]; final byte[] destKeyArray1 = new byte[tableSize]; final int[] destState = new int[tableSize]; @@ -91,27 +93,27 @@ protected void rehashInternal() { final int [] originalStateArray = mainOutputPosition.getArray(); mainOutputPosition.setArray(destState); for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { - if (originalStateArray[sourceBucket] == EMPTY_OUTPUT_POSITION) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { continue; } final Object k0 = originalKeyArray0[sourceBucket]; final byte k1 = originalKeyArray1[sourceBucket]; final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; while (true) { - if (destState[tableLocation] == EMPTY_OUTPUT_POSITION) { - destKeyArray0[tableLocation] = k0; - destKeyArray1[tableLocation] = k1; - destState[tableLocation] = originalStateArray[sourceBucket]; - if (sourceBucket != tableLocation) { - outputPositionToHashSlot.set(destState[tableLocation], tableLocation); + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + if (sourceBucket != destinationTableLocation) { + outputPositionToHashSlot.set(currentStateValue, destinationTableLocation); } break; - } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); } } } @@ -123,7 +125,7 @@ public int findPositionForKey(Object key) { final byte k1 = TypeUtils.unbox((Byte)ka[1]); int hash = hash(k0, k1); int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = tableLocation; while (true) { final int positionValue = mainOutputPosition.getUnsafe(tableLocation); if (positionValue == EMPTY_OUTPUT_POSITION) { @@ -132,8 +134,8 @@ public int findPositionForKey(Object key) { if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { return positionValue; } - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherObjectChar.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherObjectChar.java index 90dd5a8e60e..36f82166bcf 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherObjectChar.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherObjectChar.java @@ -38,7 +38,10 @@ public StaticAggOpenHasherObjectChar(ColumnSource[] tableKeySources, int tableSi this.mainKeySource1.ensureCapacity(tableSize); } - @Override + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final ObjectChunk keyChunk0 = sourceKeyChunks[0].asObjectChunk(); final CharChunk keyChunk1 = sourceKeyChunks[1].asCharChunk(); @@ -47,25 +50,25 @@ protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final Object k0 = keyChunk0.get(chunkPosition); final char k1 = keyChunk1.get(chunkPosition); final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; while (true) { - int tableState = mainOutputPosition.getUnsafe(tableLocation); - if (tableState == EMPTY_OUTPUT_POSITION) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { numEntries++; mainKeySource0.set(tableLocation, k0); mainKeySource1.set(tableLocation, k1); - final int outputPosition = nextOutputPosition.getAndIncrement(); + outputPosition = nextOutputPosition.getAndIncrement(); outputPositions.set(chunkPosition, outputPosition); mainOutputPosition.set(tableLocation, outputPosition); outputPositionToHashSlot.set(outputPosition, tableLocation); break; } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { - outputPositions.set(chunkPosition, tableState); + outputPositions.set(chunkPosition, outputPosition); break; } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } @@ -78,8 +81,7 @@ private static int hash(Object k0, char k1) { } @Override - protected void rehashInternal() { - final int oldSize = tableSize >> 1; + protected void rehashInternalFull(final int oldSize) { final Object[] destKeyArray0 = new Object[tableSize]; final char[] destKeyArray1 = new char[tableSize]; final int[] destState = new int[tableSize]; @@ -91,27 +93,27 @@ protected void rehashInternal() { final int [] originalStateArray = mainOutputPosition.getArray(); mainOutputPosition.setArray(destState); for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { - if (originalStateArray[sourceBucket] == EMPTY_OUTPUT_POSITION) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { continue; } final Object k0 = originalKeyArray0[sourceBucket]; final char k1 = originalKeyArray1[sourceBucket]; final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; while (true) { - if (destState[tableLocation] == EMPTY_OUTPUT_POSITION) { - destKeyArray0[tableLocation] = k0; - destKeyArray1[tableLocation] = k1; - destState[tableLocation] = originalStateArray[sourceBucket]; - if (sourceBucket != tableLocation) { - outputPositionToHashSlot.set(destState[tableLocation], tableLocation); + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + if (sourceBucket != destinationTableLocation) { + outputPositionToHashSlot.set(currentStateValue, destinationTableLocation); } break; - } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); } } } @@ -123,7 +125,7 @@ public int findPositionForKey(Object key) { final char k1 = TypeUtils.unbox((Character)ka[1]); int hash = hash(k0, k1); int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = tableLocation; while (true) { final int positionValue = mainOutputPosition.getUnsafe(tableLocation); if (positionValue == EMPTY_OUTPUT_POSITION) { @@ -132,8 +134,8 @@ public int findPositionForKey(Object key) { if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { return positionValue; } - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherObjectDouble.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherObjectDouble.java index 4d742faa849..e6faf9def1b 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherObjectDouble.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherObjectDouble.java @@ -38,7 +38,10 @@ public StaticAggOpenHasherObjectDouble(ColumnSource[] tableKeySources, int table this.mainKeySource1.ensureCapacity(tableSize); } - @Override + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final ObjectChunk keyChunk0 = sourceKeyChunks[0].asObjectChunk(); final DoubleChunk keyChunk1 = sourceKeyChunks[1].asDoubleChunk(); @@ -47,25 +50,25 @@ protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final Object k0 = keyChunk0.get(chunkPosition); final double k1 = keyChunk1.get(chunkPosition); final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; while (true) { - int tableState = mainOutputPosition.getUnsafe(tableLocation); - if (tableState == EMPTY_OUTPUT_POSITION) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { numEntries++; mainKeySource0.set(tableLocation, k0); mainKeySource1.set(tableLocation, k1); - final int outputPosition = nextOutputPosition.getAndIncrement(); + outputPosition = nextOutputPosition.getAndIncrement(); outputPositions.set(chunkPosition, outputPosition); mainOutputPosition.set(tableLocation, outputPosition); outputPositionToHashSlot.set(outputPosition, tableLocation); break; } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { - outputPositions.set(chunkPosition, tableState); + outputPositions.set(chunkPosition, outputPosition); break; } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } @@ -78,8 +81,7 @@ private static int hash(Object k0, double k1) { } @Override - protected void rehashInternal() { - final int oldSize = tableSize >> 1; + protected void rehashInternalFull(final int oldSize) { final Object[] destKeyArray0 = new Object[tableSize]; final double[] destKeyArray1 = new double[tableSize]; final int[] destState = new int[tableSize]; @@ -91,27 +93,27 @@ protected void rehashInternal() { final int [] originalStateArray = mainOutputPosition.getArray(); mainOutputPosition.setArray(destState); for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { - if (originalStateArray[sourceBucket] == EMPTY_OUTPUT_POSITION) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { continue; } final Object k0 = originalKeyArray0[sourceBucket]; final double k1 = originalKeyArray1[sourceBucket]; final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; while (true) { - if (destState[tableLocation] == EMPTY_OUTPUT_POSITION) { - destKeyArray0[tableLocation] = k0; - destKeyArray1[tableLocation] = k1; - destState[tableLocation] = originalStateArray[sourceBucket]; - if (sourceBucket != tableLocation) { - outputPositionToHashSlot.set(destState[tableLocation], tableLocation); + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + if (sourceBucket != destinationTableLocation) { + outputPositionToHashSlot.set(currentStateValue, destinationTableLocation); } break; - } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); } } } @@ -123,7 +125,7 @@ public int findPositionForKey(Object key) { final double k1 = TypeUtils.unbox((Double)ka[1]); int hash = hash(k0, k1); int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = tableLocation; while (true) { final int positionValue = mainOutputPosition.getUnsafe(tableLocation); if (positionValue == EMPTY_OUTPUT_POSITION) { @@ -132,8 +134,8 @@ public int findPositionForKey(Object key) { if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { return positionValue; } - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherObjectFloat.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherObjectFloat.java index fb709a2dfc2..c6ec8f39156 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherObjectFloat.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherObjectFloat.java @@ -38,7 +38,10 @@ public StaticAggOpenHasherObjectFloat(ColumnSource[] tableKeySources, int tableS this.mainKeySource1.ensureCapacity(tableSize); } - @Override + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final ObjectChunk keyChunk0 = sourceKeyChunks[0].asObjectChunk(); final FloatChunk keyChunk1 = sourceKeyChunks[1].asFloatChunk(); @@ -47,25 +50,25 @@ protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final Object k0 = keyChunk0.get(chunkPosition); final float k1 = keyChunk1.get(chunkPosition); final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; while (true) { - int tableState = mainOutputPosition.getUnsafe(tableLocation); - if (tableState == EMPTY_OUTPUT_POSITION) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { numEntries++; mainKeySource0.set(tableLocation, k0); mainKeySource1.set(tableLocation, k1); - final int outputPosition = nextOutputPosition.getAndIncrement(); + outputPosition = nextOutputPosition.getAndIncrement(); outputPositions.set(chunkPosition, outputPosition); mainOutputPosition.set(tableLocation, outputPosition); outputPositionToHashSlot.set(outputPosition, tableLocation); break; } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { - outputPositions.set(chunkPosition, tableState); + outputPositions.set(chunkPosition, outputPosition); break; } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } @@ -78,8 +81,7 @@ private static int hash(Object k0, float k1) { } @Override - protected void rehashInternal() { - final int oldSize = tableSize >> 1; + protected void rehashInternalFull(final int oldSize) { final Object[] destKeyArray0 = new Object[tableSize]; final float[] destKeyArray1 = new float[tableSize]; final int[] destState = new int[tableSize]; @@ -91,27 +93,27 @@ protected void rehashInternal() { final int [] originalStateArray = mainOutputPosition.getArray(); mainOutputPosition.setArray(destState); for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { - if (originalStateArray[sourceBucket] == EMPTY_OUTPUT_POSITION) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { continue; } final Object k0 = originalKeyArray0[sourceBucket]; final float k1 = originalKeyArray1[sourceBucket]; final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; while (true) { - if (destState[tableLocation] == EMPTY_OUTPUT_POSITION) { - destKeyArray0[tableLocation] = k0; - destKeyArray1[tableLocation] = k1; - destState[tableLocation] = originalStateArray[sourceBucket]; - if (sourceBucket != tableLocation) { - outputPositionToHashSlot.set(destState[tableLocation], tableLocation); + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + if (sourceBucket != destinationTableLocation) { + outputPositionToHashSlot.set(currentStateValue, destinationTableLocation); } break; - } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); } } } @@ -123,7 +125,7 @@ public int findPositionForKey(Object key) { final float k1 = TypeUtils.unbox((Float)ka[1]); int hash = hash(k0, k1); int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = tableLocation; while (true) { final int positionValue = mainOutputPosition.getUnsafe(tableLocation); if (positionValue == EMPTY_OUTPUT_POSITION) { @@ -132,8 +134,8 @@ public int findPositionForKey(Object key) { if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { return positionValue; } - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherObjectInt.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherObjectInt.java index 2540402c985..0faa13acf62 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherObjectInt.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherObjectInt.java @@ -38,7 +38,10 @@ public StaticAggOpenHasherObjectInt(ColumnSource[] tableKeySources, int tableSiz this.mainKeySource1.ensureCapacity(tableSize); } - @Override + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final ObjectChunk keyChunk0 = sourceKeyChunks[0].asObjectChunk(); final IntChunk keyChunk1 = sourceKeyChunks[1].asIntChunk(); @@ -47,25 +50,25 @@ protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final Object k0 = keyChunk0.get(chunkPosition); final int k1 = keyChunk1.get(chunkPosition); final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; while (true) { - int tableState = mainOutputPosition.getUnsafe(tableLocation); - if (tableState == EMPTY_OUTPUT_POSITION) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { numEntries++; mainKeySource0.set(tableLocation, k0); mainKeySource1.set(tableLocation, k1); - final int outputPosition = nextOutputPosition.getAndIncrement(); + outputPosition = nextOutputPosition.getAndIncrement(); outputPositions.set(chunkPosition, outputPosition); mainOutputPosition.set(tableLocation, outputPosition); outputPositionToHashSlot.set(outputPosition, tableLocation); break; } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { - outputPositions.set(chunkPosition, tableState); + outputPositions.set(chunkPosition, outputPosition); break; } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } @@ -78,8 +81,7 @@ private static int hash(Object k0, int k1) { } @Override - protected void rehashInternal() { - final int oldSize = tableSize >> 1; + protected void rehashInternalFull(final int oldSize) { final Object[] destKeyArray0 = new Object[tableSize]; final int[] destKeyArray1 = new int[tableSize]; final int[] destState = new int[tableSize]; @@ -91,27 +93,27 @@ protected void rehashInternal() { final int [] originalStateArray = mainOutputPosition.getArray(); mainOutputPosition.setArray(destState); for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { - if (originalStateArray[sourceBucket] == EMPTY_OUTPUT_POSITION) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { continue; } final Object k0 = originalKeyArray0[sourceBucket]; final int k1 = originalKeyArray1[sourceBucket]; final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; while (true) { - if (destState[tableLocation] == EMPTY_OUTPUT_POSITION) { - destKeyArray0[tableLocation] = k0; - destKeyArray1[tableLocation] = k1; - destState[tableLocation] = originalStateArray[sourceBucket]; - if (sourceBucket != tableLocation) { - outputPositionToHashSlot.set(destState[tableLocation], tableLocation); + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + if (sourceBucket != destinationTableLocation) { + outputPositionToHashSlot.set(currentStateValue, destinationTableLocation); } break; - } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); } } } @@ -123,7 +125,7 @@ public int findPositionForKey(Object key) { final int k1 = TypeUtils.unbox((Integer)ka[1]); int hash = hash(k0, k1); int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = tableLocation; while (true) { final int positionValue = mainOutputPosition.getUnsafe(tableLocation); if (positionValue == EMPTY_OUTPUT_POSITION) { @@ -132,8 +134,8 @@ public int findPositionForKey(Object key) { if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { return positionValue; } - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherObjectLong.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherObjectLong.java index 4769de42e6d..20f799b8101 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherObjectLong.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherObjectLong.java @@ -38,7 +38,10 @@ public StaticAggOpenHasherObjectLong(ColumnSource[] tableKeySources, int tableSi this.mainKeySource1.ensureCapacity(tableSize); } - @Override + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final ObjectChunk keyChunk0 = sourceKeyChunks[0].asObjectChunk(); final LongChunk keyChunk1 = sourceKeyChunks[1].asLongChunk(); @@ -47,25 +50,25 @@ protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final Object k0 = keyChunk0.get(chunkPosition); final long k1 = keyChunk1.get(chunkPosition); final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; while (true) { - int tableState = mainOutputPosition.getUnsafe(tableLocation); - if (tableState == EMPTY_OUTPUT_POSITION) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { numEntries++; mainKeySource0.set(tableLocation, k0); mainKeySource1.set(tableLocation, k1); - final int outputPosition = nextOutputPosition.getAndIncrement(); + outputPosition = nextOutputPosition.getAndIncrement(); outputPositions.set(chunkPosition, outputPosition); mainOutputPosition.set(tableLocation, outputPosition); outputPositionToHashSlot.set(outputPosition, tableLocation); break; } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { - outputPositions.set(chunkPosition, tableState); + outputPositions.set(chunkPosition, outputPosition); break; } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } @@ -78,8 +81,7 @@ private static int hash(Object k0, long k1) { } @Override - protected void rehashInternal() { - final int oldSize = tableSize >> 1; + protected void rehashInternalFull(final int oldSize) { final Object[] destKeyArray0 = new Object[tableSize]; final long[] destKeyArray1 = new long[tableSize]; final int[] destState = new int[tableSize]; @@ -91,27 +93,27 @@ protected void rehashInternal() { final int [] originalStateArray = mainOutputPosition.getArray(); mainOutputPosition.setArray(destState); for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { - if (originalStateArray[sourceBucket] == EMPTY_OUTPUT_POSITION) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { continue; } final Object k0 = originalKeyArray0[sourceBucket]; final long k1 = originalKeyArray1[sourceBucket]; final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; while (true) { - if (destState[tableLocation] == EMPTY_OUTPUT_POSITION) { - destKeyArray0[tableLocation] = k0; - destKeyArray1[tableLocation] = k1; - destState[tableLocation] = originalStateArray[sourceBucket]; - if (sourceBucket != tableLocation) { - outputPositionToHashSlot.set(destState[tableLocation], tableLocation); + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + if (sourceBucket != destinationTableLocation) { + outputPositionToHashSlot.set(currentStateValue, destinationTableLocation); } break; - } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); } } } @@ -123,7 +125,7 @@ public int findPositionForKey(Object key) { final long k1 = TypeUtils.unbox((Long)ka[1]); int hash = hash(k0, k1); int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = tableLocation; while (true) { final int positionValue = mainOutputPosition.getUnsafe(tableLocation); if (positionValue == EMPTY_OUTPUT_POSITION) { @@ -132,8 +134,8 @@ public int findPositionForKey(Object key) { if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { return positionValue; } - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherObjectObject.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherObjectObject.java index 321f5ac8e8b..39418090ac3 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherObjectObject.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherObjectObject.java @@ -32,7 +32,10 @@ public StaticAggOpenHasherObjectObject(ColumnSource[] tableKeySources, int table this.mainKeySource1.ensureCapacity(tableSize); } - @Override + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final ObjectChunk keyChunk0 = sourceKeyChunks[0].asObjectChunk(); final ObjectChunk keyChunk1 = sourceKeyChunks[1].asObjectChunk(); @@ -41,25 +44,25 @@ protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final Object k0 = keyChunk0.get(chunkPosition); final Object k1 = keyChunk1.get(chunkPosition); final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; while (true) { - int tableState = mainOutputPosition.getUnsafe(tableLocation); - if (tableState == EMPTY_OUTPUT_POSITION) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { numEntries++; mainKeySource0.set(tableLocation, k0); mainKeySource1.set(tableLocation, k1); - final int outputPosition = nextOutputPosition.getAndIncrement(); + outputPosition = nextOutputPosition.getAndIncrement(); outputPositions.set(chunkPosition, outputPosition); mainOutputPosition.set(tableLocation, outputPosition); outputPositionToHashSlot.set(outputPosition, tableLocation); break; } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { - outputPositions.set(chunkPosition, tableState); + outputPositions.set(chunkPosition, outputPosition); break; } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } @@ -72,8 +75,7 @@ private static int hash(Object k0, Object k1) { } @Override - protected void rehashInternal() { - final int oldSize = tableSize >> 1; + protected void rehashInternalFull(final int oldSize) { final Object[] destKeyArray0 = new Object[tableSize]; final Object[] destKeyArray1 = new Object[tableSize]; final int[] destState = new int[tableSize]; @@ -85,27 +87,27 @@ protected void rehashInternal() { final int [] originalStateArray = mainOutputPosition.getArray(); mainOutputPosition.setArray(destState); for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { - if (originalStateArray[sourceBucket] == EMPTY_OUTPUT_POSITION) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { continue; } final Object k0 = originalKeyArray0[sourceBucket]; final Object k1 = originalKeyArray1[sourceBucket]; final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; while (true) { - if (destState[tableLocation] == EMPTY_OUTPUT_POSITION) { - destKeyArray0[tableLocation] = k0; - destKeyArray1[tableLocation] = k1; - destState[tableLocation] = originalStateArray[sourceBucket]; - if (sourceBucket != tableLocation) { - outputPositionToHashSlot.set(destState[tableLocation], tableLocation); + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + if (sourceBucket != destinationTableLocation) { + outputPositionToHashSlot.set(currentStateValue, destinationTableLocation); } break; - } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); } } } @@ -117,7 +119,7 @@ public int findPositionForKey(Object key) { final Object k1 = ka[1]; int hash = hash(k0, k1); int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = tableLocation; while (true) { final int positionValue = mainOutputPosition.getUnsafe(tableLocation); if (positionValue == EMPTY_OUTPUT_POSITION) { @@ -126,8 +128,8 @@ public int findPositionForKey(Object key) { if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { return positionValue; } - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherObjectShort.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherObjectShort.java index f5f51978170..49848766840 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherObjectShort.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherObjectShort.java @@ -38,7 +38,10 @@ public StaticAggOpenHasherObjectShort(ColumnSource[] tableKeySources, int tableS this.mainKeySource1.ensureCapacity(tableSize); } - @Override + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final ObjectChunk keyChunk0 = sourceKeyChunks[0].asObjectChunk(); final ShortChunk keyChunk1 = sourceKeyChunks[1].asShortChunk(); @@ -47,25 +50,25 @@ protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final Object k0 = keyChunk0.get(chunkPosition); final short k1 = keyChunk1.get(chunkPosition); final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; while (true) { - int tableState = mainOutputPosition.getUnsafe(tableLocation); - if (tableState == EMPTY_OUTPUT_POSITION) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { numEntries++; mainKeySource0.set(tableLocation, k0); mainKeySource1.set(tableLocation, k1); - final int outputPosition = nextOutputPosition.getAndIncrement(); + outputPosition = nextOutputPosition.getAndIncrement(); outputPositions.set(chunkPosition, outputPosition); mainOutputPosition.set(tableLocation, outputPosition); outputPositionToHashSlot.set(outputPosition, tableLocation); break; } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { - outputPositions.set(chunkPosition, tableState); + outputPositions.set(chunkPosition, outputPosition); break; } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } @@ -78,8 +81,7 @@ private static int hash(Object k0, short k1) { } @Override - protected void rehashInternal() { - final int oldSize = tableSize >> 1; + protected void rehashInternalFull(final int oldSize) { final Object[] destKeyArray0 = new Object[tableSize]; final short[] destKeyArray1 = new short[tableSize]; final int[] destState = new int[tableSize]; @@ -91,27 +93,27 @@ protected void rehashInternal() { final int [] originalStateArray = mainOutputPosition.getArray(); mainOutputPosition.setArray(destState); for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { - if (originalStateArray[sourceBucket] == EMPTY_OUTPUT_POSITION) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { continue; } final Object k0 = originalKeyArray0[sourceBucket]; final short k1 = originalKeyArray1[sourceBucket]; final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; while (true) { - if (destState[tableLocation] == EMPTY_OUTPUT_POSITION) { - destKeyArray0[tableLocation] = k0; - destKeyArray1[tableLocation] = k1; - destState[tableLocation] = originalStateArray[sourceBucket]; - if (sourceBucket != tableLocation) { - outputPositionToHashSlot.set(destState[tableLocation], tableLocation); + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + if (sourceBucket != destinationTableLocation) { + outputPositionToHashSlot.set(currentStateValue, destinationTableLocation); } break; - } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); } } } @@ -123,7 +125,7 @@ public int findPositionForKey(Object key) { final short k1 = TypeUtils.unbox((Short)ka[1]); int hash = hash(k0, k1); int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = tableLocation; while (true) { final int positionValue = mainOutputPosition.getUnsafe(tableLocation); if (positionValue == EMPTY_OUTPUT_POSITION) { @@ -132,8 +134,8 @@ public int findPositionForKey(Object key) { if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { return positionValue; } - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherShort.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherShort.java index 311c1a9aaaa..875d60c296f 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherShort.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherShort.java @@ -30,31 +30,34 @@ public StaticAggOpenHasherShort(ColumnSource[] tableKeySources, int tableSize, this.mainKeySource0.ensureCapacity(tableSize); } - @Override + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final ShortChunk keyChunk0 = sourceKeyChunks[0].asShortChunk(); final int chunkSize = keyChunk0.size(); for (int chunkPosition = 0; chunkPosition < chunkSize; ++chunkPosition) { final short k0 = keyChunk0.get(chunkPosition); final int hash = hash(k0); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; while (true) { - int tableState = mainOutputPosition.getUnsafe(tableLocation); - if (tableState == EMPTY_OUTPUT_POSITION) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { numEntries++; mainKeySource0.set(tableLocation, k0); - final int outputPosition = nextOutputPosition.getAndIncrement(); + outputPosition = nextOutputPosition.getAndIncrement(); outputPositions.set(chunkPosition, outputPosition); mainOutputPosition.set(tableLocation, outputPosition); outputPositionToHashSlot.set(outputPosition, tableLocation); break; } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0)) { - outputPositions.set(chunkPosition, tableState); + outputPositions.set(chunkPosition, outputPosition); break; } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } @@ -66,8 +69,7 @@ private static int hash(short k0) { } @Override - protected void rehashInternal() { - final int oldSize = tableSize >> 1; + protected void rehashInternalFull(final int oldSize) { final short[] destKeyArray0 = new short[tableSize]; final int[] destState = new int[tableSize]; Arrays.fill(destState, EMPTY_OUTPUT_POSITION); @@ -76,25 +78,25 @@ protected void rehashInternal() { final int [] originalStateArray = mainOutputPosition.getArray(); mainOutputPosition.setArray(destState); for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { - if (originalStateArray[sourceBucket] == EMPTY_OUTPUT_POSITION) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { continue; } final short k0 = originalKeyArray0[sourceBucket]; final int hash = hash(k0); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; while (true) { - if (destState[tableLocation] == EMPTY_OUTPUT_POSITION) { - destKeyArray0[tableLocation] = k0; - destState[tableLocation] = originalStateArray[sourceBucket]; - if (sourceBucket != tableLocation) { - outputPositionToHashSlot.set(destState[tableLocation], tableLocation); + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + if (sourceBucket != destinationTableLocation) { + outputPositionToHashSlot.set(currentStateValue, destinationTableLocation); } break; - } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); } } } @@ -104,7 +106,7 @@ public int findPositionForKey(Object key) { final short k0 = TypeUtils.unbox((Short)key); int hash = hash(k0); int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = tableLocation; while (true) { final int positionValue = mainOutputPosition.getUnsafe(tableLocation); if (positionValue == EMPTY_OUTPUT_POSITION) { @@ -113,8 +115,8 @@ public int findPositionForKey(Object key) { if (eq(mainKeySource0.getUnsafe(tableLocation), k0)) { return positionValue; } - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherShortByte.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherShortByte.java index 3070196d4db..db8bc7fb72a 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherShortByte.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherShortByte.java @@ -39,7 +39,10 @@ public StaticAggOpenHasherShortByte(ColumnSource[] tableKeySources, int tableSiz this.mainKeySource1.ensureCapacity(tableSize); } - @Override + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final ShortChunk keyChunk0 = sourceKeyChunks[0].asShortChunk(); final ByteChunk keyChunk1 = sourceKeyChunks[1].asByteChunk(); @@ -48,25 +51,25 @@ protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final short k0 = keyChunk0.get(chunkPosition); final byte k1 = keyChunk1.get(chunkPosition); final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; while (true) { - int tableState = mainOutputPosition.getUnsafe(tableLocation); - if (tableState == EMPTY_OUTPUT_POSITION) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { numEntries++; mainKeySource0.set(tableLocation, k0); mainKeySource1.set(tableLocation, k1); - final int outputPosition = nextOutputPosition.getAndIncrement(); + outputPosition = nextOutputPosition.getAndIncrement(); outputPositions.set(chunkPosition, outputPosition); mainOutputPosition.set(tableLocation, outputPosition); outputPositionToHashSlot.set(outputPosition, tableLocation); break; } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { - outputPositions.set(chunkPosition, tableState); + outputPositions.set(chunkPosition, outputPosition); break; } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } @@ -79,8 +82,7 @@ private static int hash(short k0, byte k1) { } @Override - protected void rehashInternal() { - final int oldSize = tableSize >> 1; + protected void rehashInternalFull(final int oldSize) { final short[] destKeyArray0 = new short[tableSize]; final byte[] destKeyArray1 = new byte[tableSize]; final int[] destState = new int[tableSize]; @@ -92,27 +94,27 @@ protected void rehashInternal() { final int [] originalStateArray = mainOutputPosition.getArray(); mainOutputPosition.setArray(destState); for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { - if (originalStateArray[sourceBucket] == EMPTY_OUTPUT_POSITION) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { continue; } final short k0 = originalKeyArray0[sourceBucket]; final byte k1 = originalKeyArray1[sourceBucket]; final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; while (true) { - if (destState[tableLocation] == EMPTY_OUTPUT_POSITION) { - destKeyArray0[tableLocation] = k0; - destKeyArray1[tableLocation] = k1; - destState[tableLocation] = originalStateArray[sourceBucket]; - if (sourceBucket != tableLocation) { - outputPositionToHashSlot.set(destState[tableLocation], tableLocation); + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + if (sourceBucket != destinationTableLocation) { + outputPositionToHashSlot.set(currentStateValue, destinationTableLocation); } break; - } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); } } } @@ -124,7 +126,7 @@ public int findPositionForKey(Object key) { final byte k1 = TypeUtils.unbox((Byte)ka[1]); int hash = hash(k0, k1); int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = tableLocation; while (true) { final int positionValue = mainOutputPosition.getUnsafe(tableLocation); if (positionValue == EMPTY_OUTPUT_POSITION) { @@ -133,8 +135,8 @@ public int findPositionForKey(Object key) { if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { return positionValue; } - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherShortChar.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherShortChar.java index cdab7434c8f..5d156c969d3 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherShortChar.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherShortChar.java @@ -39,7 +39,10 @@ public StaticAggOpenHasherShortChar(ColumnSource[] tableKeySources, int tableSiz this.mainKeySource1.ensureCapacity(tableSize); } - @Override + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final ShortChunk keyChunk0 = sourceKeyChunks[0].asShortChunk(); final CharChunk keyChunk1 = sourceKeyChunks[1].asCharChunk(); @@ -48,25 +51,25 @@ protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final short k0 = keyChunk0.get(chunkPosition); final char k1 = keyChunk1.get(chunkPosition); final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; while (true) { - int tableState = mainOutputPosition.getUnsafe(tableLocation); - if (tableState == EMPTY_OUTPUT_POSITION) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { numEntries++; mainKeySource0.set(tableLocation, k0); mainKeySource1.set(tableLocation, k1); - final int outputPosition = nextOutputPosition.getAndIncrement(); + outputPosition = nextOutputPosition.getAndIncrement(); outputPositions.set(chunkPosition, outputPosition); mainOutputPosition.set(tableLocation, outputPosition); outputPositionToHashSlot.set(outputPosition, tableLocation); break; } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { - outputPositions.set(chunkPosition, tableState); + outputPositions.set(chunkPosition, outputPosition); break; } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } @@ -79,8 +82,7 @@ private static int hash(short k0, char k1) { } @Override - protected void rehashInternal() { - final int oldSize = tableSize >> 1; + protected void rehashInternalFull(final int oldSize) { final short[] destKeyArray0 = new short[tableSize]; final char[] destKeyArray1 = new char[tableSize]; final int[] destState = new int[tableSize]; @@ -92,27 +94,27 @@ protected void rehashInternal() { final int [] originalStateArray = mainOutputPosition.getArray(); mainOutputPosition.setArray(destState); for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { - if (originalStateArray[sourceBucket] == EMPTY_OUTPUT_POSITION) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { continue; } final short k0 = originalKeyArray0[sourceBucket]; final char k1 = originalKeyArray1[sourceBucket]; final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; while (true) { - if (destState[tableLocation] == EMPTY_OUTPUT_POSITION) { - destKeyArray0[tableLocation] = k0; - destKeyArray1[tableLocation] = k1; - destState[tableLocation] = originalStateArray[sourceBucket]; - if (sourceBucket != tableLocation) { - outputPositionToHashSlot.set(destState[tableLocation], tableLocation); + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + if (sourceBucket != destinationTableLocation) { + outputPositionToHashSlot.set(currentStateValue, destinationTableLocation); } break; - } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); } } } @@ -124,7 +126,7 @@ public int findPositionForKey(Object key) { final char k1 = TypeUtils.unbox((Character)ka[1]); int hash = hash(k0, k1); int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = tableLocation; while (true) { final int positionValue = mainOutputPosition.getUnsafe(tableLocation); if (positionValue == EMPTY_OUTPUT_POSITION) { @@ -133,8 +135,8 @@ public int findPositionForKey(Object key) { if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { return positionValue; } - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherShortDouble.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherShortDouble.java index b388b40a98c..8594b53e7d7 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherShortDouble.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherShortDouble.java @@ -39,7 +39,10 @@ public StaticAggOpenHasherShortDouble(ColumnSource[] tableKeySources, int tableS this.mainKeySource1.ensureCapacity(tableSize); } - @Override + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final ShortChunk keyChunk0 = sourceKeyChunks[0].asShortChunk(); final DoubleChunk keyChunk1 = sourceKeyChunks[1].asDoubleChunk(); @@ -48,25 +51,25 @@ protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final short k0 = keyChunk0.get(chunkPosition); final double k1 = keyChunk1.get(chunkPosition); final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; while (true) { - int tableState = mainOutputPosition.getUnsafe(tableLocation); - if (tableState == EMPTY_OUTPUT_POSITION) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { numEntries++; mainKeySource0.set(tableLocation, k0); mainKeySource1.set(tableLocation, k1); - final int outputPosition = nextOutputPosition.getAndIncrement(); + outputPosition = nextOutputPosition.getAndIncrement(); outputPositions.set(chunkPosition, outputPosition); mainOutputPosition.set(tableLocation, outputPosition); outputPositionToHashSlot.set(outputPosition, tableLocation); break; } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { - outputPositions.set(chunkPosition, tableState); + outputPositions.set(chunkPosition, outputPosition); break; } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } @@ -79,8 +82,7 @@ private static int hash(short k0, double k1) { } @Override - protected void rehashInternal() { - final int oldSize = tableSize >> 1; + protected void rehashInternalFull(final int oldSize) { final short[] destKeyArray0 = new short[tableSize]; final double[] destKeyArray1 = new double[tableSize]; final int[] destState = new int[tableSize]; @@ -92,27 +94,27 @@ protected void rehashInternal() { final int [] originalStateArray = mainOutputPosition.getArray(); mainOutputPosition.setArray(destState); for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { - if (originalStateArray[sourceBucket] == EMPTY_OUTPUT_POSITION) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { continue; } final short k0 = originalKeyArray0[sourceBucket]; final double k1 = originalKeyArray1[sourceBucket]; final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; while (true) { - if (destState[tableLocation] == EMPTY_OUTPUT_POSITION) { - destKeyArray0[tableLocation] = k0; - destKeyArray1[tableLocation] = k1; - destState[tableLocation] = originalStateArray[sourceBucket]; - if (sourceBucket != tableLocation) { - outputPositionToHashSlot.set(destState[tableLocation], tableLocation); + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + if (sourceBucket != destinationTableLocation) { + outputPositionToHashSlot.set(currentStateValue, destinationTableLocation); } break; - } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); } } } @@ -124,7 +126,7 @@ public int findPositionForKey(Object key) { final double k1 = TypeUtils.unbox((Double)ka[1]); int hash = hash(k0, k1); int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = tableLocation; while (true) { final int positionValue = mainOutputPosition.getUnsafe(tableLocation); if (positionValue == EMPTY_OUTPUT_POSITION) { @@ -133,8 +135,8 @@ public int findPositionForKey(Object key) { if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { return positionValue; } - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherShortFloat.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherShortFloat.java index 966a5705d97..b0e4085b843 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherShortFloat.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherShortFloat.java @@ -39,7 +39,10 @@ public StaticAggOpenHasherShortFloat(ColumnSource[] tableKeySources, int tableSi this.mainKeySource1.ensureCapacity(tableSize); } - @Override + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final ShortChunk keyChunk0 = sourceKeyChunks[0].asShortChunk(); final FloatChunk keyChunk1 = sourceKeyChunks[1].asFloatChunk(); @@ -48,25 +51,25 @@ protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final short k0 = keyChunk0.get(chunkPosition); final float k1 = keyChunk1.get(chunkPosition); final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; while (true) { - int tableState = mainOutputPosition.getUnsafe(tableLocation); - if (tableState == EMPTY_OUTPUT_POSITION) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { numEntries++; mainKeySource0.set(tableLocation, k0); mainKeySource1.set(tableLocation, k1); - final int outputPosition = nextOutputPosition.getAndIncrement(); + outputPosition = nextOutputPosition.getAndIncrement(); outputPositions.set(chunkPosition, outputPosition); mainOutputPosition.set(tableLocation, outputPosition); outputPositionToHashSlot.set(outputPosition, tableLocation); break; } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { - outputPositions.set(chunkPosition, tableState); + outputPositions.set(chunkPosition, outputPosition); break; } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } @@ -79,8 +82,7 @@ private static int hash(short k0, float k1) { } @Override - protected void rehashInternal() { - final int oldSize = tableSize >> 1; + protected void rehashInternalFull(final int oldSize) { final short[] destKeyArray0 = new short[tableSize]; final float[] destKeyArray1 = new float[tableSize]; final int[] destState = new int[tableSize]; @@ -92,27 +94,27 @@ protected void rehashInternal() { final int [] originalStateArray = mainOutputPosition.getArray(); mainOutputPosition.setArray(destState); for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { - if (originalStateArray[sourceBucket] == EMPTY_OUTPUT_POSITION) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { continue; } final short k0 = originalKeyArray0[sourceBucket]; final float k1 = originalKeyArray1[sourceBucket]; final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; while (true) { - if (destState[tableLocation] == EMPTY_OUTPUT_POSITION) { - destKeyArray0[tableLocation] = k0; - destKeyArray1[tableLocation] = k1; - destState[tableLocation] = originalStateArray[sourceBucket]; - if (sourceBucket != tableLocation) { - outputPositionToHashSlot.set(destState[tableLocation], tableLocation); + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + if (sourceBucket != destinationTableLocation) { + outputPositionToHashSlot.set(currentStateValue, destinationTableLocation); } break; - } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); } } } @@ -124,7 +126,7 @@ public int findPositionForKey(Object key) { final float k1 = TypeUtils.unbox((Float)ka[1]); int hash = hash(k0, k1); int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = tableLocation; while (true) { final int positionValue = mainOutputPosition.getUnsafe(tableLocation); if (positionValue == EMPTY_OUTPUT_POSITION) { @@ -133,8 +135,8 @@ public int findPositionForKey(Object key) { if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { return positionValue; } - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherShortInt.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherShortInt.java index 370e45f6207..dc4ead1d67e 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherShortInt.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherShortInt.java @@ -39,7 +39,10 @@ public StaticAggOpenHasherShortInt(ColumnSource[] tableKeySources, int tableSize this.mainKeySource1.ensureCapacity(tableSize); } - @Override + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final ShortChunk keyChunk0 = sourceKeyChunks[0].asShortChunk(); final IntChunk keyChunk1 = sourceKeyChunks[1].asIntChunk(); @@ -48,25 +51,25 @@ protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final short k0 = keyChunk0.get(chunkPosition); final int k1 = keyChunk1.get(chunkPosition); final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; while (true) { - int tableState = mainOutputPosition.getUnsafe(tableLocation); - if (tableState == EMPTY_OUTPUT_POSITION) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { numEntries++; mainKeySource0.set(tableLocation, k0); mainKeySource1.set(tableLocation, k1); - final int outputPosition = nextOutputPosition.getAndIncrement(); + outputPosition = nextOutputPosition.getAndIncrement(); outputPositions.set(chunkPosition, outputPosition); mainOutputPosition.set(tableLocation, outputPosition); outputPositionToHashSlot.set(outputPosition, tableLocation); break; } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { - outputPositions.set(chunkPosition, tableState); + outputPositions.set(chunkPosition, outputPosition); break; } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } @@ -79,8 +82,7 @@ private static int hash(short k0, int k1) { } @Override - protected void rehashInternal() { - final int oldSize = tableSize >> 1; + protected void rehashInternalFull(final int oldSize) { final short[] destKeyArray0 = new short[tableSize]; final int[] destKeyArray1 = new int[tableSize]; final int[] destState = new int[tableSize]; @@ -92,27 +94,27 @@ protected void rehashInternal() { final int [] originalStateArray = mainOutputPosition.getArray(); mainOutputPosition.setArray(destState); for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { - if (originalStateArray[sourceBucket] == EMPTY_OUTPUT_POSITION) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { continue; } final short k0 = originalKeyArray0[sourceBucket]; final int k1 = originalKeyArray1[sourceBucket]; final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; while (true) { - if (destState[tableLocation] == EMPTY_OUTPUT_POSITION) { - destKeyArray0[tableLocation] = k0; - destKeyArray1[tableLocation] = k1; - destState[tableLocation] = originalStateArray[sourceBucket]; - if (sourceBucket != tableLocation) { - outputPositionToHashSlot.set(destState[tableLocation], tableLocation); + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + if (sourceBucket != destinationTableLocation) { + outputPositionToHashSlot.set(currentStateValue, destinationTableLocation); } break; - } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); } } } @@ -124,7 +126,7 @@ public int findPositionForKey(Object key) { final int k1 = TypeUtils.unbox((Integer)ka[1]); int hash = hash(k0, k1); int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = tableLocation; while (true) { final int positionValue = mainOutputPosition.getUnsafe(tableLocation); if (positionValue == EMPTY_OUTPUT_POSITION) { @@ -133,8 +135,8 @@ public int findPositionForKey(Object key) { if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { return positionValue; } - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherShortLong.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherShortLong.java index fc79f3cc8f5..53e6be02eae 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherShortLong.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherShortLong.java @@ -39,7 +39,10 @@ public StaticAggOpenHasherShortLong(ColumnSource[] tableKeySources, int tableSiz this.mainKeySource1.ensureCapacity(tableSize); } - @Override + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final ShortChunk keyChunk0 = sourceKeyChunks[0].asShortChunk(); final LongChunk keyChunk1 = sourceKeyChunks[1].asLongChunk(); @@ -48,25 +51,25 @@ protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final short k0 = keyChunk0.get(chunkPosition); final long k1 = keyChunk1.get(chunkPosition); final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; while (true) { - int tableState = mainOutputPosition.getUnsafe(tableLocation); - if (tableState == EMPTY_OUTPUT_POSITION) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { numEntries++; mainKeySource0.set(tableLocation, k0); mainKeySource1.set(tableLocation, k1); - final int outputPosition = nextOutputPosition.getAndIncrement(); + outputPosition = nextOutputPosition.getAndIncrement(); outputPositions.set(chunkPosition, outputPosition); mainOutputPosition.set(tableLocation, outputPosition); outputPositionToHashSlot.set(outputPosition, tableLocation); break; } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { - outputPositions.set(chunkPosition, tableState); + outputPositions.set(chunkPosition, outputPosition); break; } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } @@ -79,8 +82,7 @@ private static int hash(short k0, long k1) { } @Override - protected void rehashInternal() { - final int oldSize = tableSize >> 1; + protected void rehashInternalFull(final int oldSize) { final short[] destKeyArray0 = new short[tableSize]; final long[] destKeyArray1 = new long[tableSize]; final int[] destState = new int[tableSize]; @@ -92,27 +94,27 @@ protected void rehashInternal() { final int [] originalStateArray = mainOutputPosition.getArray(); mainOutputPosition.setArray(destState); for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { - if (originalStateArray[sourceBucket] == EMPTY_OUTPUT_POSITION) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { continue; } final short k0 = originalKeyArray0[sourceBucket]; final long k1 = originalKeyArray1[sourceBucket]; final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; while (true) { - if (destState[tableLocation] == EMPTY_OUTPUT_POSITION) { - destKeyArray0[tableLocation] = k0; - destKeyArray1[tableLocation] = k1; - destState[tableLocation] = originalStateArray[sourceBucket]; - if (sourceBucket != tableLocation) { - outputPositionToHashSlot.set(destState[tableLocation], tableLocation); + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + if (sourceBucket != destinationTableLocation) { + outputPositionToHashSlot.set(currentStateValue, destinationTableLocation); } break; - } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); } } } @@ -124,7 +126,7 @@ public int findPositionForKey(Object key) { final long k1 = TypeUtils.unbox((Long)ka[1]); int hash = hash(k0, k1); int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = tableLocation; while (true) { final int positionValue = mainOutputPosition.getUnsafe(tableLocation); if (positionValue == EMPTY_OUTPUT_POSITION) { @@ -133,8 +135,8 @@ public int findPositionForKey(Object key) { if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { return positionValue; } - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherShortObject.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherShortObject.java index 2804ae404ef..a18c3688c51 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherShortObject.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherShortObject.java @@ -38,7 +38,10 @@ public StaticAggOpenHasherShortObject(ColumnSource[] tableKeySources, int tableS this.mainKeySource1.ensureCapacity(tableSize); } - @Override + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final ShortChunk keyChunk0 = sourceKeyChunks[0].asShortChunk(); final ObjectChunk keyChunk1 = sourceKeyChunks[1].asObjectChunk(); @@ -47,25 +50,25 @@ protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final short k0 = keyChunk0.get(chunkPosition); final Object k1 = keyChunk1.get(chunkPosition); final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; while (true) { - int tableState = mainOutputPosition.getUnsafe(tableLocation); - if (tableState == EMPTY_OUTPUT_POSITION) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { numEntries++; mainKeySource0.set(tableLocation, k0); mainKeySource1.set(tableLocation, k1); - final int outputPosition = nextOutputPosition.getAndIncrement(); + outputPosition = nextOutputPosition.getAndIncrement(); outputPositions.set(chunkPosition, outputPosition); mainOutputPosition.set(tableLocation, outputPosition); outputPositionToHashSlot.set(outputPosition, tableLocation); break; } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { - outputPositions.set(chunkPosition, tableState); + outputPositions.set(chunkPosition, outputPosition); break; } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } @@ -78,8 +81,7 @@ private static int hash(short k0, Object k1) { } @Override - protected void rehashInternal() { - final int oldSize = tableSize >> 1; + protected void rehashInternalFull(final int oldSize) { final short[] destKeyArray0 = new short[tableSize]; final Object[] destKeyArray1 = new Object[tableSize]; final int[] destState = new int[tableSize]; @@ -91,27 +93,27 @@ protected void rehashInternal() { final int [] originalStateArray = mainOutputPosition.getArray(); mainOutputPosition.setArray(destState); for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { - if (originalStateArray[sourceBucket] == EMPTY_OUTPUT_POSITION) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { continue; } final short k0 = originalKeyArray0[sourceBucket]; final Object k1 = originalKeyArray1[sourceBucket]; final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; while (true) { - if (destState[tableLocation] == EMPTY_OUTPUT_POSITION) { - destKeyArray0[tableLocation] = k0; - destKeyArray1[tableLocation] = k1; - destState[tableLocation] = originalStateArray[sourceBucket]; - if (sourceBucket != tableLocation) { - outputPositionToHashSlot.set(destState[tableLocation], tableLocation); + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + if (sourceBucket != destinationTableLocation) { + outputPositionToHashSlot.set(currentStateValue, destinationTableLocation); } break; - } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); } } } @@ -123,7 +125,7 @@ public int findPositionForKey(Object key) { final Object k1 = ka[1]; int hash = hash(k0, k1); int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = tableLocation; while (true) { final int positionValue = mainOutputPosition.getUnsafe(tableLocation); if (positionValue == EMPTY_OUTPUT_POSITION) { @@ -132,8 +134,8 @@ public int findPositionForKey(Object key) { if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { return positionValue; } - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherShortShort.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherShortShort.java index 2ca62b879d7..fa1ed36d097 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherShortShort.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/staticopenagg/gen/StaticAggOpenHasherShortShort.java @@ -34,7 +34,10 @@ public StaticAggOpenHasherShortShort(ColumnSource[] tableKeySources, int tableSi this.mainKeySource1.ensureCapacity(tableSize); } - @Override + private int nextTableLocation(int tableLocation) { + return (tableLocation + 1) & (tableSize - 1); + } + protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final ShortChunk keyChunk0 = sourceKeyChunks[0].asShortChunk(); final ShortChunk keyChunk1 = sourceKeyChunks[1].asShortChunk(); @@ -43,25 +46,25 @@ protected void build(RowSequence rowSequence, Chunk[] sourceKeyChunks) { final short k0 = keyChunk0.get(chunkPosition); final short k1 = keyChunk1.get(chunkPosition); final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = hashToTableLocation(hash); + int tableLocation = firstTableLocation; while (true) { - int tableState = mainOutputPosition.getUnsafe(tableLocation); - if (tableState == EMPTY_OUTPUT_POSITION) { + int outputPosition = mainOutputPosition.getUnsafe(tableLocation); + if (outputPosition == EMPTY_OUTPUT_POSITION) { numEntries++; mainKeySource0.set(tableLocation, k0); mainKeySource1.set(tableLocation, k1); - final int outputPosition = nextOutputPosition.getAndIncrement(); + outputPosition = nextOutputPosition.getAndIncrement(); outputPositions.set(chunkPosition, outputPosition); mainOutputPosition.set(tableLocation, outputPosition); outputPositionToHashSlot.set(outputPosition, tableLocation); break; } else if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { - outputPositions.set(chunkPosition, tableState); + outputPositions.set(chunkPosition, outputPosition); break; } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } @@ -74,8 +77,7 @@ private static int hash(short k0, short k1) { } @Override - protected void rehashInternal() { - final int oldSize = tableSize >> 1; + protected void rehashInternalFull(final int oldSize) { final short[] destKeyArray0 = new short[tableSize]; final short[] destKeyArray1 = new short[tableSize]; final int[] destState = new int[tableSize]; @@ -87,27 +89,27 @@ protected void rehashInternal() { final int [] originalStateArray = mainOutputPosition.getArray(); mainOutputPosition.setArray(destState); for (int sourceBucket = 0; sourceBucket < oldSize; ++sourceBucket) { - if (originalStateArray[sourceBucket] == EMPTY_OUTPUT_POSITION) { + final int currentStateValue = originalStateArray[sourceBucket]; + if (currentStateValue == EMPTY_OUTPUT_POSITION) { continue; } final short k0 = originalKeyArray0[sourceBucket]; final short k1 = originalKeyArray1[sourceBucket]; final int hash = hash(k0, k1); - int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstDestinationTableLocation = hashToTableLocation(hash); + int destinationTableLocation = firstDestinationTableLocation; while (true) { - if (destState[tableLocation] == EMPTY_OUTPUT_POSITION) { - destKeyArray0[tableLocation] = k0; - destKeyArray1[tableLocation] = k1; - destState[tableLocation] = originalStateArray[sourceBucket]; - if (sourceBucket != tableLocation) { - outputPositionToHashSlot.set(destState[tableLocation], tableLocation); + if (destState[destinationTableLocation] == EMPTY_OUTPUT_POSITION) { + destKeyArray0[destinationTableLocation] = k0; + destKeyArray1[destinationTableLocation] = k1; + destState[destinationTableLocation] = originalStateArray[sourceBucket]; + if (sourceBucket != destinationTableLocation) { + outputPositionToHashSlot.set(currentStateValue, destinationTableLocation); } break; - } else { - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); } + destinationTableLocation = nextTableLocation(destinationTableLocation); + Assert.neq(destinationTableLocation, "destinationTableLocation", firstDestinationTableLocation, "firstDestinationTableLocation"); } } } @@ -119,7 +121,7 @@ public int findPositionForKey(Object key) { final short k1 = TypeUtils.unbox((Short)ka[1]); int hash = hash(k0, k1); int tableLocation = hashToTableLocation(hash); - final int lastTableLocation = (tableLocation + tableSize - 1) & (tableSize - 1); + final int firstTableLocation = tableLocation; while (true) { final int positionValue = mainOutputPosition.getUnsafe(tableLocation); if (positionValue == EMPTY_OUTPUT_POSITION) { @@ -128,8 +130,8 @@ public int findPositionForKey(Object key) { if (eq(mainKeySource0.getUnsafe(tableLocation), k0) && eq(mainKeySource1.getUnsafe(tableLocation), k1)) { return positionValue; } - Assert.neq(tableLocation, "tableLocation", lastTableLocation, "lastTableLocation"); - tableLocation = (tableLocation + 1) & (tableSize - 1); + tableLocation = nextTableLocation(tableLocation); + Assert.neq(tableLocation, "tableLocation", firstTableLocation, "firstTableLocation"); } } } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/sources/AbstractLongArraySource.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/sources/AbstractLongArraySource.java index f8e8f6eee1c..5a494c116b1 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/sources/AbstractLongArraySource.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/sources/AbstractLongArraySource.java @@ -26,7 +26,6 @@ * element type). */ public abstract class AbstractLongArraySource extends ArraySourceHelper implements MutableColumnSourceGetDefaults.LongBacked { - private static SoftRecycler recycler = new SoftRecycler<>(DEFAULT_RECYCLER_CAPACITY, () -> new long[BLOCK_SIZE], null); private long[][] blocks; @@ -86,6 +85,19 @@ public final long getAndSetUnsafe(long index, long newValue) { return oldValue; } + public final long getAndAddUnsafe(long index, long addend) { + final int blockIndex = (int) (index >> LOG_BLOCK_SIZE); + final int indexWithinBlock = (int) (index & INDEX_MASK); + final long oldValue = blocks[blockIndex][indexWithinBlock]; + if (addend != 0) { + if (shouldRecordPrevious(index, prevBlocks, recycler)) { + prevBlocks[blockIndex][indexWithinBlock] = oldValue; + } + blocks[blockIndex][indexWithinBlock] = oldValue + addend; + } + return oldValue; + } + @Override public final long getPrevLong(long index) { if (index < 0 || index > maxIndex) { diff --git a/engine/table/src/test/java/io/deephaven/engine/table/impl/BenchmarkPlaypen.java b/engine/table/src/test/java/io/deephaven/engine/table/impl/BenchmarkPlaypen.java index 9a5fcfce439..da220137edb 100644 --- a/engine/table/src/test/java/io/deephaven/engine/table/impl/BenchmarkPlaypen.java +++ b/engine/table/src/test/java/io/deephaven/engine/table/impl/BenchmarkPlaypen.java @@ -1,7 +1,10 @@ package io.deephaven.engine.table.impl; import io.deephaven.engine.table.Table; +import io.deephaven.engine.table.impl.select.AutoTuningIncrementalReleaseFilter; +import io.deephaven.engine.updategraph.UpdateGraphProcessor; import io.deephaven.engine.util.TableTools; +import io.deephaven.io.logger.StreamLoggerImpl; import io.deephaven.parquet.table.ParquetTools; import java.text.DecimalFormat; @@ -12,11 +15,11 @@ * easy-to-profile way from your IDE. */ public class BenchmarkPlaypen { - public static void main(String[] args) { - if (args.length != 3) { + public static void main(String[] args) throws InterruptedException { + if (args.length != 4) { usage(); } - final String filename = args[2]; + final String filename = args[3]; final boolean view; switch (args[0]) { @@ -30,15 +33,30 @@ public static void main(String[] args) { view = true; usage(); } - final String mode; + + final boolean incremental; switch (args[1]) { + case "static": + incremental = false; + break; + case "incremental": + incremental = true; + break; + default: + incremental = false; + usage(); + } + + final String mode; + switch (args[2]) { case "sum": case "count": case "count2": case "countplant": + case "countmany": case "noop": case "sumall": - mode = args[1]; + mode = args[2]; break; default: mode = ""; @@ -64,6 +82,9 @@ public static void main(String[] args) { case "countplant": columns = new String[] {"plant_id"}; break; + case "countmany": + columns = new String[] {"key1"}; + break; case "noop": case "sumall": columns = new String[] {"animal_id", "adjective_id", "plant_id", "Values"}; @@ -75,22 +96,39 @@ public static void main(String[] args) { final long endTimeSelect = System.nanoTime(); System.out.println("Select Elapsed Time: " + new DecimalFormat("###,###.000") .format(((double) (endTimeSelect - startTimeSelect) / 1_000_000_000.0))); + + final Table input; + final AutoTuningIncrementalReleaseFilter filter; + if (incremental) { + System.out.println("Running test incrementally."); + UpdateGraphProcessor.DEFAULT.enableUnitTestMode(); + filter = new AutoTuningIncrementalReleaseFilter(new StreamLoggerImpl(), 0, 1_000_000L, 1.0, true); + input = viewed.where(filter); + } else { + System.out.println("Running test statically."); + input = viewed; + filter = null; + } + final Table result; switch (mode) { case "sum": - result = viewed.sumBy("animal_id"); + result = input.sumBy("animal_id"); break; case "sumall": - result = viewed.sumBy(); + result = input.sumBy(); break; case "count": - result = viewed.countBy("N", "animal_id"); + result = input.countBy("N", "animal_id"); break; case "count2": - result = viewed.countBy("N", "animal_id", "adjective_id"); + result = input.countBy("N", "animal_id", "adjective_id"); break; case "countplant": - result = viewed.countBy("N", "plant_id"); + result = input.countBy("N", "plant_id"); + break; + case "countmany": + result = input.countBy("N", "key1"); break; case "noop": result = TableTools.emptyTable(0); @@ -98,6 +136,19 @@ public static void main(String[] args) { default: throw new IllegalArgumentException("Invalid mode " + mode); } + + if (filter != null) { + filter.start(); + while (viewed.size() > input.size()) { + final long initialSize = input.size(); + System.out.println("Running UpdateGraphProcessor cycle: " + input.size() + " / " + viewed.size()); + UpdateGraphProcessor.DEFAULT.runWithinUnitTestCycle(filter::run); + if (initialSize == input.size()) { + throw new RuntimeException("Did not increase size of input table during cycle!"); + } + } + } + final long endTimeSum = System.nanoTime(); System.out.println("Operation Elapsed Time: " + new DecimalFormat("###,###.000").format(((double) (endTimeSum - endTimeSelect) / 1_000_000_000.0))); diff --git a/replication/reflective/src/main/java/io/deephaven/replicators/ReplicateTypedHashers.java b/replication/reflective/src/main/java/io/deephaven/replicators/ReplicateTypedHashers.java index a8732a579c9..874eed4d591 100644 --- a/replication/reflective/src/main/java/io/deephaven/replicators/ReplicateTypedHashers.java +++ b/replication/reflective/src/main/java/io/deephaven/replicators/ReplicateTypedHashers.java @@ -6,6 +6,7 @@ import com.squareup.javapoet.TypeSpec; import io.deephaven.chunk.ChunkType; import io.deephaven.engine.table.ColumnSource; +import io.deephaven.engine.table.impl.by.IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase; import io.deephaven.engine.table.impl.by.IncrementalChunkedOperatorAggregationStateManagerTypedBase; import io.deephaven.engine.table.impl.by.StaticChunkedOperatorAggregationStateManagerOpenAddressedBase; import io.deephaven.engine.table.impl.by.StaticChunkedOperatorAggregationStateManagerTypedBase; @@ -22,6 +23,7 @@ public static void main(String[] args) throws IOException { generatePackage(StaticChunkedOperatorAggregationStateManagerTypedBase.class, true); generatePackage(StaticChunkedOperatorAggregationStateManagerOpenAddressedBase.class, true); generatePackage(IncrementalChunkedOperatorAggregationStateManagerTypedBase.class, true); + generatePackage(IncrementalChunkedOperatorAggregationStateManagerOpenAddressedBase.class, true); } private static void generatePackage(Class baseClass, boolean doDouble) throws IOException { diff --git a/replication/static/src/main/java/io/deephaven/replicators/ReplicateOperators.java b/replication/static/src/main/java/io/deephaven/replicators/ReplicateOperators.java index 335735a8df4..cd9dd8007dc 100644 --- a/replication/static/src/main/java/io/deephaven/replicators/ReplicateOperators.java +++ b/replication/static/src/main/java/io/deephaven/replicators/ReplicateOperators.java @@ -45,6 +45,9 @@ public static void main(String[] args) throws IOException { charToAllButBoolean( "engine/table/src/main/java/io/deephaven/engine/table/impl/by/CharStreamSortedFirstOrLastChunkedOperator.java"); replicateObjectAddOnlyAndStreamSortedFirstLast(); + charToAllButBoolean( + "engine/table/src/main/java/io/deephaven/engine/table/impl/by/alternatingcolumnsource/CharAlternatingColumnSourceUnorderedMergeKernel.java"); + replicateObjectUnorderedMergeKernel(); } private static void replicateObjectAddOnlyMinMax() throws IOException { @@ -94,4 +97,13 @@ private static void replicateObjectAddOnlyAndStreamSortedFirstLast() throws IOEx FileUtils.writeLines(objectClassFile, lines); } } + + private static void replicateObjectUnorderedMergeKernel() throws IOException { + final String objectUnorderedMerge = charToObject( + "engine/table/src/main/java/io/deephaven/engine/table/impl/by/alternatingcolumnsource/CharAlternatingColumnSourceUnorderedMergeKernel.java"); + final File objectUnorderedMergeFile = new File(objectUnorderedMerge); + List lines = ReplicationUtils + .fixupChunkAttributes(FileUtils.readLines(objectUnorderedMergeFile, Charset.defaultCharset())); + FileUtils.writeLines(objectUnorderedMergeFile, lines); + } }