| 52 | // RETURN: ndims |
| 53 | template<typename T> |
| 54 | T removeEmptyColumns(const T refDims[AF_MAX_DIMS], const T refNdims, |
| 55 | T dims[AF_MAX_DIMS], T strides[AF_MAX_DIMS]) { |
| 56 | T ndims{0}; |
| 57 | const T* refPtr{refDims}; |
| 58 | const T* refPtr_end{refDims + refNdims}; |
| 59 | // Search for first dimension == 1 |
| 60 | while (refPtr != refPtr_end && *refPtr != 1) { |
| 61 | ++refPtr; |
| 62 | ++ndims; |
| 63 | } |
| 64 | if (ndims != refNdims) { |
| 65 | T* dPtr_out{dims + ndims}; |
| 66 | const T* dPtr_in{dPtr_out}; |
| 67 | T* sPtr_out{strides + ndims}; |
| 68 | const T* sPtr_in{sPtr_out}; |
| 69 | // Compress all remaining dimensions |
| 70 | while (refPtr != refPtr_end) { |
| 71 | if (*refPtr != 1) { |
| 72 | *(dPtr_out++) = *dPtr_in; |
| 73 | *(sPtr_out++) = *sPtr_in; |
| 74 | ++ndims; |
| 75 | } |
| 76 | ++refPtr; |
| 77 | ++dPtr_in; |
| 78 | ++sPtr_in; |
| 79 | } |
| 80 | // Fill remaining dimensions with 1 and calculate corresponding strides |
| 81 | // lastStride = last written dim * last written stride |
| 82 | const T lastStride{*(dPtr_out - 1) * *(sPtr_out - 1)}; |
| 83 | const T lastDim{1}; |
| 84 | for (const T* dPtr_end{dims + AF_MAX_DIMS}; dPtr_out != dPtr_end; |
| 85 | ++dPtr_out, ++sPtr_out) { |
| 86 | *dPtr_out = lastDim; |
| 87 | *sPtr_out = lastStride; |
| 88 | } |
| 89 | } |
| 90 | return ndims; |
| 91 | } |
| 92 | |
| 93 | // Empty columns (dim==1) in refDims are removed from strides |
| 94 | // ASSUMPTION: dims are equal to refDims, so are not provided |