| 44 | explicit AddNOp(OpKernelConstruction* context) : OpKernel(context) {} |
| 45 | |
| 46 | void Compute(OpKernelContext* ctx) override { |
| 47 | if (!ctx->ValidateInputsAreSameShape(this)) return; |
| 48 | |
| 49 | const Tensor& input0 = ctx->input(0); |
| 50 | const int num = ctx->num_inputs(); |
| 51 | |
| 52 | if (num == 1) { |
| 53 | ctx->set_output(0, input0); |
| 54 | return; |
| 55 | } |
| 56 | |
| 57 | // Try to forward and accumulate the result in one of the input buffers. |
| 58 | int reused_input = -1; |
| 59 | gtl::InlinedVector<int, 8> input_indices(num); |
| 60 | std::iota(input_indices.begin(), input_indices.end(), 0); |
| 61 | Tensor* output = nullptr; |
| 62 | for (int input_idx = 0; input_idx < num; ++input_idx) { |
| 63 | if (ctx->forward_input_to_output_with_shape(input_idx, 0, input0.shape(), |
| 64 | &output)) { |
| 65 | reused_input = input_idx; |
| 66 | break; |
| 67 | } |
| 68 | } |
| 69 | if (reused_input == -1) { |
| 70 | OP_REQUIRES_OK(ctx, ctx->allocate_output(0, input0.shape(), &output)); |
| 71 | } else if (reused_input > 0) { |
| 72 | // Move the forwarded buffer to the front so we don't double count |
| 73 | // anything if there are more than 8 inputs. |
| 74 | input_indices[0] = reused_input; |
| 75 | input_indices[reused_input] = 0; |
| 76 | } |
| 77 | auto To = output->flat<T>(); |
| 78 | |
| 79 | #define I(IDX) ctx->input(input_indices[IDX]).flat<T>() |
| 80 | |
| 81 | #if defined(__ANDROID_TYPES_SLIM__) |
| 82 | // On Android by default,we only support additions of two arguments, so we |
| 83 | // can reduce the number of template instantiations. |
| 84 | OP_REQUIRES(ctx, num == 2, |
| 85 | errors::InvalidArgument("Only additions of two arguments " |
| 86 | "supported. Num inputs: ", |
| 87 | num)); |
| 88 | functor::Add2Functor<Device, T> functor2; |
| 89 | functor2(ctx->template eigen_device<Device>(), To, I(0), I(1)); |
| 90 | #else |
| 91 | static const int kWidth = 8; |
| 92 | int r = num % kWidth; |
| 93 | |
| 94 | switch (r) { |
| 95 | case 2: { |
| 96 | functor::Add2Functor<Device, T> functor2; |
| 97 | functor2(ctx->template eigen_device<Device>(), To, I(0), I(1)); |
| 98 | break; |
| 99 | } |
| 100 | case 3: { |
| 101 | functor::Add3Functor<Device, T> functor3; |
| 102 | functor3(ctx->template eigen_device<Device>(), To, I(0), I(1), I(2)); |
| 103 | break; |
nothing calls this directly
no test coverage detected