Skip to content

Instantly share code, notes, and snippets.

@pbk20191
Created March 9, 2025 14:59
Show Gist options
  • Save pbk20191/ce4b485d431f1a82b39b03ffb4bfbd4d to your computer and use it in GitHub Desktop.
Save pbk20191/ce4b485d431f1a82b39b03ffb4bfbd4d to your computer and use it in GitHub Desktop.
Apple BTree Collection extended
//
// customization.swift
// BTree
//
// Created by 박병관 on 3/9/25.
//
import Foundation
extension _BTree {
@inlinable
internal func lookupGreaterOrEqual(forKey key: Key) -> Element? {
var node: Node? = self.root
var result: Element? = nil
while let currentNode = node {
currentNode.read { handle in
let slot = handle.startSlot(forKey: key)
// If exact match found, return immediately
if slot < handle.elementCount, handle[keyAt: slot] == key {
result = (handle[keyAt: slot], handle[valueAt: slot])
node = nil
return
}
// If slot is within bounds, check for the next greater key
if slot < handle.elementCount {
result = (handle[keyAt: slot], handle[valueAt: slot])
}
// Continue searching in the child node
if handle.isLeaf {
node = nil
} else {
node = handle[childAt: slot]
}
}
}
return result
}
@inlinable
internal func lookupGreater(forKey key: Key) -> Element? {
var node: Node? = self.root
var result: Element? = nil
while let currentNode = node {
currentNode.read { handle in
let slot = handle.endSlot(forKey: key)
// If exact match found, return immediately
if slot < handle.elementCount, handle[keyAt: slot] == key {
result = (handle[keyAt: slot], handle[valueAt: slot])
node = nil
return
}
// If slot is within bounds, check for the next greater key
if slot < handle.elementCount {
result = (handle[keyAt: slot], handle[valueAt: slot])
}
// Continue searching in the child node
if handle.isLeaf {
node = nil
} else {
node = handle[childAt: slot]
}
}
}
return result
}
@inlinable
internal func lookupLessThan(forKey key: Key) -> Element? {
var node: Node? = self.root
var result: Element? = nil
while let currentNode = node {
currentNode.read { handle in
let slot = handle.startSlot(forKey: key) - 1
// If there is a key < `key`, update result
if slot >= 0 {
result = (handle[keyAt: slot], handle[valueAt: slot])
}
// If `key` is smaller than the smallest key in this node, move left
// // Continue searching in the appropriate child
if handle.isLeaf {
node = nil
} else {
node = slot < 0 ? handle[childAt: 0] : handle[childAt: slot + 1]
}
}
}
return result
}
@inlinable
internal func lookupLessThanOrEqual(forKey key: Key) -> Element? {
var node: Node? = self.root
var result: Element? = nil
while let currentNode = node {
currentNode.read { handle in
let slot = handle.endSlot(forKey: key) - 1
// If there is a key <= `key`, update result
if slot >= 0 {
result = (handle[keyAt: slot], handle[valueAt: slot])
}
// If `key` is smaller than the smallest key in this node, move left
// Continue searching in the appropriate child
if handle.isLeaf {
node = nil
} else {
node = slot < 0 ? handle[childAt: 0] : handle[childAt: slot + 1]
}
}
}
return result
}
@inlinable
internal func lookup(forKey key: Key, search: BTreeSearch) -> Element? {
// self.findAnyValue(forKey: key)
var node: Node? = self.root
var result: Element? = nil
while let currentNode = node {
currentNode.read { handle in
let slot:Int
do {
var mutable:Int
switch search {
case .lessThan, .greaterThanOrEqual, .equal:
mutable = handle.startSlot(forKey: key)
mutable -= search == .lessThan ? 1 : 0
case .greaterThan, .lessThanOrEqual:
mutable = handle.endSlot(forKey: key)
mutable -= search == .lessThanOrEqual ? 1 : 0
}
slot = mutable
}
switch search {
case .lessThan, .lessThanOrEqual:
// If there is a key <= `key`, update result
if slot >= 0 {
result = (handle[keyAt: slot], handle[valueAt: slot])
}
// If `key` is smaller than the smallest key in this node, move left
// Continue searching in the appropriate child
if handle.isLeaf {
node = nil
} else {
node = slot < 0 ? handle[childAt: 0] : handle[childAt: slot + 1]
}
case .greaterThan, .greaterThanOrEqual, .equal:
// If slot is within bounds, check for the next greater key
if slot < handle.elementCount {
result = (handle[keyAt: slot], handle[valueAt: slot])
if search == .equal, result?.key != key {
result = nil
}
}
// Continue searching in the child node
if handle.isLeaf {
node = nil
} else {
node = handle[childAt: slot]
}
}
}
}
return result
}
}
public enum BTreeSearch: Hashable, BitwiseCopyable {
case lessThan
case greaterThan
case lessThanOrEqual
case greaterThanOrEqual
case equal
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment