| 95 | bool use_exclusive_lock_; |
| 96 | |
| 97 | void DoCompute(OpKernelContext* c) { |
| 98 | Tensor params = c->mutable_input(0, use_exclusive_lock_); |
| 99 | const Tensor& indices = c->input(1); |
| 100 | const Tensor& updates = c->input(2); |
| 101 | DoValidationChecking(c, params, indices, updates); |
| 102 | if (!c->status().ok()) return; |
| 103 | |
| 104 | // Check that we have enough index space |
| 105 | const int64 N_big = indices.NumElements(); |
| 106 | OP_REQUIRES( |
| 107 | c, N_big <= std::numeric_limits<Index>::max(), |
| 108 | errors::InvalidArgument("indices has too many elements for ", |
| 109 | DataTypeString(DataTypeToEnum<Index>::v()), |
| 110 | " indexing: ", N_big, " > ", |
| 111 | std::numeric_limits<Index>::max())); |
| 112 | const Index N = static_cast<Index>(indices.NumElements()); |
| 113 | OP_REQUIRES( |
| 114 | c, params.dim_size(0) <= std::numeric_limits<Index>::max(), |
| 115 | errors::InvalidArgument("params.shape[0] too large for ", |
| 116 | DataTypeString(DataTypeToEnum<Index>::v()), |
| 117 | " indexing: ", params.dim_size(0), " > ", |
| 118 | std::numeric_limits<Index>::max())); |
| 119 | |
| 120 | // We always return the input ref. |
| 121 | c->forward_ref_input_to_ref_output(0, 0); |
| 122 | |
| 123 | if (N > 0) { |
| 124 | auto indices_flat = indices.flat<Index>(); |
| 125 | auto params_flat = params.flat_outer_dims<T>(); |
| 126 | |
| 127 | if (TensorShapeUtils::IsScalar(updates.shape()) || |
| 128 | IsLegacyScalar(updates.shape())) { |
| 129 | const auto update = updates.scalar<T>(); |
| 130 | functor::ScatterScalarFunctor<Device, T, Index, op> functor; |
| 131 | const Index bad_i = functor(c, c->template eigen_device<Device>(), |
| 132 | params_flat, update, indices_flat); |
| 133 | OP_REQUIRES(c, bad_i < 0, |
| 134 | errors::InvalidArgument( |
| 135 | "indices", SliceDebugString(indices.shape(), bad_i), |
| 136 | " = ", indices_flat(bad_i), " is not in [0, ", |
| 137 | params.dim_size(0), ")")); |
| 138 | } else { |
| 139 | auto updates_flat = |
| 140 | updates.shaped<T, 2>({N, updates.NumElements() / N}); |
| 141 | |
| 142 | functor::ScatterFunctor<Device, T, Index, op> functor; |
| 143 | const Index bad_i = functor(c, c->template eigen_device<Device>(), |
| 144 | params_flat, updates_flat, indices_flat); |
| 145 | OP_REQUIRES(c, bad_i < 0, |
| 146 | errors::InvalidArgument( |
| 147 | "indices", SliceDebugString(indices.shape(), bad_i), |
| 148 | " = ", indices_flat(bad_i), " is not in [0, ", |
| 149 | params.dim_size(0), ")")); |
| 150 | } |
| 151 | } |
| 152 | } |
| 153 | }; |
| 154 |
nothing calls this directly
no test coverage detected