## Coverage Report

#### Created: 2026-05-04 15:30

next uncovered line (L), next uncovered region (R), next uncovered branch (B)

    /home/liu/actions-runner/_work/ccv/ccv/test/unit/nnc/custom.tests.c

    Line
    Count
    Source
    1
    #include "case.h"
    2
    #include "ccv_case.h"
    3
    #include "ccv_nnc_case.h"
    4
    #include <ccv.h>
    5
    #include <nnc/ccv_nnc.h>
    6
    #include <nnc/ccv_nnc_easy.h>
    7
    #include "3rdparty/dsfmt/dSFMT.h"
    8
    9
    TEST_SETUP()
    10
    {
    11
      ccv_nnc_init();
    12
    }
    13
    14
    static int _ccv_nnc_cmd_custom_exec(const ccv_nnc_cmd_t cmd, const ccv_nnc_hint_t hint, const int flags, ccv_nnc_tensor_t* const* const inputs, const int input_size, ccv_nnc_tensor_t* const* const outputs, const int output_size, ccv_nnc_stream_context_t* const stream_context)
    15
    3
    {
    16
    3
      if (cmd.cmd == CCV_NNC_CUSTOM_FORWARD)
    17
    2
      {
    18
    2
        ccv_nnc_dynamic_graph_t* const graph = ccv_nnc_dynamic_graph_new();
    19
    2
        const ccv_nnc_tensor_variable_t x = ccv_nnc_tensor_variable_new(graph);
    20
    2
        ccv_nnc_tensor_variable_set(graph, x, inputs[0]);
    21
    2
        const ccv_nnc_tensor_variable_t z = ccv_nnc_tensor_variable_new(graph);
    22
    2
        ccv_nnc_dynamic_graph_exec(graph, CMD_EWLOG_FORWARD(), ccv_nnc_no_hint, 0, TENSOR_VARIABLE_LIST(x), TENSOR_VARIABLE_LIST(z), 0, 0);
    23
    2
        const ccv_nnc_tensor_variable_t y = ccv_nnc_tensor_variable_new(graph);
    24
    2
        ccv_nnc_tensor_variable_set(graph, y, outputs[0]);
    25
    2
        ccv_nnc_dynamic_graph_exec(graph, CMD_EWLOG_FORWARD(), ccv_nnc_no_hint, 0, TENSOR_VARIABLE_LIST(z), TENSOR_VARIABLE_LIST(y), 0, 0);
    26
    2
        ccv_nnc_dynamic_graph_free(graph);
    27
    2
      } else {
    28
    1
        ccv_nnc_dynamic_graph_t* const graph = ccv_nnc_dynamic_graph_new();
    29
    1
        const ccv_nnc_tensor_variable_t x = ccv_nnc_tensor_variable_new(graph);
    30
    1
        ccv_nnc_tensor_variable_set(graph, x, inputs[1]);
    31
    1
        const ccv_nnc_tensor_variable_t z = ccv_nnc_tensor_variable_new(graph);
    32
    1
        ccv_nnc_dynamic_graph_exec(graph, CMD_EWLOG_FORWARD(), ccv_nnc_no_hint, 0, TENSOR_VARIABLE_LIST(x), TENSOR_VARIABLE_LIST(z), 0, 0);
    33
    1
        const ccv_nnc_tensor_variable_t y = ccv_nnc_tensor_variable_new(graph);
    34
    1
        ccv_nnc_tensor_variable_set(graph, y, inputs[2]);
    35
    1
        ccv_nnc_dynamic_graph_exec(graph, CMD_EWLOG_FORWARD(), ccv_nnc_no_hint, 0, TENSOR_VARIABLE_LIST(z), TENSOR_VARIABLE_LIST(y), 0, 0);
    36
    1
        const ccv_nnc_tensor_variable_t dy = ccv_nnc_tensor_variable_new(graph);
    37
    1
        ccv_nnc_tensor_variable_set(graph, dy, inputs[0]);
    38
    1
        const ccv_nnc_tensor_variable_t dx = ccv_nnc_tensor_variable_new(graph);
    39
    1
        ccv_nnc_tensor_variable_set(graph, dx, outputs[0]);
    40
    1
        ccv_nnc_dynamic_graph_backward(graph, TENSOR_VARIABLE_LIST(y), &dy, TENSOR_VARIABLE_LIST(x), TENSOR_VARIABLE_LIST(dx), 0);
    41
    1
        ccv_nnc_dynamic_graph_free(graph);
    42
    1
      }
    43
    3
      return CCV_NNC_EXEC_SUCCESS;
    44
    3
    }
    45
    46
    static ccv_nnc_cmd_vtab_t _custom_isa = {
    47
      .exec = _ccv_nnc_cmd_custom_exec,
    48
    };
    49
    50
    TEST_CASE("custom forward operation with dynamic graph")
    51
    1
    {
    52
    1
      const ccv_nnc_cmd_t cmd = ccv_nnc_cmd(CCV_NNC_CUSTOM_FORWARD, &_custom_isa, (ccv_nnc_cmd_param_t){}, 0);
    53
    1
      ccv_nnc_symbolic_graph_t* const symbolic_graph = ccv_nnc_symbolic_graph_new();
    54
    1
      const ccv_nnc_tensor_symbol_t x = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 1), "x");
    55
    1
      const ccv_nnc_tensor_symbol_t y = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 1), "y");
    56
    1
      ccv_nnc_graph_exec_symbol_new(symbolic_graph, cmd, TENSOR_SYMBOL_LIST(x), TENSOR_SYMBOL_LIST(y), "custom");
    57
    1
      ccv_nnc_graph_exec_symbol_autogen(symbolic_graph, 0, 0, CCV_NNC_AUTOGEN_SOURCES_AND_DESTINATIONS | CCV_NNC_AUTOGEN_ALL_EXECS);
    58
    1
      ccv_nnc_graph_t* graph;
    59
    1
      ccv_nnc_tensor_arena_t* tensor_arena;
    60
    1
      ccv_nnc_graph_exec_arena_t* graph_exec_arena;
    61
    1
      ccv_nnc_symbolic_graph_compile(symbolic_graph, ccv_nnc_default_compile_params, 0, 0,
    62
    1
        TENSOR_SYMBOL_LIST(y),
    63
    1
        SYMBOLIC_GRAPH_SOURCES(symbolic_graph), SYMBOLIC_GRAPH_DESTINATIONS(symbolic_graph),
    64
    1
        &graph, &tensor_arena, &graph_exec_arena);
    65
    1
      ccv_nnc_symbolic_graph_free(symbolic_graph);
    66
    1
      ccv_nnc_tensor_t* const x_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, x);
    67
    1
      x_tensor->data.f32[0] = 10;
    68
    1
      ccv_nnc_graph_run(graph, 0, TRAVERSE_FULL, 0, 0);
    69
    1
      ccv_nnc_tensor_t* const y_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, y);
    70
    1
      REQUIRE_EQ_WITH_TOLERANCE(y_tensor->data.f32[0], log(log(10)), 1e-5, "computed result should be identical");
    71
    1
      ccv_nnc_graph_free(graph);
    72
    1
      ccv_nnc_tensor_arena_free(tensor_arena);
    73
    1
      ccv_nnc_graph_exec_arena_free(graph_exec_arena);
    74
    1
    }
    75
    76
    TEST_CASE("custom backward operation with dynamic graph")
    77
    1
    {
    78
    1
      const ccv_nnc_cmd_t cmd = ccv_nnc_cmd(CCV_NNC_CUSTOM_FORWARD, &_custom_isa, (ccv_nnc_cmd_param_t){}, 0);
    79
    1
      ccv_nnc_symbolic_graph_t* const symbolic_graph = ccv_nnc_symbolic_graph_new();
    80
    1
      const ccv_nnc_tensor_symbol_t x = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 1), "x");
    81
    1
      const ccv_nnc_tensor_symbol_t y = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 1), "y");
    82
    1
      ccv_nnc_graph_exec_symbol_new(symbolic_graph, cmd, TENSOR_SYMBOL_LIST(x), TENSOR_SYMBOL_LIST(y), "custom");
    83
    1
      ccv_nnc_graph_exec_symbol_autogen(symbolic_graph, 0, 0, CCV_NNC_AUTOGEN_SOURCES_AND_DESTINATIONS | CCV_NNC_AUTOGEN_ALL_EXECS);
    84
    1
      ccv_nnc_symbolic_graph_backward(symbolic_graph, TENSOR_SYMBOL_LIST(y), TENSOR_SYMBOL_LIST(x), SYMBOLIC_GRAPH_SOURCES(symbolic_graph), SYMBOLIC_GRAPH_DESTINATIONS(symbolic_graph));
    85
    1
      const ccv_nnc_tensor_symbol_t dy = ccv_nnc_tensor_symbol_for_backward(symbolic_graph, y);
    86
    1
      ccv_nnc_graph_exec_symbol_new(symbolic_graph, CMD_SET_FORWARD(1), TENSOR_SYMBOL_LIST(), TENSOR_SYMBOL_LIST(dy), "set");
    87
    1
      ccv_nnc_graph_exec_symbol_autogen(symbolic_graph, 0, 0, CCV_NNC_AUTOGEN_SOURCES_AND_DESTINATIONS | CCV_NNC_AUTOGEN_ALL_EXECS);
    88
    1
      const ccv_nnc_tensor_symbol_t dx = ccv_nnc_tensor_symbol_for_backward(symbolic_graph, x);
    89
    1
      ccv_nnc_graph_t* graph;
    90
    1
      ccv_nnc_tensor_arena_t* tensor_arena;
    91
    1
      ccv_nnc_graph_exec_arena_t* graph_exec_arena;
    92
    1
      ccv_nnc_symbolic_graph_compile(symbolic_graph, ccv_nnc_default_compile_params, 0, 0,
    93
    1
        TENSOR_SYMBOL_LIST(dx),
    94
    1
        SYMBOLIC_GRAPH_SOURCES(symbolic_graph), SYMBOLIC_GRAPH_DESTINATIONS(symbolic_graph),
    95
    1
        &graph, &tensor_arena, &graph_exec_arena);
    96
    1
      ccv_nnc_symbolic_graph_free(symbolic_graph);
    97
    1
      ccv_nnc_tensor_t* const x_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, x);
    98
    1
      x_tensor->data.f32[0] = 10;
    99
    1
      ccv_nnc_graph_run(graph, 0, TRAVERSE_FULL, 0, 0);
    100
    1
      ccv_nnc_tensor_t* const dx_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, dx);
    101
    1
      REQUIRE_EQ_WITH_TOLERANCE(dx_tensor->data.f32[0], 1. / (log(10) * 10), 1e-5, "computed result should be identical");
    102
    1
      ccv_nnc_graph_free(graph);
    103
    1
      ccv_nnc_tensor_arena_free(tensor_arena);
    104
    1
      ccv_nnc_graph_exec_arena_free(graph_exec_arena);
    105
    1
    }
    106
    107
    #include "case_main.h"