@@ -188,6 +188,176 @@ impl<T> ValueMesh<T> {
188
188
}
189
189
}
190
190
191
+ impl < T : Clone > ValueMesh < T > {
192
+ /// Builds a `ValueMesh` that assigns the single value `s` to
193
+ /// every rank in `region`, without materializing a dense
194
+ /// `Vec<T>`. The result is stored in compressed (RLE) form as a
195
+ /// single run `[0..N)`.
196
+ ///
197
+ /// If `region.num_ranks() == 0`, the mesh contains no runs (and
198
+ /// an empty table), regardless of `s`.
199
+ pub fn from_single ( region : Region , s : T ) -> Self {
200
+ let n = region. num_ranks ( ) ;
201
+ if n == 0 {
202
+ return Self {
203
+ region,
204
+ rep : Rep :: Compressed {
205
+ table : Vec :: new ( ) ,
206
+ runs : Vec :: new ( ) ,
207
+ } ,
208
+ } ;
209
+ }
210
+
211
+ let table = vec ! [ s] ;
212
+ let runs = vec ! [ Run :: new( 0 , n, 0 ) ] ;
213
+ Self {
214
+ region,
215
+ rep : Rep :: Compressed { table, runs } ,
216
+ }
217
+ }
218
+ }
219
+
220
+ impl < T : Clone + Default > ValueMesh < T > {
221
+ /// Builds a [`ValueMesh`] covering the region, filled with
222
+ /// `T::default()`.
223
+ ///
224
+ /// Equivalent to [`ValueMesh::from_single(region,
225
+ /// T::default())`].
226
+ pub fn from_default ( region : Region ) -> Self {
227
+ ValueMesh :: < T > :: from_single ( region, T :: default ( ) )
228
+ }
229
+ }
230
+
231
+ impl < T : Clone + PartialEq > ValueMesh < T > {
232
+ /// Builds a compressed mesh from a default value and a set of
233
+ /// disjoint ranges that override the default.
234
+ ///
235
+ /// - `ranges` may be in any order; they must be non-empty,
236
+ /// in-bounds, and non-overlapping.
237
+ /// - Unspecified ranks are filled with `default`.
238
+ /// - Result is stored in RLE form; no dense `Vec<T>` is
239
+ /// materialized.
240
+ pub fn from_ranges_with_default (
241
+ region : Region ,
242
+ default : T ,
243
+ mut ranges : Vec < ( Range < usize > , T ) > ,
244
+ ) -> crate :: v1:: Result < Self > {
245
+ let n = region. num_ranks ( ) ;
246
+
247
+ if n == 0 {
248
+ return Ok ( Self {
249
+ region,
250
+ rep : Rep :: Compressed {
251
+ table : Vec :: new ( ) ,
252
+ runs : Vec :: new ( ) ,
253
+ } ,
254
+ } ) ;
255
+ }
256
+
257
+ // Validate: non-empty, in-bounds; then sort.
258
+ for ( r, _) in & ranges {
259
+ if r. is_empty ( ) {
260
+ return Err ( crate :: v1:: Error :: InvalidRankCardinality {
261
+ expected : n,
262
+ actual : 0 ,
263
+ } ) ; // TODO: this surfaces the error but its not a great fit
264
+ }
265
+ if r. end > n {
266
+ return Err ( crate :: v1:: Error :: InvalidRankCardinality {
267
+ expected : n,
268
+ actual : r. end ,
269
+ } ) ;
270
+ }
271
+ }
272
+ ranges. sort_by_key ( |( r, _) | ( r. start , r. end ) ) ;
273
+
274
+ // Validate: non-overlapping.
275
+ for w in ranges. windows ( 2 ) {
276
+ let ( a, _) = & w[ 0 ] ;
277
+ let ( b, _) = & w[ 1 ] ;
278
+ if a. end > b. start {
279
+ // Overlap
280
+ return Err ( crate :: v1:: Error :: InvalidRankCardinality {
281
+ expected : n,
282
+ actual : b. start , // TODO: this surfaces the error but is a bad fit
283
+ } ) ;
284
+ }
285
+ }
286
+
287
+ // Build table; keep it small by reusing equal values.
288
+ fn get_or_insert_id < T : PartialEq + Clone > ( table : & mut Vec < T > , v : & T ) -> u32 {
289
+ if let Some ( idx) = table. iter ( ) . position ( |x| x == v) {
290
+ idx as u32
291
+ } else {
292
+ table. push ( v. clone ( ) ) ;
293
+ ( table. len ( ) - 1 ) as u32
294
+ }
295
+ }
296
+
297
+ let mut table: Vec < T > = Vec :: with_capacity ( 1 + ranges. len ( ) ) ;
298
+ let default_id = get_or_insert_id ( & mut table, & default) ;
299
+
300
+ let mut runs: Vec < Run > = Vec :: with_capacity ( 1 + 2 * ranges. len ( ) ) ;
301
+ let mut cursor = 0usize ;
302
+
303
+ for ( r, v) in ranges. into_iter ( ) {
304
+ // Fill default gap if any.
305
+ if cursor < r. start {
306
+ runs. push ( Run :: new ( cursor, r. start , default_id) ) ;
307
+ }
308
+ // Override block.
309
+ let id = get_or_insert_id ( & mut table, & v) ;
310
+ runs. push ( Run :: new ( r. start , r. end , id) ) ;
311
+ cursor = r. end ;
312
+ }
313
+
314
+ // Trailing default tail.
315
+ if cursor < n {
316
+ runs. push ( Run :: new ( cursor, n, default_id) ) ;
317
+ }
318
+
319
+ Ok ( Self {
320
+ region,
321
+ rep : Rep :: Compressed { table, runs } ,
322
+ } )
323
+ }
324
+
325
+ /// Builds a [`ValueMesh`] from a fully materialized dense vector
326
+ /// of per-rank values, then compresses it into run-length–encoded
327
+ /// form if possible.
328
+ ///
329
+ /// This constructor is intended for callers that already have one
330
+ /// value per rank (e.g. computed or received data) but wish to
331
+ /// store it efficiently.
332
+ ///
333
+ /// # Parameters
334
+ /// - `region`: The logical region describing the mesh’s shape and
335
+ /// rank order.
336
+ /// - `values`: A dense vector of values, one per rank in
337
+ /// `region`.
338
+ ///
339
+ /// # Returns
340
+ /// A [`ValueMesh`] whose internal representation is `Compressed`
341
+ /// if any adjacent elements are equal, or `Dense` if no
342
+ /// compression was possible.
343
+ ///
344
+ /// # Errors
345
+ /// Returns an error if the number of provided `values` does not
346
+ /// match the number of ranks in `region`.
347
+ ///
348
+ /// # Examples
349
+ /// ```ignore
350
+ /// let region: Region = extent!(n = 5).into();
351
+ /// let mesh = ValueMesh::from_dense(region, vec![1, 1, 2, 2, 3]).unwrap();
352
+ /// // Internally compressed to three runs: [1, 1], [2, 2], [3]
353
+ /// ```
354
+ pub fn from_dense ( region : Region , values : Vec < T > ) -> crate :: v1:: Result < Self > {
355
+ let mut vm = Self :: new ( region, values) ?;
356
+ vm. compress_adjacent_in_place ( ) ;
357
+ Ok ( vm)
358
+ }
359
+ }
360
+
191
361
impl < F : Future > ValueMesh < F > {
192
362
/// Await all futures in the mesh, yielding a `ValueMesh` of their
193
363
/// outputs.
@@ -1414,4 +1584,97 @@ mod tests {
1414
1584
assert_eq ! ( range, 0 ..10 ) ;
1415
1585
assert_eq ! ( id, 42 ) ;
1416
1586
}
1587
+
1588
+ #[ test]
1589
+ fn from_single_builds_single_run ( ) {
1590
+ let region: Region = extent ! ( n = 6 ) . into ( ) ;
1591
+ let vm = ValueMesh :: from_single ( region. clone ( ) , 7 ) ;
1592
+
1593
+ assert_eq ! ( vm. region( ) , & region) ;
1594
+ assert_eq ! ( vm. values( ) . collect:: <Vec <_>>( ) , vec![ 7 , 7 , 7 , 7 , 7 , 7 ] ) ;
1595
+ assert_eq ! ( vm. get( 0 ) , Some ( & 7 ) ) ;
1596
+ assert_eq ! ( vm. get( 5 ) , Some ( & 7 ) ) ;
1597
+ assert_eq ! ( vm. get( 6 ) , None ) ;
1598
+ }
1599
+
1600
+ #[ test]
1601
+ fn from_default_builds_with_default_value ( ) {
1602
+ let region: Region = extent ! ( n = 6 ) . into ( ) ;
1603
+ let vm = ValueMesh :: < i32 > :: from_default ( region. clone ( ) ) ;
1604
+
1605
+ assert_eq ! ( vm. region( ) , & region) ;
1606
+ // i32::default() == 0
1607
+ assert_eq ! ( vm. values( ) . collect:: <Vec <_>>( ) , vec![ 0 , 0 , 0 , 0 , 0 , 0 ] ) ;
1608
+ assert_eq ! ( vm. get( 0 ) , Some ( & 0 ) ) ;
1609
+ assert_eq ! ( vm. get( 5 ) , Some ( & 0 ) ) ;
1610
+ }
1611
+
1612
+ #[ test]
1613
+ fn test_default_vs_single_equivalence ( ) {
1614
+ let region: Region = extent ! ( x = 4 ) . into ( ) ;
1615
+ let d1 = ValueMesh :: < i32 > :: from_default ( region. clone ( ) ) ;
1616
+ let d2 = ValueMesh :: from_single ( region. clone ( ) , 0 ) ;
1617
+ assert_eq ! ( d1, d2) ;
1618
+ }
1619
+
1620
+ #[ test]
1621
+ fn build_from_ranges_with_default_basic ( ) {
1622
+ let region: Region = extent ! ( n = 10 ) . into ( ) ;
1623
+ let vm = ValueMesh :: from_ranges_with_default (
1624
+ region. clone ( ) ,
1625
+ 0 , // default
1626
+ vec ! [ ( 2 ..4 , 1 ) , ( 6 ..9 , 2 ) ] ,
1627
+ )
1628
+ . unwrap ( ) ;
1629
+
1630
+ assert_eq ! ( vm. region( ) , & region) ;
1631
+ assert_eq ! (
1632
+ vm. values( ) . collect:: <Vec <_>>( ) ,
1633
+ vec![ 0 , 0 , 1 , 1 , 0 , 0 , 2 , 2 , 2 , 0 ]
1634
+ ) ;
1635
+
1636
+ // Internal shape: [0..2)->0, [2..4)->1, [4..6)->0, [6..9)->2,
1637
+ // [9..10)->0
1638
+ if let Rep :: Compressed { table, runs } = & vm. rep {
1639
+ // Table is small and de-duplicated.
1640
+ assert ! ( table. len( ) <= 3 ) ;
1641
+ assert_eq ! ( runs. len( ) , 5 ) ;
1642
+ } else {
1643
+ panic ! ( "expected compressed" ) ;
1644
+ }
1645
+ }
1646
+
1647
+ #[ test]
1648
+ fn build_from_ranges_with_default_edge_cases ( ) {
1649
+ let region: Region = extent ! ( n = 5 ) . into ( ) ;
1650
+
1651
+ // Full override covers entire region.
1652
+ let vm = ValueMesh :: from_ranges_with_default ( region. clone ( ) , 9 , vec ! [ ( 0 ..5 , 3 ) ] ) . unwrap ( ) ;
1653
+ assert_eq ! ( vm. values( ) . collect:: <Vec <_>>( ) , vec![ 3 , 3 , 3 , 3 , 3 ] ) ;
1654
+
1655
+ // Adjacent overrides and default gaps.
1656
+ let vm = ValueMesh :: from_ranges_with_default ( region. clone ( ) , 0 , vec ! [ ( 1 ..2 , 7 ) , ( 2 ..4 , 7 ) ] )
1657
+ . unwrap ( ) ;
1658
+ assert_eq ! ( vm. values( ) . collect:: <Vec <_>>( ) , vec![ 0 , 7 , 7 , 7 , 0 ] ) ;
1659
+
1660
+ // Empty region.
1661
+ let empty_region: Region = extent ! ( n = 0 ) . into ( ) ;
1662
+ let vm = ValueMesh :: from_ranges_with_default ( empty_region. clone ( ) , 42 , vec ! [ ] ) . unwrap ( ) ;
1663
+ assert_eq ! ( vm. values( ) . collect:: <Vec <_>>( ) , Vec :: <i32 >:: new( ) ) ;
1664
+ }
1665
+
1666
+ #[ test]
1667
+ fn from_dense_builds_and_compresses ( ) {
1668
+ let region: Region = extent ! ( n = 6 ) . into ( ) ;
1669
+ let mesh = ValueMesh :: from_dense ( region. clone ( ) , vec ! [ 1 , 1 , 2 , 2 , 3 , 3 ] ) . unwrap ( ) ;
1670
+
1671
+ assert_eq ! ( mesh. region( ) , & region) ;
1672
+ assert ! ( matches!( mesh. rep, Rep :: Compressed { .. } ) ) ;
1673
+ assert_eq ! ( mesh. values( ) . collect:: <Vec <_>>( ) , vec![ 1 , 1 , 2 , 2 , 3 , 3 ] ) ;
1674
+
1675
+ // Spot-check indexing.
1676
+ assert_eq ! ( mesh. get( 0 ) , Some ( & 1 ) ) ;
1677
+ assert_eq ! ( mesh. get( 3 ) , Some ( & 2 ) ) ;
1678
+ assert_eq ! ( mesh. get( 5 ) , Some ( & 3 ) ) ;
1679
+ }
1417
1680
}
0 commit comments