style: cargo fmt on v0.3 module source files

Co-Authored-By: claude-flow <ruv@ruv.net>
This commit is contained in:
rUv 2026-02-21 20:50:06 +00:00
parent 5712eb9269
commit aa009dff83
11 changed files with 143 additions and 121 deletions

View file

@ -375,7 +375,9 @@ pub fn ruvector_linear_attention(
// Linear attention: phi(q)^T * (sum phi(k_i) * v_i^T) / (phi(q)^T * sum phi(k_i))
// Using ELU+1 as kernel feature map
let phi = |x: &[f32]| -> Vec<f32> {
x.iter().map(|&v| if v >= 0.0 { v + 1.0 } else { v.exp() }).collect()
x.iter()
.map(|&v| if v >= 0.0 { v + 1.0 } else { v.exp() })
.collect()
};
let phi_q = phi(&query);
@ -480,7 +482,13 @@ pub fn ruvector_sliding_window_attention(
// Softmax
let max_score = scores.iter().copied().fold(f32::NEG_INFINITY, f32::max);
let exp_sum: f32 = scores.iter_mut().map(|s| { *s = (*s - max_score).exp(); *s }).sum();
let exp_sum: f32 = scores
.iter_mut()
.map(|s| {
*s = (*s - max_score).exp();
*s
})
.sum();
if exp_sum > 0.0 {
for s in &mut scores {
*s /= exp_sum;
@ -612,7 +620,10 @@ pub fn ruvector_sparse_attention(
let top = &scored[..k];
// Softmax on top-k scores
let max_s = top.iter().map(|(_, s)| *s).fold(f32::NEG_INFINITY, f32::max);
let max_s = top
.iter()
.map(|(_, s)| *s)
.fold(f32::NEG_INFINITY, f32::max);
let exps: Vec<f32> = top.iter().map(|(_, s)| (s - max_s).exp()).collect();
let sum: f32 = exps.iter().sum();
@ -704,7 +715,10 @@ pub fn ruvector_moe_attention(
// Softmax on top-k expert scores
let top_experts = &expert_scores[..k.min(expert_scores.len())];
let max_s = top_experts.iter().map(|(_, s)| *s).fold(f32::NEG_INFINITY, f32::max);
let max_s = top_experts
.iter()
.map(|(_, s)| *s)
.fold(f32::NEG_INFINITY, f32::max);
let exps: Vec<f32> = top_experts.iter().map(|(_, s)| (s - max_s).exp()).collect();
let sum: f32 = exps.iter().sum();
@ -803,7 +817,13 @@ pub fn ruvector_hyperbolic_attention(
// Softmax
let max_s = scores.iter().copied().fold(f32::NEG_INFINITY, f32::max);
let exp_sum: f32 = scores.iter_mut().map(|s| { *s = (*s - max_s).exp(); *s }).sum();
let exp_sum: f32 = scores
.iter_mut()
.map(|s| {
*s = (*s - max_s).exp();
*s
})
.sum();
if exp_sum > 0.0 {
for s in &mut scores {
*s /= exp_sum;

View file

@ -3,9 +3,9 @@
pub mod operators;
use dashmap::DashMap;
use std::sync::Arc;
use parking_lot::RwLock;
use ruvector_domain_expansion::DomainExpansionEngine;
use std::sync::Arc;
/// Global domain expansion engine state.
static DOMAIN_ENGINES: once_cell::sync::Lazy<DashMap<String, Arc<RwLock<DomainExpansionEngine>>>> =

View file

@ -3,7 +3,7 @@
use pgrx::prelude::*;
use pgrx::JsonB;
use ruvector_domain_expansion::{DomainId, Solution, ContextBucket, ArmId};
use ruvector_domain_expansion::{ArmId, ContextBucket, DomainId, Solution};
use super::get_or_create_engine;

View file

@ -441,9 +441,7 @@ unsafe fn metric_from_index(index: Relation) -> DistanceMetric {
return DistanceMetric::Euclidean;
}
let name = std::ffi::CStr::from_ptr(name_ptr)
.to_str()
.unwrap_or("");
let name = std::ffi::CStr::from_ptr(name_ptr).to_str().unwrap_or("");
let metric = if name.contains("cosine") {
DistanceMetric::Cosine
@ -546,7 +544,9 @@ unsafe fn read_vector(
if total_read_end > page_size {
pgrx::warning!(
"HNSW: Vector read would exceed page boundary ({} > {}), skipping block {}",
total_read_end, page_size, block
total_read_end,
page_size,
block
);
pg_sys::UnlockReleaseBuffer(buffer);
return None;
@ -608,7 +608,9 @@ unsafe fn read_neighbors(
if total_read_end > page_size {
pgrx::warning!(
"HNSW: Neighbor read would exceed page boundary ({} > {}), skipping block {}",
total_read_end, page_size, block
total_read_end,
page_size,
block
);
pg_sys::UnlockReleaseBuffer(buffer);
return Vec::new();
@ -1353,8 +1355,7 @@ unsafe fn connect_node_to_neighbors(
// Read current neighbor list for this layer
let header_ptr = (page as *const u8).add(size_of::<PageHeaderData>());
let node_header = &*(header_ptr as *const HnswNodePageHeader);
let existing_count =
node_header.neighbor_counts.get(layer).copied().unwrap_or(0) as usize;
let existing_count = node_header.neighbor_counts.get(layer).copied().unwrap_or(0) as usize;
let vector_size = dimensions * size_of::<f32>();
let neighbors_base = header_ptr
@ -1587,12 +1588,9 @@ unsafe extern "C" fn hnsw_beginscan(
// RelationGetIndexScan). See GiST's gistbeginscan for reference.
if (*scan).numberOfOrderBys > 0 {
let n = (*scan).numberOfOrderBys as usize;
(*scan).xs_orderbyvals = pg_sys::palloc0(
std::mem::size_of::<pg_sys::Datum>() * n,
) as *mut pg_sys::Datum;
(*scan).xs_orderbynulls = pg_sys::palloc(
std::mem::size_of::<bool>() * n,
) as *mut bool;
(*scan).xs_orderbyvals =
pg_sys::palloc0(std::mem::size_of::<pg_sys::Datum>() * n) as *mut pg_sys::Datum;
(*scan).xs_orderbynulls = pg_sys::palloc(std::mem::size_of::<bool>() * n) as *mut bool;
// Initialize all ORDER BY values as null (true = null)
std::ptr::write_bytes((*scan).xs_orderbynulls, 1u8, n);
}

View file

@ -1503,12 +1503,9 @@ unsafe extern "C" fn ivfflat_ambeginscan(
// RelationGetIndexScan). See GiST's gistbeginscan for reference.
if (*scan).numberOfOrderBys > 0 {
let n = (*scan).numberOfOrderBys as usize;
(*scan).xs_orderbyvals = pg_sys::palloc0(
std::mem::size_of::<pg_sys::Datum>() * n,
) as *mut pg_sys::Datum;
(*scan).xs_orderbynulls = pg_sys::palloc(
std::mem::size_of::<bool>() * n,
) as *mut bool;
(*scan).xs_orderbyvals =
pg_sys::palloc0(std::mem::size_of::<pg_sys::Datum>() * n) as *mut pg_sys::Datum;
(*scan).xs_orderbynulls = pg_sys::palloc(std::mem::size_of::<bool>() * n) as *mut bool;
std::ptr::write_bytes((*scan).xs_orderbynulls, 1u8, n);
}

View file

@ -3,11 +3,11 @@
use pgrx::prelude::*;
use pgrx::JsonB;
use ruvector_math::optimal_transport::{OptimalTransport, SlicedWasserstein, SinkhornSolver};
use ruvector_math::product_manifold::ProductManifold;
use ruvector_math::spherical::SphericalSpace;
use ruvector_math::spectral::{SpectralClustering, ScaledLaplacian, GraphFilter, SpectralFilter};
use ruvector_math::optimal_transport::GromovWasserstein;
use ruvector_math::optimal_transport::{OptimalTransport, SinkhornSolver, SlicedWasserstein};
use ruvector_math::product_manifold::ProductManifold;
use ruvector_math::spectral::{GraphFilter, ScaledLaplacian, SpectralClustering, SpectralFilter};
use ruvector_math::spherical::SphericalSpace;
/// Helper: parse a JsonB 2D array into Vec<Vec<f64>>.
fn parse_points(json: &JsonB) -> Vec<Vec<f64>> {
@ -16,11 +16,8 @@ fn parse_points(json: &JsonB) -> Vec<Vec<f64>> {
.map(|arr| {
arr.iter()
.filter_map(|v| {
v.as_array().map(|a| {
a.iter()
.filter_map(|x| x.as_f64())
.collect()
})
v.as_array()
.map(|a| a.iter().filter_map(|x| x.as_f64()).collect())
})
.collect()
})
@ -48,11 +45,7 @@ fn flatten_adjacency(adj: &[Vec<f64>]) -> (Vec<f64>, usize) {
/// Compute Wasserstein (Earth Mover's) distance between two distributions.
#[pg_extern(immutable, parallel_safe)]
pub fn ruvector_wasserstein_distance(
a: Vec<f32>,
b: Vec<f32>,
p: default!(i32, 1),
) -> f32 {
pub fn ruvector_wasserstein_distance(a: Vec<f32>, b: Vec<f32>, p: default!(i32, 1)) -> f32 {
if a.len() != b.len() || a.is_empty() {
pgrx::error!("Distributions must have same non-zero length");
}
@ -91,14 +84,12 @@ pub fn ruvector_sinkhorn_distance(
let solver = SinkhornSolver::new(reg as f64, 100);
match solver.solve(&cost, &wa, &wb) {
Ok(result) => {
JsonB(serde_json::json!({
"distance": result.cost,
"converged": result.converged,
"iterations": result.iterations,
"transport_plan": result.plan,
}))
}
Ok(result) => JsonB(serde_json::json!({
"distance": result.cost,
"converged": result.converged,
"iterations": result.iterations,
"transport_plan": result.plan,
})),
Err(e) => pgrx::error!("Sinkhorn failed: {}", e),
}
}
@ -174,10 +165,7 @@ pub fn ruvector_jensen_shannon(p: Vec<f32>, q: Vec<f32>) -> f32 {
/// Compute Fisher information metric.
#[pg_extern(immutable, parallel_safe)]
pub fn ruvector_fisher_information(
dist: Vec<f32>,
tangent: Vec<f32>,
) -> f32 {
pub fn ruvector_fisher_information(dist: Vec<f32>, tangent: Vec<f32>) -> f32 {
if dist.len() != tangent.len() || dist.is_empty() {
pgrx::error!("Distribution and tangent must have same non-zero length");
}
@ -197,10 +185,7 @@ pub fn ruvector_fisher_information(
/// Spectral clustering on an adjacency matrix.
#[pg_extern(immutable, parallel_safe)]
pub fn ruvector_spectral_cluster(
adj_json: JsonB,
k: i32,
) -> Vec<i32> {
pub fn ruvector_spectral_cluster(adj_json: JsonB, k: i32) -> Vec<i32> {
let adj = parse_matrix(&adj_json);
if adj.is_empty() {
return Vec::new();
@ -307,10 +292,7 @@ pub fn ruvector_spherical_distance(a: Vec<f32>, b: Vec<f32>) -> f32 {
/// Compute Gromov-Wasserstein distance between two metric spaces.
#[pg_extern(immutable, parallel_safe)]
pub fn ruvector_gromov_wasserstein(
pts_a_json: JsonB,
pts_b_json: JsonB,
) -> JsonB {
pub fn ruvector_gromov_wasserstein(pts_a_json: JsonB, pts_b_json: JsonB) -> JsonB {
let pts_a = parse_points(&pts_a_json);
let pts_b = parse_points(&pts_b_json);
@ -320,13 +302,11 @@ pub fn ruvector_gromov_wasserstein(
let gw = GromovWasserstein::new(0.1);
match gw.solve(&pts_a, &pts_b) {
Ok(result) => {
JsonB(serde_json::json!({
"distance": result.loss.sqrt(),
"converged": result.converged,
"coupling": result.transport_plan,
}))
}
Ok(result) => JsonB(serde_json::json!({
"distance": result.loss.sqrt(),
"converged": result.converged,
"coupling": result.transport_plan,
})),
Err(e) => pgrx::error!("Gromov-Wasserstein failed: {}", e),
}
}

View file

@ -11,7 +11,9 @@ pub fn edges_json_to_csr(json: &serde_json::Value) -> Result<CsrMatrix<f64>, Str
.get("edges")
.and_then(|e| e.as_array())
.or_else(|| json.as_array())
.ok_or_else(|| "Expected JSON object with 'edges' array or a JSON array of edges".to_string())?;
.ok_or_else(|| {
"Expected JSON object with 'edges' array or a JSON array of edges".to_string()
})?;
if edges.is_empty() {
return Err("Edge list is empty".to_string());
@ -47,14 +49,24 @@ pub fn edges_json_to_csr(json: &serde_json::Value) -> Result<CsrMatrix<f64>, Str
pub fn matrix_json_to_csr(json: &serde_json::Value) -> Result<CsrMatrix<f64>, String> {
// Structured format with rows/cols
if let Some(entries) = json.get("entries").and_then(|e| e.as_array()) {
let rows = json.get("rows").and_then(|r| r.as_u64()).ok_or("Missing 'rows'")? as usize;
let cols = json.get("cols").and_then(|c| c.as_u64()).ok_or("Missing 'cols'")? as usize;
let rows = json
.get("rows")
.and_then(|r| r.as_u64())
.ok_or("Missing 'rows'")? as usize;
let cols = json
.get("cols")
.and_then(|c| c.as_u64())
.ok_or("Missing 'cols'")? as usize;
let coo: Vec<(usize, usize, f64)> = entries
.iter()
.filter_map(|e| {
let a = e.as_array()?;
Some((a[0].as_u64()? as usize, a[1].as_u64()? as usize, a[2].as_f64()?))
Some((
a[0].as_u64()? as usize,
a[1].as_u64()? as usize,
a[2].as_f64()?,
))
})
.collect();

View file

@ -165,10 +165,7 @@ pub fn ruvector_solve_sparse(
/// Solve a graph Laplacian system Lx=b.
#[pg_extern(immutable, parallel_safe)]
pub fn ruvector_solve_laplacian(
laplacian_json: JsonB,
rhs: Vec<f32>,
) -> JsonB {
pub fn ruvector_solve_laplacian(laplacian_json: JsonB, rhs: Vec<f32>) -> JsonB {
let csr = match matrix_json_to_csr(&laplacian_json.0) {
Ok(m) => m,
Err(e) => pgrx::error!("Laplacian solve: {}", e),
@ -192,11 +189,7 @@ pub fn ruvector_solve_laplacian(
/// Compute effective resistance between two nodes.
#[pg_extern(immutable, parallel_safe)]
pub fn ruvector_effective_resistance(
laplacian_json: JsonB,
source: i32,
target: i32,
) -> f32 {
pub fn ruvector_effective_resistance(laplacian_json: JsonB, source: i32, target: i32) -> f32 {
let csr = match matrix_json_to_csr(&laplacian_json.0) {
Ok(m) => m,
Err(e) => pgrx::error!("Effective resistance: {}", e),
@ -219,8 +212,16 @@ pub fn ruvector_effective_resistance(
Ok(res) => {
let s = source as usize;
let t = target as usize;
let x_s = if s < res.solution.len() { res.solution[s] as f64 } else { 0.0 };
let x_t = if t < res.solution.len() { res.solution[t] as f64 } else { 0.0 };
let x_s = if s < res.solution.len() {
res.solution[s] as f64
} else {
0.0
};
let x_t = if t < res.solution.len() {
res.solution[t] as f64
} else {
0.0
};
(x_s - x_t) as f32
}
Err(e) => pgrx::error!("Effective resistance failed: {}", e),
@ -307,18 +308,48 @@ pub fn ruvector_solver_info() -> TableIterator<
),
> {
let algos = vec![
("neumann", "Jacobi-preconditioned Neumann series", "O(nnz * log(1/eps))"),
("cg", "Conjugate Gradient for SPD systems", "O(n * sqrt(kappa))"),
("forward-push", "Andersen-Chung-Lang PageRank", "O(1/epsilon)"),
("backward-push", "Backward Push for target PPR", "O(1/epsilon)"),
("hybrid-random-walk", "Push + Monte Carlo sampling", "O(sqrt(n/epsilon))"),
("bmssp", "Block MSS preconditioned solver", "O(n * nnz_per_row)"),
("true-solver", "Topology-aware batch solver", "O(batch * nnz)"),
(
"neumann",
"Jacobi-preconditioned Neumann series",
"O(nnz * log(1/eps))",
),
(
"cg",
"Conjugate Gradient for SPD systems",
"O(n * sqrt(kappa))",
),
(
"forward-push",
"Andersen-Chung-Lang PageRank",
"O(1/epsilon)",
),
(
"backward-push",
"Backward Push for target PPR",
"O(1/epsilon)",
),
(
"hybrid-random-walk",
"Push + Monte Carlo sampling",
"O(sqrt(n/epsilon))",
),
(
"bmssp",
"Block MSS preconditioned solver",
"O(n * nnz_per_row)",
),
(
"true-solver",
"Topology-aware batch solver",
"O(batch * nnz)",
),
];
TableIterator::new(algos.into_iter().map(|(a, d, c)| {
(a.to_string(), d.to_string(), c.to_string())
}))
TableIterator::new(
algos
.into_iter()
.map(|(a, d, c)| (a.to_string(), d.to_string(), c.to_string())),
)
}
/// Analyze matrix sparsity profile.
@ -384,7 +415,8 @@ pub fn ruvector_conjugate_gradient(
..Default::default()
};
let solver = ruvector_solver::cg::ConjugateGradientSolver::new(tol as f64, max_iter as usize, true);
let solver =
ruvector_solver::cg::ConjugateGradientSolver::new(tol as f64, max_iter as usize, true);
match solver.solve(&csr, &rhs_f64, &budget) {
Ok(res) => JsonB(serde_json::json!({

View file

@ -3,8 +3,8 @@
pub mod operators;
use dashmap::DashMap;
use ruvector_sona::{SonaConfig, SonaEngine};
use std::sync::Arc;
use ruvector_sona::{SonaEngine, SonaConfig};
/// Global Sona engine state per table.
static SONA_ENGINES: once_cell::sync::Lazy<DashMap<String, Arc<SonaEngine>>> =

View file

@ -7,10 +7,7 @@ use super::get_or_create_engine;
/// Record a learning trajectory for a table (Micro-LoRA).
#[pg_extern]
pub fn ruvector_sona_learn(
table_name: &str,
trajectory_json: JsonB,
) -> JsonB {
pub fn ruvector_sona_learn(table_name: &str, trajectory_json: JsonB) -> JsonB {
let engine = get_or_create_engine(table_name);
// Parse trajectory: {"initial": [f32...], "steps": [{"embedding": [f32...], "actions": [...], "reward": f32}]}
@ -56,10 +53,7 @@ pub fn ruvector_sona_learn(
})
.unwrap_or_default();
let reward = step
.get("reward")
.and_then(|v| v.as_f64())
.unwrap_or(0.0) as f32;
let reward = step.get("reward").and_then(|v| v.as_f64()).unwrap_or(0.0) as f32;
builder.add_step(embedding, attention_weights, reward);
}
@ -82,10 +76,7 @@ pub fn ruvector_sona_learn(
/// Apply learned LoRA transformation to an embedding.
#[pg_extern(immutable, parallel_safe)]
pub fn ruvector_sona_apply(
table_name: &str,
embedding: Vec<f32>,
) -> Vec<f32> {
pub fn ruvector_sona_apply(table_name: &str, embedding: Vec<f32>) -> Vec<f32> {
let engine = get_or_create_engine(table_name);
let mut output = vec![0.0f32; embedding.len()];

View file

@ -4,8 +4,8 @@ use pgrx::prelude::*;
use pgrx::JsonB;
use ruvector_math::homology::{
BottleneckDistance, PersistenceDiagram, PersistentHomology, VietorisRips, WassersteinDistance,
BirthDeathPair, PointCloud, Point,
BirthDeathPair, BottleneckDistance, PersistenceDiagram, PersistentHomology, Point, PointCloud,
VietorisRips, WassersteinDistance,
};
/// Helper: parse a JsonB array of points into a PointCloud.
@ -118,10 +118,7 @@ pub fn ruvector_betti_numbers(
/// Compute bottleneck distance between two persistence diagrams.
#[pg_extern(immutable, parallel_safe)]
pub fn ruvector_bottleneck_distance(
diag_a_json: JsonB,
diag_b_json: JsonB,
) -> f32 {
pub fn ruvector_bottleneck_distance(diag_a_json: JsonB, diag_b_json: JsonB) -> f32 {
let diag_a = parse_diagram(&diag_a_json);
let diag_b = parse_diagram(&diag_b_json);
@ -144,10 +141,7 @@ pub fn ruvector_persistence_wasserstein(
/// Compute topological summary (Betti numbers + persistence statistics + entropy).
#[pg_extern(immutable, parallel_safe)]
pub fn ruvector_topological_summary(
points_json: JsonB,
max_dim: default!(i32, 1),
) -> JsonB {
pub fn ruvector_topological_summary(points_json: JsonB, max_dim: default!(i32, 1)) -> JsonB {
let cloud = parse_point_cloud(&points_json);
if cloud.is_empty() {
return JsonB(serde_json::json!({}));
@ -210,10 +204,7 @@ pub fn ruvector_topological_summary(
/// Detect topological drift between old and new embeddings.
#[pg_extern(immutable, parallel_safe)]
pub fn ruvector_embedding_drift(
old_json: JsonB,
new_json: JsonB,
) -> JsonB {
pub fn ruvector_embedding_drift(old_json: JsonB, new_json: JsonB) -> JsonB {
let old_cloud = parse_point_cloud(&old_json);
let new_cloud = parse_point_cloud(&new_json);
@ -281,7 +272,8 @@ pub fn ruvector_vietoris_rips(
})
.collect();
let mut simplex_counts: std::collections::HashMap<usize, usize> = std::collections::HashMap::new();
let mut simplex_counts: std::collections::HashMap<usize, usize> =
std::collections::HashMap::new();
for fs in &filtration.simplices {
*simplex_counts.entry(fs.simplex.dim()).or_insert(0) += 1;
}