## 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/symbolic.graph.compile.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 _case_of(ccv_nnc_tensor_t* const *const inputs, const int input_size, const void *const case_of_data)
    15
    4
    {
    16
    4
      if (inputs[0]->data.f32[0] < 0)
    17
    1
        return -1;
    18
    3
      else if (inputs[0]->data.f32[0] < 1)
    19
    1
        return 0;
    20
    2
      else if (inputs[0]->data.f32[0] < 2)
    21
    1
        return 2;
    22
    1
      else
    23
    1
        return 1;
    24
    4
    }
    25
    26
    TEST_CASE("compile symbolic graph with case..of")
    27
    1
    {
    28
    1
      ccv_nnc_symbolic_graph_t* const symbolic_graph = ccv_nnc_symbolic_graph_new();
    29
    1
      ccv_nnc_tensor_symbol_t x = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 2), "x");
    30
    1
      ccv_nnc_tensor_symbol_t y = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 2), "y");
    31
    1
      ccv_nnc_graph_exec_symbol_t case_of = ccv_nnc_symbolic_graph_case_of_new(symbolic_graph, CCV_NNC_GRAPH_FORWARD, TENSOR_SYMBOL_LIST(x), TENSOR_SYMBOL_MAP(KV(x, y)), "case of");
    32
    1
      ccv_nnc_symbolic_graph_t* const case_0 = ccv_nnc_symbolic_graph_new();
    33
    1
      ccv_nnc_tensor_symbol_t y0 = ccv_nnc_tensor_symbol_new(case_0, CPU_TENSOR_NHWC(32F, 2), "y0");
    34
    1
      ccv_nnc_symbolic_graph_set_case_of(symbolic_graph, case_of, case_0, 0, TENSOR_SYMBOL_MAP(KV(y0, y)));
    35
    1
      ccv_nnc_symbolic_graph_set_case_of_expr(symbolic_graph, case_of, _case_of, 0);
    36
    1
      ccv_nnc_tensor_symbol_t w01 = ccv_nnc_tensor_symbol_new(case_0, CPU_TENSOR_NHWC(32F, 1, 2), "w01");
    37
    1
      ccv_nnc_tensor_symbol_t b01 = ccv_nnc_tensor_symbol_new(case_0, CPU_TENSOR_NHWC(32F, 1), "b01");
    38
    1
      ccv_nnc_tensor_symbol_t z01 = ccv_nnc_tensor_symbol_new(case_0, CPU_TENSOR_NHWC(32F, 1), "z01");
    39
    1
      ccv_nnc_graph_exec_symbol_new(case_0, CMD_GEMM_FORWARD(NO_TRANSPOSE, TRANSPOSE(0, 1)), TENSOR_SYMBOL_LIST(x, w01, b01), TENSOR_SYMBOL_LIST(z01), "mul01");
    40
    1
      ccv_nnc_tensor_symbol_t w02 = ccv_nnc_tensor_symbol_new(case_0, CPU_TENSOR_NHWC(32F, 3, 1), "w02");
    41
    1
      ccv_nnc_tensor_symbol_t b02 = ccv_nnc_tensor_symbol_new(case_0, CPU_TENSOR_NHWC(32F, 3), "b02");
    42
    1
      ccv_nnc_tensor_symbol_t z02 = ccv_nnc_tensor_symbol_new(case_0, CPU_TENSOR_NHWC(32F, 3), "z02");
    43
    1
      ccv_nnc_graph_exec_symbol_new(case_0, CMD_GEMM_FORWARD(NO_TRANSPOSE, TRANSPOSE(0, 1)), TENSOR_SYMBOL_LIST(z01, w02, b02), TENSOR_SYMBOL_LIST(z02), "mul02");
    44
    1
      ccv_nnc_tensor_symbol_t w03 = ccv_nnc_tensor_symbol_new(case_0, CPU_TENSOR_NHWC(32F, 2, 3), "w03");
    45
    1
      ccv_nnc_tensor_symbol_t b03 = ccv_nnc_tensor_symbol_new(case_0, CPU_TENSOR_NHWC(32F, 2), "b03");
    46
    1
      ccv_nnc_tensor_symbol_t y01 = ccv_nnc_tensor_symbol_new(case_0, CPU_TENSOR_NHWC(32F, 2), "y01");
    47
    1
      ccv_nnc_graph_exec_symbol_new(case_0, CMD_GEMM_FORWARD(NO_TRANSPOSE, TRANSPOSE(0, 1)), TENSOR_SYMBOL_LIST(z02, w03, b03), TENSOR_SYMBOL_LIST(y01), "mul03");
    48
    1
      ccv_nnc_tensor_symbol_t w04 = ccv_nnc_tensor_symbol_new(case_0, CPU_TENSOR_NHWC(32F, 1, 2), "w04");
    49
    1
      ccv_nnc_tensor_symbol_t b04 = ccv_nnc_tensor_symbol_new(case_0, CPU_TENSOR_NHWC(32F, 1), "b04");
    50
    1
      ccv_nnc_tensor_symbol_t z04 = ccv_nnc_tensor_symbol_new(case_0, CPU_TENSOR_NHWC(32F, 1), "z04");
    51
    1
      ccv_nnc_graph_exec_symbol_new(case_0, CMD_GEMM_FORWARD(NO_TRANSPOSE, TRANSPOSE(0, 1)), TENSOR_SYMBOL_LIST(x, w04, b04), TENSOR_SYMBOL_LIST(z04), "mul04");
    52
    1
      ccv_nnc_tensor_symbol_t w05 = ccv_nnc_tensor_symbol_new(case_0, CPU_TENSOR_NHWC(32F, 2, 1), "w05");
    53
    1
      ccv_nnc_tensor_symbol_t b05 = ccv_nnc_tensor_symbol_new(case_0, CPU_TENSOR_NHWC(32F, 2), "b05");
    54
    1
      ccv_nnc_tensor_symbol_t y02 = ccv_nnc_tensor_symbol_new(case_0, CPU_TENSOR_NHWC(32F, 2), "y02");
    55
    1
      ccv_nnc_graph_exec_symbol_new(case_0, CMD_GEMM_FORWARD(NO_TRANSPOSE, TRANSPOSE(0, 1)), TENSOR_SYMBOL_LIST(z04, w05, b05), TENSOR_SYMBOL_LIST(y02), "mul05");
    56
    1
      ccv_nnc_graph_exec_symbol_new(case_0, CMD_EWSUM_FORWARD(), TENSOR_SYMBOL_LIST(y01, y02), TENSOR_SYMBOL_LIST(y0), "sum");
    57
    1
      ccv_nnc_graph_exec_symbol_autogen(case_0, 0, 0, CCV_NNC_AUTOGEN_ALL_EXECS | CCV_NNC_AUTOGEN_SOURCES_AND_DESTINATIONS);
    58
    1
      ccv_nnc_symbolic_graph_t* const case_2 = ccv_nnc_symbolic_graph_new();
    59
    1
      ccv_nnc_tensor_symbol_t y2 = ccv_nnc_tensor_symbol_new(case_2, CPU_TENSOR_NHWC(32F, 2), "y2");
    60
    1
      ccv_nnc_symbolic_graph_set_case_of(symbolic_graph, case_of, case_2, 1, TENSOR_SYMBOL_MAP(KV(y2, y)));
    61
    1
      ccv_nnc_tensor_symbol_t w21 = ccv_nnc_tensor_symbol_new(case_2, CPU_TENSOR_NHWC(32F, 8, 2), "w21");
    62
    1
      ccv_nnc_tensor_symbol_t b21 = ccv_nnc_tensor_symbol_new(case_2, CPU_TENSOR_NHWC(32F, 8), "b21");
    63
    1
      ccv_nnc_tensor_symbol_t z2 = ccv_nnc_tensor_symbol_new(case_2, CPU_TENSOR_NHWC(32F, 8), "z2");
    64
    1
      ccv_nnc_graph_exec_symbol_new(case_2, CMD_GEMM_FORWARD(NO_TRANSPOSE, TRANSPOSE(0, 1)), TENSOR_SYMBOL_LIST(x, w21, b21), TENSOR_SYMBOL_LIST(z2), "mul21");
    65
    1
      ccv_nnc_tensor_symbol_t w22 = ccv_nnc_tensor_symbol_new(case_2, CPU_TENSOR_NHWC(32F, 2, 8), "w22");
    66
    1
      ccv_nnc_tensor_symbol_t b22 = ccv_nnc_tensor_symbol_new(case_2, CPU_TENSOR_NHWC(32F, 2), "b22");
    67
    1
      ccv_nnc_graph_exec_symbol_new(case_2, CMD_GEMM_FORWARD(NO_TRANSPOSE, TRANSPOSE(0, 1)), TENSOR_SYMBOL_LIST(z2, w22, b22), TENSOR_SYMBOL_LIST(y2), "mul22");
    68
    1
      ccv_nnc_graph_exec_symbol_autogen(case_2, 0, 0, CCV_NNC_AUTOGEN_ALL_EXECS | CCV_NNC_AUTOGEN_SOURCES_AND_DESTINATIONS);
    69
    1
      ccv_nnc_symbolic_graph_t* const case_1 = ccv_nnc_symbolic_graph_new();
    70
    1
      ccv_nnc_tensor_symbol_t y1 = ccv_nnc_tensor_symbol_new(case_1, CPU_TENSOR_NHWC(32F, 2), "y0");
    71
    1
      ccv_nnc_symbolic_graph_set_case_of(symbolic_graph, case_of, case_1, 2, TENSOR_SYMBOL_MAP(KV(y1, y)));
    72
    1
      ccv_nnc_tensor_symbol_t w11 = ccv_nnc_tensor_symbol_new(case_1, CPU_TENSOR_NHWC(32F, 16, 2), "w11");
    73
    1
      ccv_nnc_tensor_symbol_t b11 = ccv_nnc_tensor_symbol_new(case_1, CPU_TENSOR_NHWC(32F, 16), "b11");
    74
    1
      ccv_nnc_tensor_symbol_t z1 = ccv_nnc_tensor_symbol_new(case_1, CPU_TENSOR_NHWC(32F, 16), "z1");
    75
    1
      ccv_nnc_graph_exec_symbol_new(case_1, CMD_GEMM_FORWARD(NO_TRANSPOSE, TRANSPOSE(0, 1)), TENSOR_SYMBOL_LIST(x, w11, b11), TENSOR_SYMBOL_LIST(z1), "mul11");
    76
    1
      ccv_nnc_tensor_symbol_t w12 = ccv_nnc_tensor_symbol_new(case_1, CPU_TENSOR_NHWC(32F, 2, 16), "w12");
    77
    1
      ccv_nnc_tensor_symbol_t b12 = ccv_nnc_tensor_symbol_new(case_1, CPU_TENSOR_NHWC(32F, 2), "b12");
    78
    1
      ccv_nnc_graph_exec_symbol_new(case_1, CMD_GEMM_FORWARD(NO_TRANSPOSE, TRANSPOSE(0, 1)), TENSOR_SYMBOL_LIST(z1, w12, b12), TENSOR_SYMBOL_LIST(y1), "mul12");
    79
    1
      ccv_nnc_graph_exec_symbol_autogen(case_1, 0, 0, CCV_NNC_AUTOGEN_ALL_EXECS | CCV_NNC_AUTOGEN_SOURCES_AND_DESTINATIONS);
    80
    1
      ccv_nnc_graph_exec_symbol_autogen(symbolic_graph, 0, 0, CCV_NNC_AUTOGEN_ALL_EXECS | CCV_NNC_AUTOGEN_SOURCES_AND_DESTINATIONS);
    81
    1
      SYMBOLIC_GRAPH_GEN(symbolic_graph, CCV_NNC_LONG_DOT_GRAPH);
    82
    1
      ccv_nnc_graph_t* graph;
    83
    1
      ccv_nnc_tensor_arena_t* tensor_arena;
    84
    1
      ccv_nnc_graph_exec_arena_t* graph_exec_arena;
    85
    1
      ccv_nnc_symbolic_graph_compile(symbolic_graph, ccv_nnc_default_compile_params, 0, 0, 0, 0, SYMBOLIC_GRAPH_SOURCES(symbolic_graph), SYMBOLIC_GRAPH_DESTINATIONS(symbolic_graph), &graph, &tensor_arena, &graph_exec_arena);
    86
    1
      GRAPH_GEN(graph, CCV_NNC_LONG_DOT_GRAPH);
    87
    88
    1
      ccv_nnc_tensor_t* const x_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, x);
    89
    1
      x_tensor->data.f32[0] = -1;
    90
    1
      x_tensor->data.f32[1] = 10;
    91
    1
      ccv_nnc_tensor_t* const yt = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2), 0);
    92
    1
      yt->data.f32[0] = -1;
    93
    1
      yt->data.f32[1] = 10;
    94
    1
      ccv_nnc_graph_run(graph, 0, TRAVERSE_FULL, 0, 0);
    95
    1
      ccv_nnc_tensor_t* y_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, y);
    96
    1
      REQUIRE_TENSOR_EQ(y_tensor, yt, "skip any computation");
    97
    98
    1
      dsfmt_t dsfmt;
    99
    1
      dsfmt_init_gen_rand(&dsfmt, 0);
    100
    1
      int i;
    101
    102
    1
      x_tensor->data.f32[0] = 0.5;
    103
    1
      x_tensor->data.f32[1] = 1;
    104
    1
      ccv_nnc_tensor_t* w01_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, w01);
    105
    1
      w01_tensor->data.f32[0] = 0.1;
    106
    1
      w01_tensor->data.f32[1] = -0.28;
    107
    1
      ccv_nnc_tensor_t* b01_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, b01);
    108
    1
      b01_tensor->data.f32[0] = 1;
    109
    1
      ccv_nnc_tensor_t* w02_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, w02);
    110
    1
      float w02t[3];
    111
    4
      for (i = 0; i < 3; i++3)
    112
    3
        w02t[i] = w02_tensor->data.f32[i] = dsfmt_genrand_open_close(&dsfmt);
    113
    1
      ccv_nnc_tensor_t* b02_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, b02);
    114
    1
      float b02t[3];
    115
    4
      for (i = 0; i < 3; i++3)
    116
    3
        b02t[i] = b02_tensor->data.f32[i] = dsfmt_genrand_open_close(&dsfmt);
    117
    1
      ccv_nnc_tensor_t* w03_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, w03);
    118
    1
      float w03t[6];
    119
    7
      for (i = 0; i < 6; i++6)
    120
    6
        w03t[i] = w03_tensor->data.f32[i] = dsfmt_genrand_open_close(&dsfmt);
    121
    1
      ccv_nnc_tensor_t* b03_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, b03);
    122
    1
      float b03t[2];
    123
    3
      for (i = 0; i < 2; i++2)
    124
    2
        b03t[i] = b03_tensor->data.f32[i] = dsfmt_genrand_open_close(&dsfmt);
    125
    1
      ccv_nnc_tensor_t* w04_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, w04);
    126
    1
      w04_tensor->data.f32[0] = -1.11;
    127
    1
      w04_tensor->data.f32[1] = 15;
    128
    1
      ccv_nnc_tensor_t* b04_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, b04);
    129
    1
      b04_tensor->data.f32[0] = 0.2;
    130
    1
      ccv_nnc_tensor_t* w05_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, w05);
    131
    1
      w05_tensor->data.f32[0] = 3.1;
    132
    1
      w05_tensor->data.f32[1] = 3.3;
    133
    1
      ccv_nnc_tensor_t* b05_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, b05);
    134
    1
      b05_tensor->data.f32[0] = -0.2;
    135
    1
      b05_tensor->data.f32[1] = -0.3;
    136
    1
      ccv_nnc_graph_run(graph, 0, TRAVERSE_FULL, 0, 0);
    137
    1
      y_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, y);
    138
    1
      const float z01val = 0.5 * 0.1 - 0.28 + 1;
    139
    1
      yt->data.f32[0] = b03t[0];
    140
    1
      yt->data.f32[1] = b03t[1];
    141
    4
      for (i = 0; i < 3; i++3)
    142
    3
      {
    143
    3
        const float z02val = z01val * w02t[i] + b02t[i];
    144
    3
        yt->data.f32[0] += z02val * w03t[i];
    145
    3
        yt->data.f32[1] += z02val * w03t[i + 3];
    146
    3
      }
    147
    1
      const float z04val = 0.5 * -1.11 + 15 + 0.2;
    148
    1
      yt->data.f32[0] += z04val * 3.1 - 0.2;
    149
    1
      yt->data.f32[1] += z04val * 3.3 - 0.3;
    150
    1
      REQUIRE_TENSOR_EQ(y_tensor, yt, "((x * w01 + b01) * w02 + b02) * w03 + b03");
    151
    152
    1
      x_tensor->data.f32[0] = 1.11;
    153
    1
      x_tensor->data.f32[1] = 2.56;
    154
    1
      ccv_nnc_tensor_t* w11_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, w11);
    155
    1
      float w11t[32];
    156
    33
      for (i = 0; i < 32; i++32)
    157
    32
        w11t[i] = w11_tensor->data.f32[i] = dsfmt_genrand_open_close(&dsfmt);
    158
    1
      ccv_nnc_tensor_t* b11_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, b11);
    159
    1
      float b11t[16];
    160
    17
      for (i = 0; i < 16; i++16)
    161
    16
        b11t[i] = b11_tensor->data.f32[i] = dsfmt_genrand_open_close(&dsfmt);
    162
    1
      ccv_nnc_tensor_t* w12_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, w12);
    163
    1
      float w12t[32];
    164
    33
      for (i = 0; i < 32; i++32)
    165
    32
        w12t[i] = w12_tensor->data.f32[i] = dsfmt_genrand_open_close(&dsfmt);
    166
    1
      ccv_nnc_tensor_t* b12_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, b12);
    167
    1
      b12_tensor->data.f32[0] = 0.32;
    168
    1
      b12_tensor->data.f32[1] = -0.2;
    169
    1
      ccv_nnc_graph_autotune(graph, 0, 0, TRAVERSE_FULL);
    170
    1
      ccv_nnc_graph_run(graph, 0, TRAVERSE_FULL, 0, 0);
    171
    1
      yt->data.f32[0] = 0.32;
    172
    1
      yt->data.f32[1] = -0.2;
    173
    17
      for (i = 0; i < 16; i++16)
    174
    16
      {
    175
    16
        float z1val = 1.11 * w11t[i * 2] + 2.56 * w11t[i * 2 + 1] + b11t[i];
    176
    16
        yt->data.f32[0] += z1val * w12t[i];
    177
    16
        yt->data.f32[1] += z1val * w12t[i + 16];
    178
    16
      }
    179
    1
      y_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, y);
    180
    1
      REQUIRE_TENSOR_EQ(y_tensor, yt, "(x * w11 + b11) * w12 + b12");
    181
    182
    1
      x_tensor->data.f32[0] = 4.5;
    183
    1
      x_tensor->data.f32[1] = 3.33;
    184
    1
      ccv_nnc_tensor_t* w21_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, w21);
    185
    17
      for (i = 0; i < 16; i++16)
    186
    16
        w11t[i] = w21_tensor->data.f32[i] = dsfmt_genrand_open_close(&dsfmt);
    187
    1
      ccv_nnc_tensor_t* b21_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, b21);
    188
    9
      for (i = 0; i < 8; i++8)
    189
    8
        b11t[i] = b21_tensor->data.f32[i] = dsfmt_genrand_open_close(&dsfmt);
    190
    1
      ccv_nnc_tensor_t* w22_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, w22);
    191
    17
      for (i = 0; i < 16; i++16)
    192
    16
        w12t[i] = w22_tensor->data.f32[i] = dsfmt_genrand_open_close(&dsfmt);
    193
    1
      ccv_nnc_tensor_t* b22_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, b22);
    194
    1
      b22_tensor->data.f32[0] = 3.32;
    195
    1
      b22_tensor->data.f32[1] = -2;
    196
    1
      ccv_nnc_graph_run(graph, 0, TRAVERSE_FULL, 0, 0);
    197
    1
      yt->data.f32[0] = 3.32;
    198
    1
      yt->data.f32[1] = -2;
    199
    1
      assert(w11_tensor->data.f32 != w21_tensor->data.f32);
    200
    9
      for (i = 0; 1i < 8; i++8)
    201
    8
      {
    202
    8
        float z2val = 4.5 * w11t[i * 2] + 3.33 * w11t[i * 2 + 1] + b11t[i];
    203
    8
        yt->data.f32[0] += z2val * w12t[i];
    204
    8
        yt->data.f32[1] += z2val * w12t[i + 8];
    205
    8
      }
    206
    1
      y_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, y);
    207
    1
      REQUIRE_TENSOR_EQ(y_tensor, yt, "(x * w21 + b21) * w22 + b22");
    208
    209
    1
      ccv_nnc_tensor_free(yt);
    210
    1
      ccv_nnc_symbolic_graph_free(symbolic_graph);
    211
    1
      ccv_nnc_graph_free(graph);
    212
    1
      ccv_nnc_tensor_arena_free(tensor_arena);
    213
    1
      ccv_nnc_graph_exec_arena_free(graph_exec_arena);
    214
    1
    }
    215
    216
    #include "case_main.h"