Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package io.github.dfa1.vortex.reader.array;

import io.github.dfa1.vortex.core.DType;

import java.lang.foreign.MemorySegment;
import java.lang.foreign.SegmentAllocator;
import java.util.Optional;

/// Shared cold-path plumbing for the buffer-backed `Materialized*` arrays: the
/// `dtype` / `length` / `buffer` triple, the trivial accessors, and the zero-copy
/// `materialize` / `segmentIfPresent` contract every variant shares.
///
/// Subclasses keep their own typed element access and the branch-split hot loops
/// (`getX` / `fold` / `forEach`): those must stay monomorphic in the leaf class so the
/// JIT can vectorise them, and so are deliberately not hoisted here. This base only
/// holds the cold boilerplate.
///
/// Not `implements Array`: that interface is sealed to the typed element families
/// ([IntArray], [LongArray], …), which each leaf implements directly while inheriting
/// the common methods from here.
abstract class AbstractMaterializedArray {

final DType dtype;
final long length;
final MemorySegment buffer;

AbstractMaterializedArray(DType dtype, long length, MemorySegment buffer) {
this.dtype = dtype;
this.length = length;
this.buffer = buffer;
}

public final DType dtype() {
return dtype;
}

public final long length() {
return length;
}

/// Returns the backing buffer directly — it is already the contiguous segment the
/// array's materialize contract promises, so no copy or allocation is needed.
///
/// @param arena unused; the existing buffer is returned as-is
/// @return the backing segment
public final MemorySegment materialize(SegmentAllocator arena) {
return buffer;
}

public final Optional<MemorySegment> segmentIfPresent() {
return Optional.of(buffer);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,53 +4,19 @@
import io.github.dfa1.vortex.core.DType;

import java.lang.foreign.MemorySegment;
import java.lang.foreign.SegmentAllocator;
import java.lang.foreign.ValueLayout;
import java.util.Optional;

/// Buffer-backed [BoolArray] — the fallback used when an encoding decoder
/// either materialises the output eagerly or has no lazy variant of its own.
public final class MaterializedBoolArray implements BoolArray {

private final DType dtype;
private final long length;
private final MemorySegment buffer;
public final class MaterializedBoolArray extends AbstractMaterializedArray implements BoolArray {

/// Constructs a `MaterializedBoolArray` backed by the given bit-packed buffer.
///
/// @param dtype logical type, must be [io.github.dfa1.vortex.core.DType.Bool]
/// @param length number of logical boolean elements
/// @param buffer bit-packed boolean data (LSB-first, one byte per 8 elements)
public MaterializedBoolArray(DType dtype, long length, MemorySegment buffer) {
this.dtype = dtype;
this.length = length;
this.buffer = buffer;
}

@Override
public DType dtype() {
return dtype;
}

@Override
public long length() {
return length;
}

/// Returns the backing buffer directly — already an LSB-first packed bitmap,
/// matching the format produced by [BoolArray#materialize(SegmentAllocator)],
/// so no copy or allocation is needed.
///
/// @param arena unused; the existing buffer is returned as-is
/// @return the backing LSB-first packed bitmap
@Override
public MemorySegment materialize(SegmentAllocator arena) {
return buffer;
}

@Override
public Optional<MemorySegment> segmentIfPresent() {
return Optional.of(buffer);
super(dtype, length, buffer);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,13 @@
import io.github.dfa1.vortex.core.PType;

import java.lang.foreign.MemorySegment;
import java.lang.foreign.SegmentAllocator;
import java.lang.foreign.ValueLayout;
import java.util.Optional;
import java.util.function.LongBinaryOperator;

/// Buffer-backed [ByteArray] — the fallback used when an encoding decoder
/// either materialises the output eagerly or has no lazy variant of its own.
public final class MaterializedByteArray implements ByteArray {
public final class MaterializedByteArray extends AbstractMaterializedArray implements ByteArray {

private final DType dtype;
private final long length;
private final MemorySegment buffer;
private final long elementCount;

/// Constructs a `MaterializedByteArray` backed by the given buffer.
Expand All @@ -25,37 +20,10 @@ public final class MaterializedByteArray implements ByteArray {
/// @param length number of logical elements
/// @param buffer raw byte data (one byte per element)
public MaterializedByteArray(DType dtype, long length, MemorySegment buffer) {
this.dtype = dtype;
this.length = length;
this.buffer = buffer;
super(dtype, length, buffer);
this.elementCount = buffer.byteSize();
}

@Override
public DType dtype() {
return dtype;
}

@Override
public long length() {
return length;
}

/// Returns the backing buffer directly — already a contiguous one-byte-per-element
/// segment, so no copy or allocation is needed.
///
/// @param arena unused; the existing buffer is returned as-is
/// @return the backing byte segment
@Override
public MemorySegment materialize(SegmentAllocator arena) {
return buffer;
}

@Override
public Optional<MemorySegment> segmentIfPresent() {
return Optional.of(buffer);
}

@Override
public byte getByte(long i) {
return buffer.get(ValueLayout.JAVA_BYTE, length == elementCount ? i : i % elementCount);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,13 @@
import io.github.dfa1.vortex.encoding.PTypeIO;

import java.lang.foreign.MemorySegment;
import java.lang.foreign.SegmentAllocator;
import java.util.Optional;
import java.util.function.DoubleBinaryOperator;
import java.util.function.DoubleConsumer;

/// Buffer-backed [DoubleArray] — the fallback used when an encoding decoder
/// either materialises the output eagerly or has no lazy variant of its own.
public final class MaterializedDoubleArray implements DoubleArray {
public final class MaterializedDoubleArray extends AbstractMaterializedArray implements DoubleArray {

private final DType dtype;
private final long length;
private final MemorySegment buffer;
private final long elementCount;

/// Constructs a `MaterializedDoubleArray` backed by the given buffer.
Expand All @@ -24,37 +19,10 @@ public final class MaterializedDoubleArray implements DoubleArray {
/// @param length number of logical elements
/// @param buffer raw double data (8 bytes per element, little-endian)
public MaterializedDoubleArray(DType dtype, long length, MemorySegment buffer) {
this.dtype = dtype;
this.length = length;
this.buffer = buffer;
super(dtype, length, buffer);
this.elementCount = buffer.byteSize() / PTypeIO.LE_DOUBLE.byteSize();
}

@Override
public DType dtype() {
return dtype;
}

@Override
public long length() {
return length;
}

/// Returns the backing buffer directly — already a contiguous little-endian
/// `f64` segment, so no copy or allocation is needed.
///
/// @param arena unused; the existing buffer is returned as-is
/// @return the backing little-endian `f64` segment
@Override
public MemorySegment materialize(SegmentAllocator arena) {
return buffer;
}

@Override
public Optional<MemorySegment> segmentIfPresent() {
return Optional.of(buffer);
}

@Override
public double getDouble(long i) {
return buffer.getAtIndex(PTypeIO.LE_DOUBLE, length == elementCount ? i : i % elementCount);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,51 +5,18 @@
import io.github.dfa1.vortex.encoding.PTypeIO;

import java.lang.foreign.MemorySegment;
import java.lang.foreign.SegmentAllocator;
import java.util.Optional;

/// Buffer-backed [Float16Array] — the fallback used when an encoding decoder
/// either materialises the output eagerly or has no lazy variant of its own.
public final class MaterializedFloat16Array implements Float16Array {

private final DType dtype;
private final long length;
private final MemorySegment buffer;
public final class MaterializedFloat16Array extends AbstractMaterializedArray implements Float16Array {

/// Creates a new `MaterializedFloat16Array` backed by the given memory segment.
///
/// @param dtype logical type, must be F16
/// @param length number of elements
/// @param buffer little-endian half-precision float data (2 bytes per element)
public MaterializedFloat16Array(DType dtype, long length, MemorySegment buffer) {
this.dtype = dtype;
this.length = length;
this.buffer = buffer;
}

@Override
public DType dtype() {
return dtype;
}

@Override
public long length() {
return length;
}

/// Returns the backing buffer directly — already a contiguous little-endian
/// half-precision segment (2 bytes per element), so no copy or allocation is needed.
///
/// @param arena unused; the existing buffer is returned as-is
/// @return the backing little-endian `f16` segment
@Override
public MemorySegment materialize(SegmentAllocator arena) {
return buffer;
}

@Override
public Optional<MemorySegment> segmentIfPresent() {
return Optional.of(buffer);
super(dtype, length, buffer);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,12 @@
import io.github.dfa1.vortex.encoding.PTypeIO;

import java.lang.foreign.MemorySegment;
import java.lang.foreign.SegmentAllocator;
import java.util.Optional;
import java.util.function.DoubleBinaryOperator;

/// Buffer-backed [FloatArray] — the fallback used when an encoding decoder
/// either materialises the output eagerly or has no lazy variant of its own.
public final class MaterializedFloatArray implements FloatArray {
public final class MaterializedFloatArray extends AbstractMaterializedArray implements FloatArray {

private final DType dtype;
private final long length;
private final MemorySegment buffer;
private final long elementCount;

/// Creates a new `MaterializedFloatArray` backed by the given memory segment.
Expand All @@ -24,37 +19,10 @@ public final class MaterializedFloatArray implements FloatArray {
/// @param length number of elements
/// @param buffer little-endian float data (4 bytes per element)
public MaterializedFloatArray(DType dtype, long length, MemorySegment buffer) {
this.dtype = dtype;
this.length = length;
this.buffer = buffer;
super(dtype, length, buffer);
this.elementCount = buffer.byteSize() / PTypeIO.LE_FLOAT.byteSize();
}

@Override
public DType dtype() {
return dtype;
}

@Override
public long length() {
return length;
}

/// Returns the backing buffer directly — already a contiguous little-endian
/// `f32` segment, so no copy or allocation is needed.
///
/// @param arena unused; the existing buffer is returned as-is
/// @return the backing little-endian `f32` segment
@Override
public MemorySegment materialize(SegmentAllocator arena) {
return buffer;
}

@Override
public Optional<MemorySegment> segmentIfPresent() {
return Optional.of(buffer);
}

@Override
public float getFloat(long i) {
return buffer.getAtIndex(PTypeIO.LE_FLOAT, length == elementCount ? i : i % elementCount);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,13 @@
import io.github.dfa1.vortex.encoding.PTypeIO;

import java.lang.foreign.MemorySegment;
import java.lang.foreign.SegmentAllocator;
import java.util.Optional;
import java.util.function.IntBinaryOperator;
import java.util.function.IntConsumer;

/// Buffer-backed [IntArray] — the fallback used when an encoding decoder
/// either materialises the output eagerly or has no lazy variant of its own.
public final class MaterializedIntArray implements IntArray {
public final class MaterializedIntArray extends AbstractMaterializedArray implements IntArray {

private final DType dtype;
private final long length;
private final MemorySegment buffer;
private final long elementCount;

/// Creates a new `MaterializedIntArray` backed by the given memory segment.
Expand All @@ -25,37 +20,10 @@ public final class MaterializedIntArray implements IntArray {
/// @param length number of elements
/// @param buffer little-endian int data (4 bytes per element)
public MaterializedIntArray(DType dtype, long length, MemorySegment buffer) {
this.dtype = dtype;
this.length = length;
this.buffer = buffer;
super(dtype, length, buffer);
this.elementCount = buffer.byteSize() / PTypeIO.LE_INT.byteSize();
}

@Override
public DType dtype() {
return dtype;
}

@Override
public long length() {
return length;
}

/// Returns the backing buffer directly — already a contiguous little-endian
/// `i32` segment, so no copy or allocation is needed.
///
/// @param arena unused; the existing buffer is returned as-is
/// @return the backing little-endian `i32` segment
@Override
public MemorySegment materialize(SegmentAllocator arena) {
return buffer;
}

@Override
public Optional<MemorySegment> segmentIfPresent() {
return Optional.of(buffer);
}

@Override
public int getInt(long i) {
return buffer.getAtIndex(PTypeIO.LE_INT, length == elementCount ? i : i % elementCount);
Expand Down
Loading