Skip to content

Commit da19903

Browse files
authored
Merge pull request #399 from tensor4all/feat/capi-linop-swap
feat(capi): add t4a_treetn_swap_site_indices
2 parents 3f05ea8 + 092c12b commit da19903

1 file changed

Lines changed: 60 additions & 0 deletions

File tree

crates/tensor4all-capi/src/treetn.rs

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1233,6 +1233,66 @@ pub extern "C" fn t4a_treetn_linsolve(
12331233
crate::unwrap_catch(result)
12341234
}
12351235

1236+
// ============================================================================
1237+
// Swap site indices
1238+
// ============================================================================
1239+
1240+
/// Swap site indices on a TreeTN to a target assignment.
1241+
///
1242+
/// Rearranges site indices so that each specified index ends up at its
1243+
/// target vertex. Values are preserved via SVD factorization.
1244+
///
1245+
/// # Arguments
1246+
/// * `ttn` - Tree tensor network (modified in place)
1247+
/// * `index_ids` - Array of index IDs (u64) to move
1248+
/// * `target_vertices` - Array of target vertex numbers (same length as index_ids)
1249+
/// * `n_pairs` - Number of (index_id, target_vertex) pairs
1250+
/// * `max_rank` - Maximum bond dimension after SVD (0 = no limit)
1251+
/// * `rtol` - Relative SVD truncation tolerance (0.0 = no truncation)
1252+
#[unsafe(no_mangle)]
1253+
pub extern "C" fn t4a_treetn_swap_site_indices(
1254+
ttn: *mut t4a_treetn,
1255+
index_ids: *const u64,
1256+
target_vertices: *const libc::size_t,
1257+
n_pairs: libc::size_t,
1258+
max_rank: libc::size_t,
1259+
rtol: libc::c_double,
1260+
) -> StatusCode {
1261+
if ttn.is_null() {
1262+
return T4A_NULL_POINTER;
1263+
}
1264+
if n_pairs > 0 && (index_ids.is_null() || target_vertices.is_null()) {
1265+
return T4A_NULL_POINTER;
1266+
}
1267+
1268+
let result = catch_unwind(AssertUnwindSafe(|| {
1269+
use std::collections::HashMap;
1270+
use tensor4all_core::defaults::index::DynId;
1271+
use tensor4all_treetn::treetn::SwapOptions;
1272+
1273+
let inner = unsafe { &mut *ttn }.inner_mut();
1274+
1275+
let mut target_map: HashMap<DynId, usize> = HashMap::new();
1276+
for i in 0..n_pairs {
1277+
let id = DynId(unsafe { *index_ids.add(i) });
1278+
let vertex = unsafe { *target_vertices.add(i) };
1279+
target_map.insert(id, vertex);
1280+
}
1281+
1282+
let opts = SwapOptions {
1283+
max_rank: if max_rank == 0 { None } else { Some(max_rank) },
1284+
rtol: if rtol == 0.0 { None } else { Some(rtol) },
1285+
};
1286+
1287+
match inner.swap_site_indices(&target_map, &opts) {
1288+
Ok(()) => T4A_SUCCESS,
1289+
Err(e) => crate::err_status(e, crate::T4A_INTERNAL_ERROR),
1290+
}
1291+
}));
1292+
1293+
crate::unwrap_catch(result)
1294+
}
1295+
12361296
// ============================================================================
12371297
// Tests
12381298
// ============================================================================

0 commit comments

Comments
 (0)