@@ -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