///|
fn format_doubles(values : Array[Double]) -> String {
let mut result = "["
let mut index = 0
while index < values.length() {
if index > 0 {
result = result + ", "
}
result = result + values[index].to_string()
index = index + 1
}
result + "]"
}
///|
fn format_ints(values : Array[Int32]) -> String {
let mut result = "["
let mut index = 0
while index < values.length() {
if index > 0 {
result = result + ", "
}
result = result + values[index].to_string()
index = index + 1
}
result + "]"
}
///|
fn format_matrix(values : Array[Array[Double]]) -> String {
let mut result = "["
let mut row = 0
while row < values.length() {
if row > 0 {
result = result + ", "
}
result = result + format_doubles(values[row])
row = row + 1
}
result + "]"
}
///|
fn main {
println("=== Bioconductor SparseArray Demo ===\n")
let tensor = @src.sparse_array_sample() catch {
_ => abort("failed to create sparse tensor")
}
let tensor_summary = tensor.summary() catch {
_ => abort("failed to summarize sparse tensor")
}
let tensor_value = tensor.get([0, 4, 1]) catch {
_ => abort("failed to access sparse tensor")
}
println("1. Multidimensional sparse tensor")
println(" " + tensor_summary)
println(" value[0, 4, 1] = " + tensor_value.to_string())
println(
" stored coordinates = " + tensor.nzcoordinates().length().to_string(),
)
let permuted = tensor.aperm([2, 0, 1]) catch {
_ => abort("failed to permute sparse tensor")
}
let permuted_summary = permuted.summary() catch {
_ => abort("failed to summarize permuted tensor")
}
let permuted_value = permuted.get([1, 0, 4]) catch {
_ => abort("failed to access permuted tensor")
}
println("\n2. Dimension permutation")
println(" " + permuted_summary)
println(" old [0, 4, 1] -> new [1, 0, 4] = " + permuted_value.to_string())
let sliced = tensor.slice([0, 0, 1], [4, 5, 2]) catch {
_ => abort("failed to slice sparse tensor")
}
let sliced_summary = sliced.summary() catch {
_ => abort("failed to summarize sparse slice")
}
println("\n3. Sparse slice without dense materialization")
println(" " + sliced_summary)
let counts = @src.SparseArray::from_matrix([
[1.0, 0.0, 2.0],
[0.0, 3.0, 0.0],
[4.0, 0.0, 5.0],
]) catch {
_ => abort("failed to create sparse count matrix")
}
let counts_summary = counts.summary() catch {
_ => abort("failed to summarize sparse count matrix")
}
let row_sums = counts.row_sums() catch {
_ => abort("failed to compute row sums")
}
let column_sums = counts.column_sums() catch {
_ => abort("failed to compute column sums")
}
let row_nonzero_counts = counts.row_nonzero_counts() catch {
_ => abort("failed to count row nonzero values")
}
println("\n4. Matrix summaries")
println(" " + counts_summary)
println(" row sums: " + format_doubles(row_sums))
println(" column sums: " + format_doubles(column_sums))
println(" row nonzero counts: " + format_ints(row_nonzero_counts))
let design = @src.SparseArray::from_matrix([
[1.0, 0.0],
[0.0, 1.0],
[1.0, 1.0],
]) catch {
_ => abort("failed to create sparse design matrix")
}
let product = counts.matmul(design) catch {
_ => abort("failed to multiply sparse matrices")
}
println("\n5. Sparse matrix multiplication")
println(" result: " + format_matrix(product))
let normalized = counts.scale(0.5) catch {
_ => abort("failed to scale sparse matrix")
}
let combined = counts.add(normalized) catch {
_ => abort("failed to add sparse matrices")
}
let combined_summary = combined.summary() catch {
_ => abort("failed to summarize sparse arithmetic result")
}
let dense_combined = combined.to_dense_matrix() catch {
_ => abort("failed to materialize sparse arithmetic result")
}
println("\n6. Sparse arithmetic")
println(" counts + counts * 0.5: " + combined_summary)
println(" dense view: " + format_matrix(dense_combined))
}