///|
/// Convert AttrValue to string key for indexing
/// Uses type prefix to disambiguate different types with same string representation
pub fn attr_value_to_key(value : @types.AttrValue) -> String {
match value {
Null => "N:"
Bool(b) => if b { "B:true" } else { "B:false" }
Int(n) => "I:" + n.to_string()
Float(f) => "F:" + f.to_string()
String(s) => "S:" + s
}
}
///|
/// Extract numeric value from AttrValue for range queries
pub fn attr_value_to_number(value : @types.AttrValue) -> Double? {
match value {
Int(n) => Some(n.to_double())
Float(f) => Some(f)
_ => None
}
}
///|
/// Sorted entry for numeric index (value, id) pair
pub struct NumEntry {
value : Double
id : @types.VectorId
}
///|
pub impl Show for NumEntry with fn output(self, logger) {
logger.write_string("{ value: ")
Show::output(self.value, logger)
logger.write_string(", id: ")
Show::output(self.id, logger)
logger.write_string(" }")
}
///|
/// Compare NumEntry by value for sorting
pub fn NumEntry::compare(self : NumEntry, other : NumEntry) -> Int {
if self.value < other.value {
-1
} else if self.value > other.value {
1
} else {
0
}
}
///|
/// Binary search for lower bound in sorted array
/// Returns index of first element >= target
pub fn lower_bound(arr : Array[NumEntry], target : Double) -> Int {
let mut lo = 0
let mut hi = arr.length()
while lo < hi {
let mid = (lo + hi) / 2
if arr[mid].value < target {
lo = mid + 1
} else {
hi = mid
}
}
lo
}
///|
/// Binary search for upper bound in sorted array
/// Returns index of first element > target
pub fn upper_bound(arr : Array[NumEntry], target : Double) -> Int {
let mut lo = 0
let mut hi = arr.length()
while lo < hi {
let mid = (lo + hi) / 2
if arr[mid].value <= target {
lo = mid + 1
} else {
hi = mid
}
}
lo
}
///|
/// Sort NumEntry array by value
pub fn sort_num_entries(arr : Array[NumEntry]) -> Unit {
// Simple insertion sort for now (stable and works for small arrays)
for i in 1..= 0 && arr[j].value > key.value {
arr[j + 1] = arr[j]
j = j - 1
}
arr[j + 1] = key
}
}
///|
/// Remove an Int64 value from an array using swap-and-pop
/// Returns true if the value was found and removed
pub fn remove_vectorid_swap(
arr : Array[@types.VectorId],
value : @types.VectorId,
) -> Bool {
let mut found_idx = -1
for i in 0..= 0 {
let last = arr.length() - 1
if found_idx != last {
arr[found_idx] = arr[last]
}
let _ = arr.pop()
true
} else {
false
}
}
///|
/// Remove a NumEntry by id from an array using swap-and-pop
/// Returns true if the entry was found and removed
pub fn remove_num_entry_swap(
arr : Array[NumEntry],
id : @types.VectorId,
) -> Bool {
let mut found_idx = -1
for i in 0..= 0 {
let last = arr.length() - 1
if found_idx != last {
arr[found_idx] = arr[last]
}
let _ = arr.pop()
true
} else {
false
}
}