1 | /* Copyright 2022 The TensorFlow Authors. All Rights Reserved. |
2 | |
3 | Licensed under the Apache License, Version 2.0 (the "License"); |
4 | you may not use this file except in compliance with the License. |
5 | You may obtain a copy of the License at |
6 | |
7 | http://www.apache.org/licenses/LICENSE-2.0 |
8 | |
9 | Unless required by applicable law or agreed to in writing, software |
10 | distributed under the License is distributed on an "AS IS" BASIS, |
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 | See the License for the specific language governing permissions and |
13 | limitations under the License. |
14 | ==============================================================================*/ |
15 | |
16 | #include "tensorflow/core/kernels/tensor_list_util.h" |
17 | |
18 | #include <functional> |
19 | |
20 | #include "tensorflow/core/framework/op_kernel.h" |
21 | #include "tensorflow/core/framework/tensor.h" |
22 | #include "tensorflow/core/framework/variant.h" |
23 | #include "tensorflow/core/kernels/tensor_list.h" |
24 | #include "tensorflow/core/lib/core/errors.h" |
25 | |
26 | namespace tensorflow { |
27 | |
28 | Status TensorListBinaryAdd( |
29 | OpKernelContext* c, const TensorList& a, const TensorList& b, |
30 | TensorList* out, |
31 | std::function<Status(OpKernelContext* ctx, const Tensor& a, const Tensor& b, |
32 | Tensor* out)> |
33 | binary_add_func) { |
34 | if (a.element_dtype != b.element_dtype) { |
35 | return errors::InvalidArgument( |
36 | "Trying to add two lists of tensors of different dtypes. One is " , |
37 | DataTypeString(a.element_dtype), " and the other is " , |
38 | DataTypeString(b.element_dtype)); |
39 | } |
40 | out->element_dtype = a.element_dtype; |
41 | if (!a.element_shape.IsCompatibleWith(b.element_shape)) { |
42 | return errors::InvalidArgument( |
43 | "Trying to add two lists of tensors with incompatible element shapes. " |
44 | "One is " , |
45 | a.element_shape.DebugString(), " and the other is " , |
46 | b.element_shape.DebugString()); |
47 | } |
48 | |
49 | TF_RETURN_IF_ERROR( |
50 | a.element_shape.MergeWith(b.element_shape, &out->element_shape)); |
51 | if (a.tensors().size() != b.tensors().size()) { |
52 | return errors::InvalidArgument( |
53 | "Trying to add two lists of tensors with different lengths. One is " , |
54 | a.tensors().size(), " and the other is " , b.tensors().size()); |
55 | } |
56 | out->tensors().reserve(a.tensors().size()); |
57 | for (int i = 0; i < a.tensors().size(); ++i) { |
58 | const Tensor& a_tensor = a.tensors()[i]; |
59 | const Tensor& b_tensor = b.tensors()[i]; |
60 | Tensor out_tensor; |
61 | TF_RETURN_IF_ERROR(binary_add_func(c, a_tensor, b_tensor, &out_tensor)); |
62 | out->tensors().push_back(out_tensor); |
63 | } |
64 | return OkStatus(); |
65 | } |
66 | |
67 | Status TensorListZerosLike( |
68 | OpKernelContext* c, const TensorList& x, TensorList* y, |
69 | std::function<Status(OpKernelContext* ctx, const Tensor& input, |
70 | Tensor* out)> |
71 | zeros_like_func) { |
72 | y->element_dtype = x.element_dtype; |
73 | y->element_shape = x.element_shape; |
74 | y->tensors().reserve(x.tensors().size()); |
75 | for (const Tensor& t : x.tensors()) { |
76 | Tensor out_tensor; |
77 | TF_RETURN_IF_ERROR(zeros_like_func(c, t, &out_tensor)); |
78 | y->tensors().emplace_back(out_tensor); |
79 | } |
80 | return OkStatus(); |
81 | } |
82 | |
83 | } // namespace tensorflow |
84 | |