| 725 | } |
| 726 | |
| 727 | core::TensorValue graph_downsample( |
| 728 | core::ModuleBuildContext & ctx, |
| 729 | const core::TensorValue & input, |
| 730 | const Param & bias) { |
| 731 | const int64_t ds = static_cast<int64_t>(bias.values.size()); |
| 732 | if (ds <= 0) { |
| 733 | throw std::runtime_error("ZipEnhancer downsample bias is empty"); |
| 734 | } |
| 735 | const auto weights = softmax_values(bias); |
| 736 | const int64_t out_s = (input.shape.dims[0] + ds - 1) / ds; |
| 737 | std::vector<core::TensorValue> pieces; |
| 738 | pieces.reserve(static_cast<size_t>(out_s)); |
| 739 | for (int64_t s = 0; s < out_s; ++s) { |
| 740 | core::TensorValue acc; |
| 741 | for (int64_t k = 0; k < ds; ++k) { |
| 742 | const int64_t src_s = std::min(input.shape.dims[0] - 1, s * ds + k); |
| 743 | auto slice = modules::SliceModule({0, src_s, 1}).build(ctx, input); |
| 744 | slice = graph_scale(ctx, slice, weights[static_cast<size_t>(k)]); |
| 745 | acc = acc.valid() ? graph_add(ctx, acc, slice) : slice; |
| 746 | } |
| 747 | pieces.push_back(acc); |
| 748 | } |
| 749 | return graph_concat_all(ctx, pieces, 0); |
| 750 | } |
| 751 | |
| 752 | core::TensorValue graph_upsample_slice( |
| 753 | core::ModuleBuildContext & ctx, |
no test coverage detected