L1 Cache Flow

From Chrysalis Archive
Jump to navigation Jump to search

See also


package flatrow

import (
	"encoding/binary"
	"errors"
	"math"
)

// Row is a single Flat SKV Morpheme Row packed into exactly 64 bytes.
// It is represented as a fixed-size byte array to guarantee cache-line alignment
// and to avoid any compiler-introduced padding.
type Row [64]byte

// Offsets within the 64-byte layout (0-based, big-endian order for multi-byte values).
const (
	OffTIdx      = 0
	OffMID       = 8
	OffPacked    = 16
	OffSubject   = 17
	OffPredicate = 25
	OffObject    = 27
	OffCtxLen    = 35
	OffContext   = 36
	OffRank      = 51
	OffMetaHash  = 59
)

// Bit positions and masks for the packed byte at offset 16.
// Layout: bits 0-2 = type, bit 3 = direction, bits 4-5 = status, bits 6-7 = reserved.
const (
	MaskType      = 0x07 // bits 0-2
	MaskDirection = 0x08 // bit 3
	MaskStatus    = 0x30 // bits 4-5

	ShiftDirection = 3
	ShiftStatus    = 4
)

// Enum values (must fit in their respective bit widths).
const (
	TypeEvent    uint8 = 0
	TypeState    uint8 = 1
	TypeAction   uint8 = 2
	TypeRelation uint8 = 3
	// (values 4-7 reserved)

	DirForward uint8 = 0
	DirReverse uint8 = 1

	StatusValid      uint8 = 0
	StatusObstructed uint8 = 1
	StatusDuplicate  uint8 = 2
	StatusInvalid    uint8 = 3
)

// ----------------------------------------------------------------------
// Getters and setters for each field.
// ----------------------------------------------------------------------

func (r *Row) TIdx() uint64 {
	return binary.BigEndian.Uint64(r[OffTIdx : OffTIdx+8])
}
func (r *Row) SetTIdx(v uint64) {
	binary.BigEndian.PutUint64(r[OffTIdx:OffTIdx+8], v)
}

func (r *Row) MID() uint64 {
	return binary.BigEndian.Uint64(r[OffMID : OffMID+8])
}
func (r *Row) SetMID(v uint64) {
	binary.BigEndian.PutUint64(r[OffMID:OffMID+8], v)
}

func (r *Row) Type() uint8 {
	return r[OffPacked] & MaskType
}
func (r *Row) SetType(t uint8) {
	r[OffPacked] = (r[OffPacked] &^ MaskType) | (t & MaskType)
}

func (r *Row) Direction() uint8 {
	return (r[OffPacked] & MaskDirection) >> ShiftDirection
}
func (r *Row) SetDirection(d uint8) {
	r[OffPacked] = (r[OffPacked] &^ MaskDirection) | ((d & 0x01) << ShiftDirection)
}

func (r *Row) Status() uint8 {
	return (r[OffPacked] & MaskStatus) >> ShiftStatus
}
func (r *Row) SetStatus(s uint8) {
	r[OffPacked] = (r[OffPacked] &^ MaskStatus) | ((s & 0x03) << ShiftStatus)
}

func (r *Row) Subject() uint64 {
	return binary.BigEndian.Uint64(r[OffSubject : OffSubject+8])
}
func (r *Row) SetSubject(v uint64) {
	binary.BigEndian.PutUint64(r[OffSubject:OffSubject+8], v)
}

func (r *Row) Predicate() uint16 {
	return binary.BigEndian.Uint16(r[OffPredicate : OffPredicate+2])
}
func (r *Row) SetPredicate(v uint16) {
	binary.BigEndian.PutUint16(r[OffPredicate:OffPredicate+2], v)
}

func (r *Row) Object() uint64 {
	return binary.BigEndian.Uint64(r[OffObject : OffObject+8])
}
func (r *Row) SetObject(v uint64) {
	binary.BigEndian.PutUint64(r[OffObject:OffObject+8], v)
}

func (r *Row) CtxLen() uint8 {
	return r[OffCtxLen]
}
func (r *Row) SetCtxLen(v uint8) {
	r[OffCtxLen] = v
}

// Context returns a copy of the inline context bytes up to CtxLen() length.
func (r *Row) Context() []byte {
	n := r.CtxLen()
	if n > 15 {
		n = 15
	}
	c := make([]byte, n)
	copy(c, r[OffContext:OffContext+n])
	return c
}

// SetContext writes up to 15 bytes of inline context.
func (r *Row) SetContext(data []byte) error {
	if len(data) > 15 {
		return errors.New("context exceeds 15 bytes")
	}
	r.SetCtxLen(uint8(len(data)))
	copy(r[OffContext:OffContext+len(data)], data)
	// zero the remaining context area for hygiene
	for i := len(data); i < 15; i++ {
		r[OffContext+i] = 0
	}
	return nil
}

func (r *Row) Rank() float64 {
	bits := binary.BigEndian.Uint64(r[OffRank : OffRank+8])
	return math.Float64frombits(bits)
}
func (r *Row) SetRank(f float64) {
	bits := math.Float64bits(f)
	binary.BigEndian.PutUint64(r[OffRank:OffRank+8], bits)
}

func (r *Row) MetaHash() [5]byte {
	var h [5]byte
	copy(h[:], r[OffMetaHash:OffMetaHash+5])
	return h
}
func (r *Row) SetMetaHash(h [5]byte) {
	copy(r[OffMetaHash:OffMetaHash+5], h[:])
}