| 169 | |
| 170 | template <typename DType> |
| 171 | void traverse_binary(const Tensor &in1, const Tensor &in2, Tensor *out, |
| 172 | std::function<DType(DType, DType)> func) { |
| 173 | DType *outPtr = static_cast<DType *>(out->block()->mutable_data()); |
| 174 | const DType *in1Ptr = static_cast<const DType *>(in1.block()->data()); |
| 175 | const DType *in2Ptr = static_cast<const DType *>(in2.block()->data()); |
| 176 | /* |
| 177 | vector<int> traversal_info_in1 = generate_traversal_info(in1); |
| 178 | vector<int> traversal_info_in2 = generate_traversal_info(in2); |
| 179 | vector<int> shape_multipliers_in1 = generate_shape_multipliers(in1); |
| 180 | vector<int> shape_multipliers_in2 = generate_shape_multipliers(in2); |
| 181 | |
| 182 | for (size_t i = 0; i < in1.Size(); i++) { |
| 183 | outPtr[i] = func(in1Ptr[traversal_info_in1[in1.shape().size()]], |
| 184 | in2Ptr[traversal_info_in2[in2.shape().size()]]); |
| 185 | traverse_next(in1, shape_multipliers_in1, traversal_info_in1, i + 1); |
| 186 | traverse_next(in2, shape_multipliers_in2, traversal_info_in2, i + 1); |
| 187 | } |
| 188 | */ |
| 189 | auto prod = Product(in1.shape()); |
| 190 | CHECK(in1.shape() == out->shape()); |
| 191 | CHECK(in2.shape() == out->shape()); |
| 192 | if ((in1.stride() == out->stride()) && (in2.stride() == in1.stride())) { |
| 193 | for (size_t i = 0; i < prod; i++) outPtr[i] = func(in1Ptr[i], in2Ptr[i]); |
| 194 | } else { |
| 195 | /* |
| 196 | LOG(INFO) << "not equal stride"; |
| 197 | std::ostringstream s1, s2, s3, s4, s5, s6; |
| 198 | std::copy(in1.stride().begin(), in1.stride().end(), |
| 199 | std::ostream_iterator<int>(s1, ", ")); |
| 200 | std::copy(in2.stride().begin(), in2.stride().end(), |
| 201 | std::ostream_iterator<int>(s2, ", ")); |
| 202 | std::copy(out->stride().begin(), out->stride().end(), |
| 203 | std::ostream_iterator<int>(s3, ", ")); |
| 204 | |
| 205 | std::copy(in1.shape().begin(), in1.shape().end(), |
| 206 | std::ostream_iterator<int>(s4, ", ")); |
| 207 | std::copy(in2.shape().begin(), in2.shape().end(), |
| 208 | std::ostream_iterator<int>(s5, ", ")); |
| 209 | std::copy(out->shape().begin(), out->shape().end(), |
| 210 | std::ostream_iterator<int>(s6, ", ")); |
| 211 | |
| 212 | LOG(INFO) << s1.str() << ": " << s4.str(); |
| 213 | LOG(INFO) << s2.str() << ": " << s5.str(); |
| 214 | LOG(INFO) << s3.str() << ": " << s6.str(); |
| 215 | LOG(INFO) << Backtrace(); |
| 216 | */ |
| 217 | |
| 218 | size_t in1_offset = 0, in2_offset = 0, out_offset = 0; |
| 219 | vector<int> in1_idx(in1.nDim(), 0), in2_idx(in2.nDim(), 0), |
| 220 | out_idx(out->nDim(), 0); |
| 221 | for (size_t i = 0; i < prod; i++) { |
| 222 | outPtr[out_offset] = func(in1Ptr[in1_offset], in2Ptr[in2_offset]); |
| 223 | out_offset = |
| 224 | next_offset(out_offset, out->shape(), out->stride(), &out_idx); |
| 225 | in1_offset = next_offset(in1_offset, in1.shape(), in1.stride(), &in1_idx); |
| 226 | in2_offset = next_offset(in2_offset, in2.shape(), in2.stride(), &in2_idx); |
| 227 | // LOG(INFO) << in1_offset << ", " << in2_offset << ", " << out_offset; |
| 228 | } |
nothing calls this directly
no test coverage detected