113 lines
3.5 KiB
C++
113 lines
3.5 KiB
C++
/* Copyright 2016 The TensorFlow Authors. All Rights Reserved.
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
==============================================================================*/
|
|
|
|
#include "tensorflow/cc/framework/ops.h"
|
|
#include "tensorflow/core/lib/hash/hash.h"
|
|
|
|
namespace tensorflow {
|
|
|
|
Operation::Operation(Node* n) : inputs_(GetInputs(n)), node_(n) {}
|
|
|
|
Output Operation::input(int32 i) const {
|
|
CHECK_NOTNULL(node_);
|
|
CHECK_GE(i, 0);
|
|
CHECK_LT(i, node_->num_inputs());
|
|
// Handle the case where the input was unknown at the time this
|
|
// Operation was constructed.
|
|
if (inputs_[i].first == nullptr && inputs_[i].second == -1) {
|
|
for (const Edge* e : node_->in_edges()) {
|
|
if (e->IsControlEdge()) continue;
|
|
if (e->dst_input() == i) {
|
|
return Output(e->src(), e->src_output());
|
|
}
|
|
}
|
|
}
|
|
return Output(inputs_[i].first, inputs_[i].second);
|
|
}
|
|
|
|
Output Operation::output(int32 i) const {
|
|
CHECK_NOTNULL(node_);
|
|
CHECK_GE(i, 0);
|
|
CHECK_LT(i, node_->num_outputs());
|
|
return Output(node_, i);
|
|
}
|
|
|
|
uint64 Operation::hash(int32 index) const {
|
|
return ::tensorflow::Hash64(reinterpret_cast<const char*>(&node_),
|
|
sizeof(Node*), index);
|
|
}
|
|
|
|
Operation::Inputs Operation::GetInputs(Node* node) {
|
|
Operation::Inputs inputs;
|
|
if (node != nullptr) {
|
|
inputs.resize(node->num_inputs(), {nullptr, -1});
|
|
for (const Edge* e : node->in_edges()) {
|
|
if (e->IsControlEdge()) continue;
|
|
inputs[e->dst_input()] = std::make_pair(e->src(), e->src_output());
|
|
}
|
|
}
|
|
return inputs;
|
|
}
|
|
|
|
Input::Initializer::Initializer(
|
|
const std::initializer_list<Input::Initializer>& v) {
|
|
if (v.size() < 1) {
|
|
// Empty initializer list defaults to float tensor with shape (0,)
|
|
tensor = Tensor(DT_FLOAT, TensorShape{0});
|
|
return;
|
|
}
|
|
auto const& first = *v.begin();
|
|
// Check to make sure that the constituent Initializers are all the same
|
|
// type and same shape.
|
|
for (auto const& e : v) {
|
|
if (e.tensor.dtype() != first.tensor.dtype()) {
|
|
status = errors::InvalidArgument(
|
|
"Initializer list components should all have the same type");
|
|
return;
|
|
}
|
|
if (!TensorShape{e.tensor.shape()}.IsSameSize(
|
|
TensorShape{first.tensor.shape()})) {
|
|
status = errors::InvalidArgument(
|
|
"Initializer list components should all have the same shape");
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Form the new shape.
|
|
TensorShape shape{static_cast<int64>(v.size())};
|
|
shape.AppendShape(TensorShape{first.tensor.shape()});
|
|
|
|
Tensor t(first.tensor.dtype(), shape);
|
|
|
|
// Collate the constituent Tensors.
|
|
size_t offset = 0;
|
|
for (auto const& e : v) {
|
|
Tensor elem = e.tensor;
|
|
if (first.tensor.dtype() == DT_STRING) {
|
|
for (int i = 0; i < elem.NumElements(); ++i) {
|
|
t.flat<tstring>()(offset + i) = elem.flat<tstring>()(i);
|
|
}
|
|
offset += elem.NumElements();
|
|
} else {
|
|
std::copy_n(elem.tensor_data().data(), elem.TotalBytes(),
|
|
const_cast<char*>(t.tensor_data().data()) + offset);
|
|
offset += elem.TotalBytes();
|
|
}
|
|
}
|
|
tensor = t;
|
|
}
|
|
|
|
} // namespace tensorflow
|