@@ -1112,14 +1112,22 @@ module ChapelArray {
1112
1112
// Compute which dimensions are collapsed and what the index
1113
1113
// (idx) is in the event that it is. These will be stored in
1114
1114
// the array view to convert from lower-D indices to higher-D.
1115
+ // Also compute the upward-facing rank and tuple of ranges.
1115
1116
//
1116
1117
var collapsedDim: rank* bool ;
1117
1118
var idx: rank* idxType;
1119
+ param uprank = chpl__countRanges((...args));
1120
+ param upstridable = this .stridable || chpl__anyRankChangeStridable(args);
1121
+ var upranges: uprank* range (idxType= _value.idxType,
1122
+ stridable= upstridable);
1123
+ var updim = 1 ;
1118
1124
1119
1125
for param i in 1 ..rank {
1120
1126
if (isRange(args(i))) {
1121
1127
collapsedDim(i) = false ;
1122
1128
idx(i) = dim(i).alignedLow;
1129
+ upranges(updim) = this ._value.dsiDim(i)[ args(i)] ; // intersect ranges
1130
+ updim += 1 ;
1123
1131
} else {
1124
1132
collapsedDim(i) = true ;
1125
1133
idx(i) = args(i);
@@ -1128,9 +1136,7 @@ module ChapelArray {
1128
1136
1129
1137
// Create distribution, domain, and array objects representing
1130
1138
// the array view
1131
- var upranges = _getRankChangeRanges(args, this ._value);
1132
1139
const emptyrange: upranges(1 ).type ;
1133
- param uprank = upranges.size;
1134
1140
//
1135
1141
// If idx isn't in the original domain, we need to generate an
1136
1142
// empty upward facing domain (intersection is empty)
@@ -3100,13 +3106,33 @@ module ChapelArray {
3100
3106
3101
3107
3102
3108
// computes || reduction over stridable of ranges
3103
- proc chpl__anyStridable (ranges, param d : int = 1 ) param {
3109
+ proc chpl__anyStridable (ranges) param {
3104
3110
for param i in 1 ..ranges.size do
3105
3111
if ranges(i).stridable then
3106
3112
return true ;
3107
3113
return false ;
3108
3114
}
3109
3115
3116
+ // computes || reduction over stridable of ranges, but permits some
3117
+ // elements not to be ranges (as in a rank-change slice)
3118
+ proc chpl__anyRankChangeStridable (args) param {
3119
+ for param i in 1 ..args.size do
3120
+ if isRangeValue(args(i)) then
3121
+ if args(i).stridable then
3122
+ return true ;
3123
+ return false ;
3124
+ }
3125
+
3126
+ // the following pair of routines counts the number of ranges in its
3127
+ // argument list and is used for rank-change slices
3128
+ proc chpl__countRanges (arg) param {
3129
+ return isRangeValue(arg): int ;
3130
+ }
3131
+
3132
+ proc chpl__countRanges (arg, args...) param {
3133
+ return chpl__countRanges(arg) + chpl__countRanges((...args));
3134
+ }
3135
+
3110
3136
// given a tuple args, returns true if the tuple contains only
3111
3137
// integers and ranges; that is, it is a valid argument list for rank
3112
3138
// change
@@ -3147,38 +3173,6 @@ module ChapelArray {
3147
3173
// return help(1);
3148
3174
}
3149
3175
3150
- proc _getRankChangeRanges (args, downdom) {
3151
- return collectRanges(1 );
3152
-
3153
- proc collectRanges (param dim: int ) {
3154
- if isRange(args(dim)) {
3155
- const newRange = downdom.dsiDim(dim)[ args(dim)] ; // intersect ranges
3156
- return collectRanges(dim+ 1 , (newRange,));
3157
- } else
3158
- return collectRanges(dim+ 1 );
3159
- }
3160
-
3161
- proc collectRanges (param dim: int , x: _tuple) {
3162
- if dim > args.size {
3163
- return x;
3164
- } else if dim < args.size {
3165
- if isRange(args(dim)) {
3166
- const newRange = downdom.dsiDim(dim)[ args(dim)] ; // intersect ranges
3167
- return collectRanges(dim+ 1 , ((...x), newRange));
3168
- } else {
3169
- return collectRanges(dim+ 1 , x);
3170
- }
3171
- } else {
3172
- if isRange(args(dim)) {
3173
- const newRange = downdom.dsiDim(dim)[ args(dim)] ; // intersect ranges
3174
- return ((...x), newRange);
3175
- } else {
3176
- return x;
3177
- }
3178
- }
3179
- }
3180
- }
3181
-
3182
3176
//
3183
3177
// Assignment of domains and arrays
3184
3178
//
0 commit comments