diff --git a/modules/internal/ChapelArray.chpl b/modules/internal/ChapelArray.chpl index bee16647faa8..858f0983a889 100644 --- a/modules/internal/ChapelArray.chpl +++ b/modules/internal/ChapelArray.chpl @@ -1112,14 +1112,22 @@ module ChapelArray { // Compute which dimensions are collapsed and what the index // (idx) is in the event that it is. These will be stored in // the array view to convert from lower-D indices to higher-D. + // Also compute the upward-facing rank and tuple of ranges. // var collapsedDim: rank*bool; var idx: rank*idxType; + param uprank = chpl__countRanges((...args)); + param upstridable = this.stridable || chpl__anyRankChangeStridable(args); + var upranges: uprank*range(idxType=_value.idxType, + stridable=upstridable); + var updim = 1; for param i in 1..rank { if (isRange(args(i))) { collapsedDim(i) = false; idx(i) = dim(i).alignedLow; + upranges(updim) = this._value.dsiDim(i)[args(i)]; // intersect ranges + updim += 1; } else { collapsedDim(i) = true; idx(i) = args(i); @@ -1128,9 +1136,7 @@ module ChapelArray { // Create distribution, domain, and array objects representing // the array view - var upranges = _getRankChangeRanges(args, this._value); const emptyrange: upranges(1).type; - param uprank = upranges.size; // // If idx isn't in the original domain, we need to generate an // empty upward facing domain (intersection is empty) @@ -3100,13 +3106,33 @@ module ChapelArray { // computes || reduction over stridable of ranges - proc chpl__anyStridable(ranges, param d: int = 1) param { + proc chpl__anyStridable(ranges) param { for param i in 1..ranges.size do if ranges(i).stridable then return true; return false; } + // computes || reduction over stridable of ranges, but permits some + // elements not to be ranges (as in a rank-change slice) + proc chpl__anyRankChangeStridable(args) param { + for param i in 1..args.size do + if isRangeValue(args(i)) then + if args(i).stridable then + return true; + return false; + } + + // the following pair of routines counts the number of ranges in its + // argument list and is used for rank-change slices + proc chpl__countRanges(arg) param { + return isRangeValue(arg):int; + } + + proc chpl__countRanges(arg, args...) param { + return chpl__countRanges(arg) + chpl__countRanges((...args)); + } + // given a tuple args, returns true if the tuple contains only // integers and ranges; that is, it is a valid argument list for rank // change @@ -3147,38 +3173,6 @@ module ChapelArray { //return help(1); } - proc _getRankChangeRanges(args, downdom) { - return collectRanges(1); - - proc collectRanges(param dim: int) { - if isRange(args(dim)) { - const newRange = downdom.dsiDim(dim)[args(dim)]; // intersect ranges - return collectRanges(dim+1, (newRange,)); - } else - return collectRanges(dim+1); - } - - proc collectRanges(param dim: int, x: _tuple) { - if dim > args.size { - return x; - } else if dim < args.size { - if isRange(args(dim)) { - const newRange = downdom.dsiDim(dim)[args(dim)]; // intersect ranges - return collectRanges(dim+1, ((...x), newRange)); - } else { - return collectRanges(dim+1, x); - } - } else { - if isRange(args(dim)) { - const newRange = downdom.dsiDim(dim)[args(dim)]; // intersect ranges - return ((...x), newRange); - } else { - return x; - } - } - } - } - // // Assignment of domains and arrays // diff --git a/test/arrays/rankChange/rankChangeMixStridables.chpl b/test/arrays/rankChange/rankChangeMixStridables.chpl new file mode 100644 index 000000000000..97046fd317c3 --- /dev/null +++ b/test/arrays/rankChange/rankChangeMixStridables.chpl @@ -0,0 +1,8 @@ +config const n = 5; +config const it = 3; + +var b: [0..n+1, 0..n+1, 0..1] bool; + +b[2..n-1 by 2, 2..n-1, 0] = true; + +writeln(b); diff --git a/test/arrays/rankChange/rankChangeMixStridables.good b/test/arrays/rankChange/rankChangeMixStridables.good new file mode 100644 index 000000000000..28def4a62aeb --- /dev/null +++ b/test/arrays/rankChange/rankChangeMixStridables.good @@ -0,0 +1,55 @@ +false false +false false +false false +false false +false false +false false +false false + +false false +false false +false false +false false +false false +false false +false false + +false false +false false +true false +true false +true false +false false +false false + +false false +false false +false false +false false +false false +false false +false false + +false false +false false +true false +true false +true false +false false +false false + +false false +false false +false false +false false +false false +false false +false false + +false false +false false +false false +false false +false false +false false +false false