<commit_before>#include "xchainer/op_node.h"

#include <algorithm>
#include <cassert>
#include <functional>
#include <memory>
#include <tuple>
#include <utility>
#include <vector>

#include "xchainer/array.h"
#include "xchainer/array_node.h"
#include "xchainer/graph.h"

namespace xchainer {
namespace internal {

ArrayProps::ArrayProps(const Array& array) : shape{array.shape()}, dtype{array.dtype()}, device{array.device()} {}
ArrayProps::ArrayProps(const ArrayNode& array_node) : shape{array_node.shape()}, dtype{array_node.dtype()}, device{array_node.device()} {}

OpNodeBackwardEntry::OpNodeBackwardEntry(OpNode& op_node, std::vector<size_t> input_array_node_indices, BackwardFunction backward_func)
    : op_node_{op_node}, input_array_node_indices_{std::move(input_array_node_indices)}, backward_func_{std::move(backward_func)} {}

void OpNodeBackwardEntry::AddExoticInputArrayNode(std::tuple<BackpropId, std::vector<std::shared_ptr<ArrayNode>>> input_array_nodes) {
    assert(std::get<0>(input_array_nodes) != op_node_.backprop_id());
    exotic_input_array_nodes_.emplace_back(std::move(input_array_nodes));
}

std::shared_ptr<ArrayNode> FabricateOutputArrayNode(std::shared_ptr<OpNode> op_node, size_t output_array_node_index) {
    assert(output_array_node_index < op_node->output_array_node_count());
    assert(op_node->output_array_nodes()[output_array_node_index].expired());

    const ArrayProps& props = op_node->GetOutputArrayProps(output_array_node_index);
    auto output_array_node = std::make_shared<ArrayNode>(props.shape, props.dtype, props.device, op_node->backprop_id());

    op_node->output_array_nodes()[output_array_node_index] = output_array_node;
    output_array_node->set_creator_op_node(std::move(op_node));

    return output_array_node;
}

// static
std::shared_ptr<OpNode> OpNode::CreateWithOutputArrayNodes(
        std::string name, BackpropId backprop_id, size_t input_count, const std::vector<ConstArrayRef>& outputs) {
    // Trick to use make_shared with private ctor
    struct OpNodeWithPublicCtor : OpNode {
        OpNodeWithPublicCtor(std::string name, BackpropId backprop_id, size_t input_count)
            : OpNode{std::move(name), backprop_id, input_count} {}
    };
    std::shared_ptr<OpNode> op_node = std::make_shared<OpNodeWithPublicCtor>(std::move(name), backprop_id, input_count);

    for (const Array& out : outputs) {
        const std::shared_ptr<ArrayBody>& out_body = GetArrayBody(out);
        assert(!out_body->HasArrayNode(backprop_id));
        const std::shared_ptr<ArrayNode>& output_array_node = ArrayBody::CreateArrayNode(out_body, backprop_id);
        op_node->output_array_props_.emplace_back(*output_array_node);
        op_node->output_array_nodes_.emplace_back(output_array_node);
        output_array_node->set_creator_op_node(op_node);
    }
    op_node->AssertConsistency();
    return op_node;
}

OpNode::OpNode(std::string name, BackpropId backprop_id, size_t input_array_node_count)
    : name_{std::move(name)},
      backprop_id_{backprop_id},
      input_array_nodes_{input_array_node_count}  // Initialize with nullptrs
{}

#ifndef NDEBUG

namespace {

bool IsAllArrayNodesMatchBackpropId(
        const BackpropId& outer_backprop_id, const std::vector<std::shared_ptr<ArrayNode>>& outer_graphs_array_nodes) {
    return std::all_of(
            outer_graphs_array_nodes.begin(),
            outer_graphs_array_nodes.end(),
            [&outer_backprop_id](const std::shared_ptr<ArrayNode>& array_node) {
                return array_node == nullptr || array_node->backprop_id() == outer_backprop_id;
            });
}

bool AssertOuterGraphsArrayNodesConsistency(
        const BackpropId& backprop_id,
        size_t array_node_count,
        const std::vector<std::tuple<BackpropId, std::vector<std::shared_ptr<ArrayNode>>>>& outer_graphs_array_nodes,
        bool is_output) {
    assert(array_node_count > 0);
<commit_msg>Fix wrong return type<commit_after>#include "xchainer/op_node.h"

#include <algorithm>
#include <cassert>
#include <functional>
#include <memory>
#include <tuple>
#include <utility>
#include <vector>

#include "xchainer/array.h"
#include "xchainer/array_node.h"
#include "xchainer/graph.h"

namespace xchainer {
namespace internal {

ArrayProps::ArrayProps(const Array& array) : shape{array.shape()}, dtype{array.dtype()}, device{array.device()} {}
ArrayProps::ArrayProps(const ArrayNode& array_node) : shape{array_node.shape()}, dtype{array_node.dtype()}, device{array_node.device()} {}

OpNodeBackwardEntry::OpNodeBackwardEntry(OpNode& op_node, std::vector<size_t> input_array_node_indices, BackwardFunction backward_func)
    : op_node_{op_node}, input_array_node_indices_{std::move(input_array_node_indices)}, backward_func_{std::move(backward_func)} {}

void OpNodeBackwardEntry::AddExoticInputArrayNode(std::tuple<BackpropId, std::vector<std::shared_ptr<ArrayNode>>> input_array_nodes) {
    assert(std::get<0>(input_array_nodes) != op_node_.backprop_id());
    exotic_input_array_nodes_.emplace_back(std::move(input_array_nodes));
}

std::shared_ptr<ArrayNode> FabricateOutputArrayNode(std::shared_ptr<OpNode> op_node, size_t output_array_node_index) {
    assert(output_array_node_index < op_node->output_array_node_count());
    assert(op_node->output_array_nodes()[output_array_node_index].expired());

    const ArrayProps& props = op_node->GetOutputArrayProps(output_array_node_index);
    auto output_array_node = std::make_shared<ArrayNode>(props.shape, props.dtype, props.device, op_node->backprop_id());

    op_node->output_array_nodes()[output_array_node_index] = output_array_node;
    output_array_node->set_creator_op_node(std::move(op_node));

    return output_array_node;
}

// static
std::shared_ptr<OpNode> OpNode::CreateWithOutputArrayNodes(
        std::string name, BackpropId backprop_id, size_t input_count, const std::vector<ConstArrayRef>& outputs) {
    // Trick to use make_shared with private ctor
    struct OpNodeWithPublicCtor : OpNode {
        OpNodeWithPublicCtor(std::string name, BackpropId backprop_id, size_t input_count)
            : OpNode{std::move(name), backprop_id, input_count} {}
    };
    std::shared_ptr<OpNode> op_node = std::make_shared<OpNodeWithPublicCtor>(std::move(name), backprop_id, input_count);

    for (const Array& out : outputs) {
        const std::shared_ptr<ArrayBody>& out_body = GetArrayBody(out);
        assert(!out_body->HasArrayNode(backprop_id));
        const std::shared_ptr<ArrayNode>& output_array_node = ArrayBody::CreateArrayNode(out_body, backprop_id);
        op_node->output_array_props_.emplace_back(*output_array_node);
        op_node->output_array_nodes_.emplace_back(output_array_node);
        output_array_node->set_creator_op_node(op_node);
    }
    op_node->AssertConsistency();
    return op_node;
}

OpNode::OpNode(std::string name, BackpropId backprop_id, size_t input_array_node_count)
    : name_{std::move(name)},
      backprop_id_{backprop_id},
      input_array_nodes_{input_array_node_count}  // Initialize with nullptrs
{}

#ifndef NDEBUG

namespace {

bool IsAllArrayNodesMatchBackpropId(
        const BackpropId& outer_backprop_id, const std::vector<std::shared_ptr<ArrayNode>>& outer_graphs_array_nodes) {
    return std::all_of(
            outer_graphs_array_nodes.begin(),
            outer_graphs_array_nodes.end(),
            [&outer_backprop_id](const std::shared_ptr<ArrayNode>& array_node) {
                return array_node == nullptr || array_node->backprop_id() == outer_backprop_id;
            });
}

void AssertOuterGraphsArrayNodesConsistency(
        const BackpropId& backprop_id,
        size_t array_node_count,
        const std::vector<std::tuple<BackpropId, std::vector<std::shared_ptr<ArrayNode>>>>& outer_graphs_array_nodes,
        bool is_output) {
    assert(array_node_count > 0);

{'fraction_non_alphanumeric': 0.12031608462911038, 'fraction_numerical': 0.0005098139179199592, 'mean_word_length': 5.919753086419753, 'pattern_counts': {'":': 0, '<': 61, '<?xml version=': 0, '>': 85, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3057036', 'n_tokens_mistral': 2586, 'n_tokens_neox': 2575, 'n_words': 371}