static*/
| 536 | } |
| 537 | |
| 538 | /*static*/ std::vector<float> ReferenceUtil::Reduce4DTo1D( |
| 539 | const Array4D<float>& array, float init, absl::Span<const int64> dims, |
| 540 | const std::function<float(float, float)>& reduce_function) { |
| 541 | std::vector<float> result; |
| 542 | CHECK_EQ(dims.size(), 3); |
| 543 | const absl::flat_hash_set<int64> dim_set(dims.begin(), dims.end()); |
| 544 | CHECK_EQ(dim_set.size(), 3); |
| 545 | for (int64 a0 = 0; a0 == 0 || (!dim_set.contains(0) && a0 < array.n1()); |
| 546 | ++a0) { |
| 547 | for (int64 a1 = 0; a1 == 0 || (!dim_set.contains(1) && a1 < array.n2()); |
| 548 | ++a1) { |
| 549 | for (int64 a2 = 0; a2 == 0 || (!dim_set.contains(2) && a2 < array.n3()); |
| 550 | ++a2) { |
| 551 | for (int64 a3 = 0; a3 == 0 || (!dim_set.contains(3) && a3 < array.n4()); |
| 552 | ++a3) { |
| 553 | float accumulator = init; |
| 554 | for (int64 i0 = 0; |
| 555 | i0 == 0 || (dim_set.contains(0) && i0 < array.n1()); ++i0) { |
| 556 | for (int64 i1 = 0; |
| 557 | i1 == 0 || (dim_set.contains(1) && i1 < array.n2()); ++i1) { |
| 558 | for (int64 i2 = 0; |
| 559 | i2 == 0 || (dim_set.contains(2) && i2 < array.n3()); ++i2) { |
| 560 | for (int64 i3 = 0; |
| 561 | i3 == 0 || (dim_set.contains(3) && i3 < array.n4()); |
| 562 | ++i3) { |
| 563 | // Handle zero-sized arrays. |
| 564 | if (array.n1() > 0 && array.n2() > 0 && array.n3() > 0 && |
| 565 | array.n4() > 0) { |
| 566 | accumulator = reduce_function( |
| 567 | accumulator, array(a0 + i0, a1 + i1, a2 + i2, a3 + i3)); |
| 568 | } |
| 569 | } |
| 570 | } |
| 571 | } |
| 572 | } |
| 573 | result.push_back(accumulator); |
| 574 | } |
| 575 | } |
| 576 | } |
| 577 | } |
| 578 | return result; |
| 579 | } |
| 580 | |
| 581 | /* static */ std::unique_ptr<Array4D<float>> ReferenceUtil::Broadcast1DTo4D( |
| 582 | const std::vector<float>& array, const std::vector<int64>& bounds, |