So of course it's easy to create a domain (and from that, an array) with fixed known rank and array of sizes,
proc do_something(sizes: [1..2] int) {
  const D: domain(2) = {1..sizes[1], 1..sizes[2]};
  var arr: [D] int;
    // ...
}
But what does one do with an array of varying sizes, of runtime-determined (or at least not hardcoded-in) length?
proc do_something_2(sizes: [?sd] int) {
  const rank = sd.rank;
  var D: domain(rank); 
  var arr: [D] int; 
  writeln(arr);
}
The line var D: domain(rank); fails, as it seems to need a param rank - but even if that worked it's not clear how to set the domain afterwards; expand seems like it expands the domain in both directions.
You can assign a domain from a tuple of ranges:
var tup = (1..10,2..20);
var D : domain(2) = tup;
The param modifier will work. Here is an example where I take in a domain, create a domain one dimension larger, and return an array on it.
proc dimensionalExpansion( dom : domain ) {
  // Get and expand rank
  param oldRank = dom.rank;
  param newRank = oldRank+1;
  // create tuple of size newRank to store each dimensions ranges
  var ranges : newRank*range(dom.idxType, BoundedRangeType.bounded, dom.stridable);
  // copy range from domain
  for i in 1..#oldRank do ranges[i] = dom.dim(i);
  // use last range from domain as our last range
  ranges[newRank] = ranges[oldRank];
  // Create new domain from ranges tuple
  var D: domain(newRank) = ranges;
  // Create array
  var arr: [D] int;
  // Putting some arbitrary values into the array;
  for idx in D {
    arr[idx] = if newRank > 1 then idx[newRank] - idx[1] else idx; 
  }
  return arr;
}
writeln( "==================" );
writeln( dimensionalExpansion( {1..3} ) );
writeln( "==================" );
writeln( dimensionalExpansion( {1..3,1..3} ) );
writeln( "==================" );
writeln( dimensionalExpansion( {1..3,1..3,1..3} ) );
Running TIO Instance
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With