59{
60 int num_original_dims = _dense_shape.size();
61 int num_block_dims = _block_map.size();
62 int num_expanded_dims = num_original_dims + num_block_dims;
63 std::vector<int> expanded_shape(num_expanded_dims);
64 for (int i = 0; i < num_expanded_dims; i++)
65 {
66 if (i < num_original_dims)
67 {
68 expanded_shape.at(i) = _blocked_shape.at(i);
69 }
70 else
71 {
72 expanded_shape.at(i) = _block_size.at(i - num_original_dims);
73 }
74 }
75
76 std::vector<int> shape_offset(num_original_dims);
77 shape_offset.at(shape_offset.size() - 1) = 1;
78 for (int i = num_original_dims - 1; i > 0; --i)
79 {
80 shape_offset.at(i - 1) = shape_offset.at(i) * _dense_shape.at(i);
81 }
82
83 std::vector<int> expanded_shape_offset(num_expanded_dims);
84 for (int i = 0; i < num_original_dims; ++i)
85 {
86 expanded_shape_offset.at(i) = shape_offset.at(i);
87 }
88 for (int i = 0; i < num_block_dims; ++i)
89 {
90 int mapped_dim = _block_map.at(i);
91 expanded_shape_offset.at(num_original_dims + i) = shape_offset.at(mapped_dim);
92 expanded_shape_offset.at(mapped_dim) *= _block_size.at(i);
93 }
94
95 std::vector<int> dst_ordered_offset(num_expanded_dims);
96 for (int i = 0; i < num_expanded_dims; ++i)
97 {
98 dst_ordered_offset.at(i) = expanded_shape_offset.at(_traversal_order.at(i));
99 }
100
101 std::vector<bool> dst_dim_has_nonzeroes(num_expanded_dims);
102 std::fill(dst_dim_has_nonzeroes.begin(), dst_dim_has_nonzeroes.end(), false);
103 std::vector<int> inner_compressed_dim(num_expanded_dims);
104 int most_recent_compressed_dim = -1;
105 std::vector<int> num_segments_of_next_compressed_dim(num_expanded_dims);
106 int segment_count = 1;
107 for (int i = num_expanded_dims - 1; i >= 0; --i)
108 {
109 inner_compressed_dim.at(i) = most_recent_compressed_dim;
111 {
112 most_recent_compressed_dim = i;
113 num_segments_of_next_compressed_dim.at(i) = segment_count;
114 segment_count = 1;
115 }
116 else
117 {
118 num_segments_of_next_compressed_dim.at(i) = -1;
119 segment_count *= expanded_shape.at(_traversal_order.at(i));
120 }
121 }
122
123 _dim_metadata.resize(num_expanded_dims * 2);
124 std::vector<int> dst_sparse_dims;
125 dst_sparse_dims.reserve(num_expanded_dims);
126 for (int i = 0; i < num_expanded_dims; ++i)
127 {
128 _dim_metadata.at(i * 2).clear();
129 _dim_metadata.at(i * 2 + 1).clear();
131 {
132
133 _dim_metadata.at(i * 2).push_back(expanded_shape.at(_traversal_order.at(i)));
134 }
135 else
136 {
137 _dim_metadata.at(i * 2).push_back(0);
138 dst_sparse_dims.push_back(i);
139 }
140 }
141
142
143
144
145 int dst_dim_idx = num_expanded_dims;
146 std::vector<int> coordinate(num_expanded_dims, 0);
147 int dense_tensor_idx = 0;
148 while (dst_dim_idx >= 0)
149 {
150 if (dst_dim_idx == num_expanded_dims)
151 {
152
153
154 if (!IsZero(src_data[dense_tensor_idx]))
155 {
156 _data.push_back(src_data[dense_tensor_idx]);
157
158 for (auto dst_dim : dst_sparse_dims)
159 {
160 if (!dst_dim_has_nonzeroes.at(dst_dim))
161 {
162
163
164 _dim_metadata.at(2 * dst_dim + 1).push_back(coordinate.at(dst_dim));
165 dst_dim_has_nonzeroes.at(dst_dim) = true;
166 }
167 }
168 }
170 {
171 _data.push_back(src_data[dense_tensor_idx]);
172 }
173 --dst_dim_idx;
174 }
175 else
176 {
177 int original_dim_idx = _traversal_order.at(dst_dim_idx);
178 int dim_size = expanded_shape.at(original_dim_idx);
179 if (dst_dim_has_nonzeroes.at(dst_dim_idx))
180 {
181
182
183 dst_dim_has_nonzeroes.at(dst_dim_idx) = false;
184 }
186 {
187
188 int next_compressed_dim = inner_compressed_dim.at(dst_dim_idx);
189 int erase_offset = _dim_metadata.at(2 * dst_dim_idx + 1).size() *
190 num_segments_of_next_compressed_dim.at(dst_dim_idx);
191 if (next_compressed_dim >= 0)
192 {
193 auto &segments = _dim_metadata.at(2 * inner_compressed_dim.at(dst_dim_idx));
194 segments.erase(segments.begin() + 1 + erase_offset, segments.end());
195 }
196 else
197 {
198 _data.erase(_data.begin() + erase_offset, _data.end());
199 }
200 }
201 if (++coordinate.at(dst_dim_idx) < dim_size)
202 {
203
204 dense_tensor_idx += dst_ordered_offset.at(dst_dim_idx);
205 ++dst_dim_idx;
206 }
207 else
208 {
209
210
212 {
213 _dim_metadata.at(2 * dst_dim_idx).push_back(_dim_metadata.at(2 * dst_dim_idx + 1).size());
214 }
215 coordinate.at(dst_dim_idx) = -1;
216 dense_tensor_idx -= dst_ordered_offset.at(dst_dim_idx) * dim_size;
217 --dst_dim_idx;
218 }
219 }
220 }
221}