176 if (domain_size == 0) {
182 evaluator.
add(input_);
183 evaluator.
add(group_index_);
191 using T = decltype(dummy);
192 if constexpr (is_same_any_v<T, int, float, float3>) {
193 const VArraySpan<T> values = g_values.typed<T>();
195 if (operation_ == Operation::Mean) {
196 if (group_indices.is_single()) {
197 const T mean = std::reduce(values.begin(), values.end(), T()) / domain_size;
198 g_outputs = VArray<T>::from_single(mean, domain_size);
201 Map<int, std::pair<T, int>> sum_and_counts;
202 for (const int i : values.index_range()) {
203 auto &pair = sum_and_counts.lookup_or_add(group_indices[i], std::make_pair(T(), 0));
204 pair.first = pair.first + values[i];
205 pair.second = pair.second + 1;
208 Array<T> outputs(domain_size);
209 for (const int i : values.index_range()) {
210 const auto &pair = sum_and_counts.lookup(group_indices[i]);
211 outputs[i] = pair.first / pair.second;
213 g_outputs = VArray<T>::from_container(std::move(outputs));
217 if (group_indices.is_single()) {
218 Array<T> sorted_values(values);
219 T median = calculate_median<T>(sorted_values);
220 g_outputs = VArray<T>::from_single(median, domain_size);
223 Map<int, Vector<T>> groups;
224 for (const int i : values.index_range()) {
225 groups.lookup_or_add(group_indices[i], Vector<T>()).append(values[i]);
229 for (MutableMapItem<int, Vector<T>> group : groups.items()) {
230 medians.add(group.key, calculate_median<T>(group.value));
233 Array<T> outputs(domain_size);
234 for (const int i : values.index_range()) {
235 outputs[i] = medians.lookup(group_indices[i]);
237 g_outputs = VArray<T>::from_container(std::move(outputs));
243 return attributes.adapt_domain(std::move(g_outputs), source_domain_, context.domain());