## 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/case_of.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 piecewise_case_of(ccv_nnc_tensor_t* const* const inputs, const int input_size, const void* const data)
    15
    25
    {
    16
    25
      assert(input_size == 1);
    17
    25
      if (inputs[0]->data.f32[0] < 0)
    18
    3
        return 0;
    19
    22
      else if (inputs[0]->data.f32[0] < 1)
    20
    9
        return -1; // Pass through because the computation is essentially x * 1
    21
    13
      else if (inputs[0]->data.f32[0] < 2)
    22
    8
        return 1;
    23
    5
      else if (inputs[0]->data.f32[0] > 1000)
    24
    1
        return 3;
    25
    4
      else
    26
    4
        return 2;
    27
    25
    }
    28
    29
    static int while_4(ccv_nnc_tensor_t* const* const inputs, const int input_size, const void* const data)
    30
    15
    {
    31
    15
      return inputs[0]->data.i64[0] < 4;
    32
    15
    }
    33
    34
    TEST_CASE("graph for a piece-wise linear function")
    35
    1
    {
    36
    1
      ccv_nnc_graph_t* const graph = ccv_nnc_graph_new();
    37
    1
      ccv_nnc_tensor_t* x = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 1), 0);
    38
    1
      ccv_nnc_graph_exec_t case_of = ccv_nnc_graph_case_of_new(graph, CCV_NNC_GRAPH_FORWARD, TENSOR_LIST(x), 0, 0);
    39
    1
      ccv_nnc_graph_set_case_of_expr(graph, case_of, piecewise_case_of, 0, 0);
    40
    1
      ccv_nnc_graph_t* graph_0 = ccv_nnc_graph_new();
    41
    1
      ccv_nnc_graph_exec_t set_0 = ccv_nnc_graph_exec_new(graph_0, CMD_SET_FORWARD(0), ccv_nnc_no_hint, 0, 0, TENSOR_LIST(x));
    42
    1
      ccv_nnc_graph_set_sources(graph_0, GRAPH_EXEC_LIST(set_0));
    43
    1
      ccv_nnc_graph_set_destinations(graph_0, GRAPH_EXEC_LIST(set_0));
    44
    1
      ccv_nnc_graph_set_case_of(graph, case_of, graph_0, 0);
    45
    1
      ccv_nnc_graph_t* graph_1 = ccv_nnc_graph_new();
    46
    1
      ccv_nnc_tensor_t* p1 = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 1), 0);
    47
    1
      p1->data.f32[0] = 0.5;
    48
    1
      ccv_nnc_tensor_t* s1 = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 1), 0);
    49
    1
      s1->data.f32[0] = 0.5;
    50
    1
      ccv_nnc_graph_exec_t prod_1 = ccv_nnc_graph_exec_new(graph_1, CMD_EWPROD_FORWARD(), ccv_nnc_no_hint, TENSOR_LIST(x, p1), TENSOR_LIST(x));
    51
    1
      ccv_nnc_graph_exec_t sum_1 = ccv_nnc_graph_exec_new(graph_1, CMD_EWSUM_FORWARD(), ccv_nnc_no_hint, TENSOR_LIST(x, s1), TENSOR_LIST(x));
    52
    1
      ccv_nnc_graph_exec_concat(graph_1, prod_1, sum_1);
    53
    1
      ccv_nnc_graph_set_sources(graph_1, GRAPH_EXEC_LIST(prod_1));
    54
    1
      ccv_nnc_graph_set_destinations(graph_1, GRAPH_EXEC_LIST(sum_1));
    55
    1
      ccv_nnc_graph_set_case_of(graph, case_of, graph_1, 1);
    56
    1
      ccv_nnc_graph_t* graph_2 = ccv_nnc_graph_new();
    57
    1
      ccv_nnc_graph_exec_t set_2 = ccv_nnc_graph_exec_new(graph_2, CMD_SET_FORWARD(1.5), ccv_nnc_no_hint, 0, 0, TENSOR_LIST(x));
    58
    1
      ccv_nnc_graph_set_sources(graph_2, GRAPH_EXEC_LIST(set_2));
    59
    1
      ccv_nnc_graph_set_destinations(graph_2, GRAPH_EXEC_LIST(set_2));
    60
    1
      ccv_nnc_graph_set_case_of(graph, case_of, graph_2, 2);
    61
    1
      GRAPH_GEN(graph, CCV_NNC_LONG_DOT_GRAPH);
    62
    1
      x->data.f32[0] = -1;
    63
    1
      ccv_nnc_graph_run(graph, 0, GRAPH_EXEC_LIST(case_of), GRAPH_EXEC_LIST(case_of), 0, 0);
    64
    1
      REQUIRE_EQ_WITH_TOLERANCE(x->data.f32[0], 0, 1e-5, "in negative region should equal to 0");
    65
    1
      x->data.f32[0] = 0.76;
    66
    1
      ccv_nnc_graph_run(graph, 0, GRAPH_EXEC_LIST(case_of), GRAPH_EXEC_LIST(case_of), 0, 0);
    67
    1
      REQUIRE_EQ_WITH_TOLERANCE(x->data.f32[0], 0.76, 1e-5, "y = x in (0, 1)");
    68
    1
      x->data.f32[0] = 1.226;
    69
    1
      ccv_nnc_graph_run(graph, 0, GRAPH_EXEC_LIST(case_of), GRAPH_EXEC_LIST(case_of), 0, 0);
    70
    1
      REQUIRE_EQ_WITH_TOLERANCE(x->data.f32[0], (1.226 - 1) * 0.5 + 1, 1e-5, "y = (x - 1) * 0.5 + 1 in (1, 2)");
    71
    1
      x->data.f32[0] = 2.1;
    72
    1
      ccv_nnc_graph_run(graph, 0, GRAPH_EXEC_LIST(case_of), GRAPH_EXEC_LIST(case_of), 0, 0);
    73
    1
      REQUIRE_EQ_WITH_TOLERANCE(x->data.f32[0], 1.5, 1e-5, "y = 1.5 if x > 2");
    74
    1
      ccv_nnc_tensor_free(x);
    75
    1
      ccv_nnc_tensor_free(p1);
    76
    1
      ccv_nnc_tensor_free(s1);
    77
    1
      ccv_nnc_graph_free(graph);
    78
    1
    }
    79
    80
    TEST_CASE("symbolic graph for piece-wise function")
    81
    1
    {
    82
    1
      ccv_nnc_symbolic_graph_t* const symbolic_graph = ccv_nnc_symbolic_graph_new();
    83
    1
      ccv_nnc_tensor_symbol_t x = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 1), "x");
    84
    1
      ccv_nnc_tensor_symbol_t y = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 1), "y");
    85
    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)), "piece-wise linear");
    86
    1
      ccv_nnc_symbolic_graph_set_case_of_expr(symbolic_graph, case_of, piecewise_case_of, 0);
    87
    1
      ccv_nnc_symbolic_graph_t* const symbolic_graph_0 = ccv_nnc_symbolic_graph_new();
    88
    1
      ccv_nnc_tensor_symbol_t y0 = ccv_nnc_tensor_symbol_new(symbolic_graph_0, CPU_TENSOR_NHWC(32F, 1), "y0");
    89
    1
      ccv_nnc_symbolic_graph_set_case_of(symbolic_graph, case_of, symbolic_graph_0, 0, TENSOR_SYMBOL_MAP(KV(y0, y)));
    90
    1
      ccv_nnc_graph_exec_symbol_new(symbolic_graph_0, CMD_SET_FORWARD(0), 0, 0, TENSOR_SYMBOL_LIST(y0), "set");
    91
    1
      ccv_nnc_graph_exec_symbol_autogen(symbolic_graph_0, 0, 0, CCV_NNC_AUTOGEN_ALL_EXECS | CCV_NNC_AUTOGEN_SOURCES_AND_DESTINATIONS);
    92
    1
      ccv_nnc_symbolic_graph_t* const symbolic_graph_1 = ccv_nnc_symbolic_graph_new();
    93
    1
      ccv_nnc_tensor_symbol_t y1 = ccv_nnc_tensor_symbol_new(symbolic_graph_1, CPU_TENSOR_NHWC(32F, 1), "y1");
    94
    1
      ccv_nnc_symbolic_graph_set_case_of(symbolic_graph, case_of, symbolic_graph_1, 1, TENSOR_SYMBOL_MAP(KV(y1, y)));
    95
    1
      ccv_nnc_tensor_symbol_t s1 = ccv_nnc_tensor_symbol_new(symbolic_graph_1, CPU_TENSOR_NHWC(32F, 1), "s");
    96
    1
      ccv_nnc_tensor_symbol_t z1 = ccv_nnc_tensor_symbol_new(symbolic_graph_1, CPU_TENSOR_NHWC(32F, 1), "z1");
    97
    1
      ccv_nnc_tensor_symbol_t p1 = ccv_nnc_tensor_symbol_new(symbolic_graph_1, CPU_TENSOR_NHWC(32F, 1), "p");
    98
    1
      ccv_nnc_graph_exec_symbol_new(symbolic_graph_1, CMD_EWPROD_FORWARD(), TENSOR_SYMBOL_LIST(x, s1), TENSOR_SYMBOL_LIST(z1), "prod");
    99
    1
      ccv_nnc_graph_exec_symbol_new(symbolic_graph_1, CMD_EWSUM_FORWARD(), TENSOR_SYMBOL_LIST(z1, p1), TENSOR_SYMBOL_LIST(y1), "sum");
    100
    1
      ccv_nnc_graph_exec_symbol_autogen(symbolic_graph_1, 0, 0, CCV_NNC_AUTOGEN_ALL_EXECS | CCV_NNC_AUTOGEN_SOURCES_AND_DESTINATIONS);
    101
    1
      ccv_nnc_symbolic_graph_t* const symbolic_graph_2 = ccv_nnc_symbolic_graph_new();
    102
    1
      ccv_nnc_tensor_symbol_t y2 = ccv_nnc_tensor_symbol_new(symbolic_graph_2, CPU_TENSOR_NHWC(32F, 1), "y2");
    103
    1
      ccv_nnc_symbolic_graph_set_case_of(symbolic_graph, case_of, symbolic_graph_2, 2, TENSOR_SYMBOL_MAP(KV(y2, y)));
    104
    1
      ccv_nnc_graph_exec_symbol_new(symbolic_graph_2, CMD_SET_FORWARD(1.5), 0, 0, TENSOR_SYMBOL_LIST(y2), "set");
    105
    1
      ccv_nnc_graph_exec_symbol_autogen(symbolic_graph_2, 0, 0, CCV_NNC_AUTOGEN_ALL_EXECS | CCV_NNC_AUTOGEN_SOURCES_AND_DESTINATIONS);
    106
    1
      SYMBOLIC_GRAPH_GEN(symbolic_graph, CCV_NNC_LONG_DOT_GRAPH);
    107
    1
      ccv_nnc_graph_t* graph = 0;
    108
    1
      ccv_nnc_tensor_arena_t* tensor_arena = 0;
    109
    1
      ccv_nnc_graph_exec_arena_t* graph_exec_arena = 0;
    110
    1
      ccv_nnc_symbolic_graph_compile(symbolic_graph, ccv_nnc_default_compile_params, 0, 0, 0, 0, &case_of, 1, &case_of, 1, &graph, &tensor_arena, &graph_exec_arena);
    111
    1
      GRAPH_GEN(graph, CCV_NNC_LONG_DOT_GRAPH);
    112
    1
      ccv_nnc_tensor_t* x_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, x);
    113
    1
      ccv_nnc_tensor_t* y_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, y);
    114
    1
      ccv_nnc_tensor_t* s1_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, s1);
    115
    1
      ccv_nnc_tensor_t* p1_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, p1);
    116
    1
      s1_tensor->data.f32[0] = 0.5;
    117
    1
      p1_tensor->data.f32[0] = 0.5;
    118
    1
      x_tensor->data.f32[0] = -1;
    119
    1
      ccv_nnc_graph_run(graph, 0, TRAVERSE_FULL, 0, 0);
    120
    1
      REQUIRE_EQ_WITH_TOLERANCE(y_tensor->data.f32[0], 0, 1e-5, "in negative region should equal to 0");
    121
    1
      x_tensor->data.f32[0] = 0.76;
    122
    1
      ccv_nnc_graph_run(graph, 0, TRAVERSE_FULL, 0, 0);
    123
    1
      REQUIRE_EQ_WITH_TOLERANCE(y_tensor->data.f32[0], 0.76, 1e-5, "y = x in (0, 1)");
    124
    1
      s1_tensor->data.f32[0] = 0.5;
    125
    1
      p1_tensor->data.f32[0] = 0.5;
    126
    1
      x_tensor->data.f32[0] = 1.226;
    127
    1
      ccv_nnc_graph_run(graph, 0, TRAVERSE_FULL, 0, 0);
    128
    1
      REQUIRE_EQ_WITH_TOLERANCE(y_tensor->data.f32[0], (1.226 - 1) * 0.5 + 1, 1e-5, "y = (x - 1) * 0.5 + 1 in (1, 2)");
    129
    1
      s1_tensor->data.f32[0] = 0.5;
    130
    1
      p1_tensor->data.f32[0] = 0.5;
    131
    1
      x_tensor->data.f32[0] = 2.1;
    132
    1
      ccv_nnc_graph_run(graph, 0, TRAVERSE_FULL, 0, 0);
    133
    1
      REQUIRE_EQ_WITH_TOLERANCE(y_tensor->data.f32[0], 1.5, 1e-5, "y = 1.5 if x > 2");
    134
    1
      ccv_nnc_symbolic_graph_free(symbolic_graph);
    135
    1
      ccv_nnc_graph_exec_arena_free(graph_exec_arena);
    136
    1
      ccv_nnc_tensor_arena_free(tensor_arena);
    137
    1
      ccv_nnc_graph_free(graph);
    138
    1
    }
    139
    140
    TEST_CASE("symbolic graph case..of when reuse intermediate tensors")
    141
    1
    {
    142
    1
      ccv_nnc_symbolic_graph_t* const symbolic_graph = ccv_nnc_symbolic_graph_new();
    143
    1
      ccv_nnc_tensor_symbol_t x = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 2), "x");
    144
    1
      ccv_nnc_tensor_symbol_t y = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 2), "y");
    145
    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)), "piece-wise linear vector");
    146
    1
      ccv_nnc_symbolic_graph_set_case_of_expr(symbolic_graph, case_of, piecewise_case_of, 0);
    147
    1
      ccv_nnc_symbolic_graph_t* const symbolic_graph_0 = ccv_nnc_symbolic_graph_new();
    148
    1
      ccv_nnc_tensor_symbol_t z0 = ccv_nnc_tensor_symbol_new(symbolic_graph_0, CPU_TENSOR_NHWC(32F, 2), "z0");
    149
    1
      ccv_nnc_tensor_symbol_t u0 = ccv_nnc_tensor_symbol_new(symbolic_graph_0, CPU_TENSOR_NHWC(32F, 2, 2), "u0");
    150
    1
      ccv_nnc_tensor_symbol_t w0 = ccv_nnc_tensor_symbol_new(symbolic_graph_0, CPU_TENSOR_NHWC(32F, 2, 2), "w0");
    151
    1
      ccv_nnc_tensor_symbol_t b0 = ccv_nnc_tensor_symbol_new(symbolic_graph_0, CPU_TENSOR_NHWC(32F, 2), "b0");
    152
    1
      ccv_nnc_tensor_symbol_t c0 = ccv_nnc_tensor_symbol_new(symbolic_graph_0, CPU_TENSOR_NHWC(32F, 2), "c0");
    153
    1
      ccv_nnc_tensor_symbol_t y0 = ccv_nnc_tensor_symbol_new(symbolic_graph_0, CPU_TENSOR_NHWC(32F, 2), "y0");
    154
    1
      ccv_nnc_symbolic_graph_set_case_of(symbolic_graph, case_of, symbolic_graph_0, 0, TENSOR_SYMBOL_MAP(KV(y0, y)));
    155
    1
      ccv_nnc_graph_exec_symbol_new(symbolic_graph_0, CMD_GEMM_FORWARD(NO_TRANSPOSE, TRANSPOSE(0, 1)), TENSOR_SYMBOL_LIST(x, u0, b0), TENSOR_SYMBOL_LIST(z0), "mmu");
    156
    1
      ccv_nnc_graph_exec_symbol_new(symbolic_graph_0, CMD_GEMM_FORWARD(NO_TRANSPOSE, TRANSPOSE(0, 1)), TENSOR_SYMBOL_LIST(z0, w0, c0), TENSOR_SYMBOL_LIST(y0), "mmw");
    157
    1
      ccv_nnc_graph_exec_symbol_autogen(symbolic_graph_0, 0, 0, CCV_NNC_AUTOGEN_ALL_EXECS | CCV_NNC_AUTOGEN_SOURCES_AND_DESTINATIONS);
    158
    1
      ccv_nnc_symbolic_graph_t* const symbolic_graph_1 = ccv_nnc_symbolic_graph_new();
    159
    1
      ccv_nnc_tensor_symbol_t z1 = ccv_nnc_tensor_symbol_new(symbolic_graph_1, CPU_TENSOR_NHWC(32F, 2), "z1");
    160
    1
      ccv_nnc_tensor_symbol_t u1 = ccv_nnc_tensor_symbol_new(symbolic_graph_1, CPU_TENSOR_NHWC(32F, 2, 2), "u1");
    161
    1
      ccv_nnc_tensor_symbol_t w1 = ccv_nnc_tensor_symbol_new(symbolic_graph_1, CPU_TENSOR_NHWC(32F, 2, 2), "w1");
    162
    1
      ccv_nnc_tensor_symbol_t b1 = ccv_nnc_tensor_symbol_new(symbolic_graph_1, CPU_TENSOR_NHWC(32F, 2), "b1");
    163
    1
      ccv_nnc_tensor_symbol_t c1 = ccv_nnc_tensor_symbol_new(symbolic_graph_1, CPU_TENSOR_NHWC(32F, 2), "c1");
    164
    1
      ccv_nnc_tensor_symbol_t y1 = ccv_nnc_tensor_symbol_new(symbolic_graph_1, CPU_TENSOR_NHWC(32F, 2), "y1");
    165
    1
      ccv_nnc_symbolic_graph_set_case_of(symbolic_graph, case_of, symbolic_graph_1, 1, TENSOR_SYMBOL_MAP(KV(y1, y)));
    166
    1
      ccv_nnc_graph_exec_symbol_new(symbolic_graph_1, CMD_GEMM_FORWARD(NO_TRANSPOSE, TRANSPOSE(0, 1)), TENSOR_SYMBOL_LIST(x, u1, b1), TENSOR_SYMBOL_LIST(z1), "mmu1");
    167
    1
      ccv_nnc_graph_exec_symbol_new(symbolic_graph_1, CMD_GEMM_FORWARD(NO_TRANSPOSE, TRANSPOSE(0, 1)), TENSOR_SYMBOL_LIST(z1, w1, c1), TENSOR_SYMBOL_LIST(y1), "mmw1");
    168
    1
      ccv_nnc_graph_exec_symbol_autogen(symbolic_graph_1, 0, 0, CCV_NNC_AUTOGEN_ALL_EXECS | CCV_NNC_AUTOGEN_SOURCES_AND_DESTINATIONS);
    169
    1
      SYMBOLIC_GRAPH_GEN(symbolic_graph, CCV_NNC_LONG_DOT_GRAPH);
    170
    1
      ccv_nnc_graph_t* graph = 0;
    171
    1
      ccv_nnc_tensor_arena_t* tensor_arena = 0;
    172
    1
      ccv_nnc_graph_exec_arena_t* graph_exec_arena = 0;
    173
    1
      ccv_nnc_symbolic_graph_compile(symbolic_graph, ccv_nnc_default_compile_params, 0, 0, 0, 0, &case_of, 1, &case_of, 1, &graph, &tensor_arena, &graph_exec_arena);
    174
    1
      GRAPH_GEN(graph, CCV_NNC_LONG_DOT_GRAPH);
    175
    1
      ccv_nnc_tensor_t* z0_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, z0);
    176
    1
      ccv_nnc_tensor_t* z1_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, z1);
    177
    1
      REQUIRE(z0_tensor->data.f32 == z1_tensor->data.f32, "z0 and z1 should be allocated to the same location");
    178
    1
      ccv_nnc_symbolic_graph_free(symbolic_graph);
    179
    1
      ccv_nnc_graph_exec_arena_free(graph_exec_arena);
    180
    1
      ccv_nnc_tensor_arena_free(tensor_arena);
    181
    1
      ccv_nnc_graph_free(graph);
    182
    1
    }
    183
    184
    TEST_CASE("symbolic graph case..of with 4 branches")
    185
    1
    {
    186
    1
      ccv_nnc_symbolic_graph_t* const symbolic_graph = ccv_nnc_symbolic_graph_new();
    187
    1
      ccv_nnc_tensor_symbol_t x = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 1), "x");
    188
    1
      ccv_nnc_tensor_symbol_t y = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 1), "y");
    189
    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)), "4 branches");
    190
    1
      ccv_nnc_symbolic_graph_set_case_of_expr(symbolic_graph, case_of, piecewise_case_of, 0);
    191
    1
      ccv_nnc_symbolic_graph_t* const case_of_0 = ccv_nnc_symbolic_graph_new();
    192
    1
      ccv_nnc_tensor_symbol_t b = ccv_nnc_tensor_symbol_new(case_of_0, CPU_TENSOR_NHWC(32F, 1), "b0");
    193
    1
      ccv_nnc_symbolic_graph_set_case_of(symbolic_graph, case_of, case_of_0, 0, TENSOR_SYMBOL_MAP(KV(b, y)));
    194
    1
      ccv_nnc_graph_exec_symbol_new(case_of_0, CMD_EWEXP_FORWARD(), TENSOR_SYMBOL_LIST(x), TENSOR_SYMBOL_LIST(b), "exp");
    195
    1
      ccv_nnc_graph_exec_symbol_autogen(case_of_0, 0, 0, CCV_NNC_AUTOGEN_ALL_EXECS | CCV_NNC_AUTOGEN_SOURCES_AND_DESTINATIONS);
    196
    1
      ccv_nnc_symbolic_graph_t* const case_of_1 = ccv_nnc_symbolic_graph_new();
    197
    1
      b = ccv_nnc_tensor_symbol_new(case_of_1, CPU_TENSOR_NHWC(32F, 1), "b1");
    198
    1
      ccv_nnc_symbolic_graph_set_case_of(symbolic_graph, case_of, case_of_1, 1, TENSOR_SYMBOL_MAP(KV(b, y)));
    199
    1
      ccv_nnc_graph_exec_symbol_new(case_of_1, CMD_EWLOG_FORWARD(), TENSOR_SYMBOL_LIST(x), TENSOR_SYMBOL_LIST(b), "log");
    200
    1
      ccv_nnc_graph_exec_symbol_autogen(case_of_1, 0, 0, CCV_NNC_AUTOGEN_ALL_EXECS | CCV_NNC_AUTOGEN_SOURCES_AND_DESTINATIONS);
    201
    1
      ccv_nnc_symbolic_graph_t* const case_of_2 = ccv_nnc_symbolic_graph_new();
    202
    1
      b = ccv_nnc_tensor_symbol_new(case_of_2, CPU_TENSOR_NHWC(32F, 1), "b2");
    203
    1
      ccv_nnc_symbolic_graph_set_case_of(symbolic_graph, case_of, case_of_2, 2, TENSOR_SYMBOL_MAP(KV(b, y)));
    204
    1
      ccv_nnc_graph_exec_symbol_new(case_of_2, CMD_EWDIV_FORWARD(), TENSOR_SYMBOL_LIST(NO_TENSOR_SYMBOL, x), TENSOR_SYMBOL_LIST(b), "1/b");
    205
    1
      ccv_nnc_graph_exec_symbol_autogen(case_of_2, 0, 0, CCV_NNC_AUTOGEN_ALL_EXECS | CCV_NNC_AUTOGEN_SOURCES_AND_DESTINATIONS);
    206
    1
      ccv_nnc_symbolic_graph_t* const case_of_3 = ccv_nnc_symbolic_graph_new();
    207
    1
      b = ccv_nnc_tensor_symbol_new(case_of_3, CPU_TENSOR_NHWC(32F, 1), "b3");
    208
    1
      ccv_nnc_symbolic_graph_set_case_of(symbolic_graph, case_of, case_of_3, 3, TENSOR_SYMBOL_MAP(KV(b, y)));
    209
    1
      ccv_nnc_graph_exec_symbol_new(case_of_3, CMD_SCALAR_MUL_FORWARD(1.1), TENSOR_SYMBOL_LIST(x), TENSOR_SYMBOL_LIST(b), "1.1b");
    210
    1
      ccv_nnc_graph_exec_symbol_autogen(case_of_3, 0, 0, CCV_NNC_AUTOGEN_ALL_EXECS | CCV_NNC_AUTOGEN_SOURCES_AND_DESTINATIONS);
    211
    1
      ccv_nnc_graph_exec_symbol_autogen(symbolic_graph, 0, 0, CCV_NNC_AUTOGEN_ALL_EXECS | CCV_NNC_AUTOGEN_SOURCES_AND_DESTINATIONS);
    212
    1
      SYMBOLIC_GRAPH_GEN(symbolic_graph, CCV_NNC_LONG_DOT_GRAPH);
    213
    1
      ccv_nnc_graph_t* graph = 0;
    214
    1
      ccv_nnc_tensor_arena_t* tensor_arena = 0;
    215
    1
      ccv_nnc_graph_exec_arena_t* graph_exec_arena = 0;
    216
    1
      ccv_nnc_symbolic_graph_compile(symbolic_graph, ccv_nnc_default_compile_params, 0, 0, 0, 0, &case_of, 1, &case_of, 1, &graph, &tensor_arena, &graph_exec_arena);
    217
    1
      GRAPH_GEN(graph, CCV_NNC_LONG_DOT_GRAPH);
    218
    1
      ccv_nnc_tensor_t* x_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, x);
    219
    1
      x_tensor->data.f32[0] = -2.2;
    220
    1
      ccv_nnc_graph_run(graph, 0, TRAVERSE_FULL, 0, 0);
    221
    1
      ccv_nnc_tensor_t* y_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, y);
    222
    1
      REQUIRE_EQ_WITH_TOLERANCE(y_tensor->data.f32[0], expf(-2.2), 1e-5, "y should be expf(-2.2)");
    223
    1
      x_tensor->data.f32[0] = 1.1;
    224
    1
      ccv_nnc_graph_run(graph, 0, TRAVERSE_FULL, 0, 0);
    225
    1
      y_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, y);
    226
    1
      REQUIRE_EQ_WITH_TOLERANCE(y_tensor->data.f32[0], logf(1.1), 1e-5, "y should be logf(1.1)");
    227
    1
      x_tensor->data.f32[0] = 0.9;
    228
    1
      ccv_nnc_graph_run(graph, 0, TRAVERSE_FULL, 0, 0);
    229
    1
      y_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, y);
    230
    1
      REQUIRE_EQ_WITH_TOLERANCE(y_tensor->data.f32[0], 0.9, 1e-5, "y should be 0.9");
    231
    1
      x_tensor->data.f32[0] = 2.2;
    232
    1
      ccv_nnc_graph_run(graph, 0, TRAVERSE_FULL, 0, 0);
    233
    1
      y_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, y);
    234
    1
      REQUIRE_EQ_WITH_TOLERANCE(y_tensor->data.f32[0], 1. / 2.2, 1e-5, "y should be 1 / 2.2");
    235
    1
      x_tensor->data.f32[0] = 1001;
    236
    1
      ccv_nnc_graph_run(graph, 0, TRAVERSE_FULL, 0, 0);
    237
    1
      y_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, y);
    238
    1
      REQUIRE_EQ_WITH_TOLERANCE(y_tensor->data.f32[0], 1.1 * 1001, 1e-2, "y should be 1.1 * 1001");
    239
    1
      ccv_nnc_symbolic_graph_free(symbolic_graph);
    240
    1
      ccv_nnc_graph_exec_arena_free(graph_exec_arena);
    241
    1
      ccv_nnc_tensor_arena_free(tensor_arena);
    242
    1
      ccv_nnc_graph_free(graph);
    243
    244
    1
    }
    245
    246
    TEST_CASE("symbolic while graph contains a case..of graph and multiply its output with 0.3")
    247
    1
    {
    248
    1
      ccv_nnc_symbolic_graph_t* const symbolic_graph = ccv_nnc_symbolic_graph_new();
    249
    1
      ccv_nnc_tensor_symbol_t x = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 1), "x");
    250
    1
      ccv_nnc_symbolic_graph_t* const while_graph = ccv_nnc_symbolic_graph_new();
    251
    1
      ccv_nnc_graph_exec_symbol_t noop = ccv_nnc_graph_exec_symbol_new(while_graph, CMD_NOOP(), 0, 0, 0, 0, "noop");
    252
    1
      ccv_nnc_symbolic_graph_while(symbolic_graph, CCV_NNC_GRAPH_FORWARD, while_graph, "while 4");
    253
    1
      ccv_nnc_tensor_symbol_t y = ccv_nnc_tensor_symbol_new(while_graph, CPU_TENSOR_NHWC(32F, 1), "y");
    254
    1
      ccv_nnc_symbolic_graph_set_while_expr(while_graph, while_4, 0, TENSOR_SYMBOL_LIST(ccv_nnc_tensor_symbol_for_while_count(while_graph)), GRAPH_EXEC_SYMBOL_LIST(noop));
    255
    1
      ccv_nnc_graph_exec_symbol_t case_of = ccv_nnc_symbolic_graph_case_of_new(while_graph, CCV_NNC_GRAPH_FORWARD, TENSOR_SYMBOL_LIST(x), TENSOR_SYMBOL_MAP(KV(x, y)), "piece-wise linear vector");
    256
    1
      ccv_nnc_symbolic_graph_set_case_of_expr(while_graph, case_of, piecewise_case_of, 0);
    257
    1
      ccv_nnc_graph_exec_symbol_concat(while_graph, noop, case_of);
    258
    1
      ccv_nnc_symbolic_graph_set_sources(while_graph, GRAPH_EXEC_SYMBOL_LIST(noop));
    259
    1
      ccv_nnc_symbolic_graph_set_destinations(while_graph, GRAPH_EXEC_SYMBOL_LIST(case_of));
    260
    1
      ccv_nnc_symbolic_graph_t* const case_of_0 = ccv_nnc_symbolic_graph_new();
    261
    1
      ccv_nnc_tensor_symbol_t y0 = ccv_nnc_tensor_symbol_new(case_of_0, CPU_TENSOR_NHWC(32F, 1), "y0");
    262
    1
      ccv_nnc_symbolic_graph_set_case_of(while_graph, case_of, case_of_0, 0, TENSOR_SYMBOL_MAP(KV(y0, y)));
    263
    1
      ccv_nnc_graph_exec_symbol_new(case_of_0, CMD_SET_FORWARD(0), 0, 0, TENSOR_SYMBOL_LIST(y0), "set");
    264
    1
      ccv_nnc_graph_exec_symbol_autogen(case_of_0, 0, 0, CCV_NNC_AUTOGEN_ALL_EXECS | CCV_NNC_AUTOGEN_SOURCES_AND_DESTINATIONS);
    265
    1
      ccv_nnc_symbolic_graph_t* const case_of_1 = ccv_nnc_symbolic_graph_new();
    266
    1
      ccv_nnc_tensor_symbol_t y1 = ccv_nnc_tensor_symbol_new(case_of_1, CPU_TENSOR_NHWC(32F, 1), "y1");
    267
    1
      ccv_nnc_symbolic_graph_set_case_of(while_graph, case_of, case_of_1, 1, TENSOR_SYMBOL_MAP(KV(y1, y)));
    268
    1
      ccv_nnc_tensor_symbol_t s1 = ccv_nnc_tensor_symbol_new(case_of_1, CPU_TENSOR_NHWC(32F, 1), "s");
    269
    1
      ccv_nnc_tensor_symbol_t z1 = ccv_nnc_tensor_symbol_new(case_of_1, CPU_TENSOR_NHWC(32F, 1), "z1");
    270
    1
      ccv_nnc_tensor_symbol_t p1 = ccv_nnc_tensor_symbol_new(case_of_1, CPU_TENSOR_NHWC(32F, 1), "p");
    271
    1
      ccv_nnc_graph_exec_symbol_new(case_of_1, CMD_EWPROD_FORWARD(), TENSOR_SYMBOL_LIST(x, s1), TENSOR_SYMBOL_LIST(z1), "prod0");
    272
    1
      ccv_nnc_graph_exec_symbol_new(case_of_1, CMD_EWSUM_FORWARD(), TENSOR_SYMBOL_LIST(z1, p1), TENSOR_SYMBOL_LIST(y1), "sum");
    273
    1
      ccv_nnc_graph_exec_symbol_autogen(case_of_1, 0, 0, CCV_NNC_AUTOGEN_ALL_EXECS | CCV_NNC_AUTOGEN_SOURCES_AND_DESTINATIONS);
    274
    1
      ccv_nnc_symbolic_graph_t* const case_of_2 = ccv_nnc_symbolic_graph_new();
    275
    1
      ccv_nnc_tensor_symbol_t y2 = ccv_nnc_tensor_symbol_new(case_of_2, CPU_TENSOR_NHWC(32F, 1), "y2");
    276
    1
      ccv_nnc_symbolic_graph_set_case_of(while_graph, case_of, case_of_2, 2, TENSOR_SYMBOL_MAP(KV(y2, y)));
    277
    1
      ccv_nnc_graph_exec_symbol_new(case_of_2, CMD_SET_FORWARD(1.5), 0, 0, TENSOR_SYMBOL_LIST(y2), "set");
    278
    1
      ccv_nnc_graph_exec_symbol_autogen(case_of_2, 0, 0, CCV_NNC_AUTOGEN_ALL_EXECS | CCV_NNC_AUTOGEN_SOURCES_AND_DESTINATIONS);
    279
    1
      ccv_nnc_symbolic_graph_set_carry_overs(while_graph, TENSOR_SYMBOL_MAP(KV(y, x)));
    280
    1
      ccv_nnc_tensor_symbol_t z = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 1), "z");
    281
    1
      ccv_nnc_tensor_symbol_t a = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 1), "a");
    282
    1
      ccv_nnc_graph_exec_symbol_new(symbolic_graph, CMD_EWPROD_FORWARD(), TENSOR_SYMBOL_LIST(a, y), TENSOR_SYMBOL_LIST(z), "prod1");
    283
    1
      ccv_nnc_graph_exec_symbol_autogen(symbolic_graph, 0, 0, CCV_NNC_AUTOGEN_ALL_EXECS | CCV_NNC_AUTOGEN_SOURCES_AND_DESTINATIONS);
    284
    1
      SYMBOLIC_GRAPH_GEN(symbolic_graph, CCV_NNC_LONG_DOT_GRAPH);
    285
    1
      ccv_nnc_graph_t* graph = 0;
    286
    1
      ccv_nnc_tensor_arena_t* tensor_arena = 0;
    287
    1
      ccv_nnc_graph_exec_arena_t* graph_exec_arena = 0;
    288
    1
      ccv_nnc_symbolic_graph_compile(symbolic_graph, ccv_nnc_default_compile_params, 0, 0, 0, 0, ccv_nnc_symbolic_graph_sources(symbolic_graph), ccv_nnc_symbolic_graph_source_size(symbolic_graph), ccv_nnc_symbolic_graph_destinations(symbolic_graph), ccv_nnc_symbolic_graph_destination_size(symbolic_graph), &graph, &tensor_arena, &graph_exec_arena);
    289
    1
      GRAPH_GEN(graph, CCV_NNC_LONG_DOT_GRAPH);
    290
    1
      ccv_nnc_tensor_t* x_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, x);
    291
    1
      ccv_nnc_tensor_t* s1_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, s1);
    292
    1
      s1_tensor->data.f32[0] = 0.5;
    293
    1
      ccv_nnc_tensor_t* p1_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, p1);
    294
    1
      p1_tensor->data.f32[0] = 0.5;
    295
    1
      ccv_nnc_tensor_t* a_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, a);
    296
    1
      a_tensor->data.f32[0] = 0.3;
    297
    1
      x_tensor->data.f32[0] = 1.226;
    298
    1
      ccv_nnc_graph_run(graph, 0, TRAVERSE_FULL, 0, 0);
    299
    1
      ccv_nnc_tensor_t* z_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, z);
    300
    1
      REQUIRE_EQ_WITH_TOLERANCE((1 + 0.226 * 0.5 * 0.5 * 0.5 * 0.5) * 0.3, z_tensor->data.f32[0], 1e-6, "The piece-wise linear function applied 4 times");
    301
    1
      a_tensor->data.f32[0] = 0.3;
    302
    1
      x_tensor->data.f32[0] = 0.8;
    303
    1
      ccv_nnc_graph_run(graph, 0, TRAVERSE_FULL, 0, 0);
    304
    1
      z_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, z);
    305
    1
      REQUIRE_EQ_WITH_TOLERANCE(0.8 * 0.3, z_tensor->data.f32[0], 1e-6, "The piece-wise linear function applied 4 times");
    306
    1
      ccv_nnc_symbolic_graph_free(symbolic_graph);
    307
    1
      ccv_nnc_graph_exec_arena_free(graph_exec_arena);
    308
    1
      ccv_nnc_tensor_arena_free(tensor_arena);
    309
    1
      ccv_nnc_graph_free(graph);
    310
    1
    }
    311
    312
    TEST_CASE("symbolic while graph contains a case..of graph takes input by multiplying to 0.8 and multiply its output with 0.3")
    313
    1
    {
    314
    1
      ccv_nnc_symbolic_graph_t* const symbolic_graph = ccv_nnc_symbolic_graph_new();
    315
    1
      ccv_nnc_tensor_symbol_t b = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 1), "b");
    316
    1
      ccv_nnc_symbolic_graph_t* const while_graph = ccv_nnc_symbolic_graph_new();
    317
    1
      ccv_nnc_graph_exec_symbol_t noop = ccv_nnc_graph_exec_symbol_new(while_graph, CMD_NOOP(), 0, 0, 0, 0, "noop");
    318
    1
      ccv_nnc_symbolic_graph_while(symbolic_graph, CCV_NNC_GRAPH_FORWARD, while_graph, "while 4");
    319
    1
      ccv_nnc_tensor_symbol_t s0 = ccv_nnc_tensor_symbol_new(while_graph, CPU_TENSOR_NHWC(32F, 1), "s0");
    320
    1
      ccv_nnc_tensor_symbol_t x = ccv_nnc_tensor_symbol_new(while_graph, CPU_TENSOR_NHWC(32F, 1), "x");
    321
    1
      ccv_nnc_graph_exec_symbol_t prod = ccv_nnc_graph_exec_symbol_new(while_graph, CMD_EWPROD_FORWARD(), TENSOR_SYMBOL_LIST(b, s0), TENSOR_SYMBOL_LIST(x), "prod");
    322
    1
      ccv_nnc_tensor_symbol_t y = ccv_nnc_tensor_symbol_new(while_graph, CPU_TENSOR_NHWC(32F, 1), "y");
    323
    1
      ccv_nnc_symbolic_graph_set_while_expr(while_graph, while_4, 0, TENSOR_SYMBOL_LIST(ccv_nnc_tensor_symbol_for_while_count(while_graph)), GRAPH_EXEC_SYMBOL_LIST(noop));
    324
    1
      ccv_nnc_graph_exec_symbol_t case_of = ccv_nnc_symbolic_graph_case_of_new(while_graph, CCV_NNC_GRAPH_FORWARD, TENSOR_SYMBOL_LIST(x), TENSOR_SYMBOL_MAP(KV(x, y)), "piece-wise linear vector");
    325
    1
      ccv_nnc_symbolic_graph_set_case_of_expr(while_graph, case_of, piecewise_case_of, 0);
    326
    1
      ccv_nnc_graph_exec_symbol_concat(while_graph, noop, prod);
    327
    1
      ccv_nnc_symbolic_graph_set_sources(while_graph, GRAPH_EXEC_SYMBOL_LIST(noop));
    328
    1
      ccv_nnc_symbolic_graph_set_destinations(while_graph, GRAPH_EXEC_SYMBOL_LIST(case_of));
    329
    1
      ccv_nnc_symbolic_graph_t* const case_of_0 = ccv_nnc_symbolic_graph_new();
    330
    1
      ccv_nnc_tensor_symbol_t y0 = ccv_nnc_tensor_symbol_new(case_of_0, CPU_TENSOR_NHWC(32F, 1), "y0");
    331
    1
      ccv_nnc_symbolic_graph_set_case_of(while_graph, case_of, case_of_0, 0, TENSOR_SYMBOL_MAP(KV(y0, y)));
    332
    1
      ccv_nnc_graph_exec_symbol_new(case_of_0, CMD_SET_FORWARD(0), 0, 0, TENSOR_SYMBOL_LIST(y0), "set");
    333
    1
      ccv_nnc_graph_exec_symbol_autogen(case_of_0, 0, 0, CCV_NNC_AUTOGEN_ALL_EXECS | CCV_NNC_AUTOGEN_SOURCES_AND_DESTINATIONS);
    334
    1
      ccv_nnc_symbolic_graph_t* const case_of_1 = ccv_nnc_symbolic_graph_new();
    335
    1
      ccv_nnc_tensor_symbol_t y1 = ccv_nnc_tensor_symbol_new(case_of_1, CPU_TENSOR_NHWC(32F, 1), "y1");
    336
    1
      ccv_nnc_symbolic_graph_set_case_of(while_graph, case_of, case_of_1, 1, TENSOR_SYMBOL_MAP(KV(y1, y)));
    337
    1
      ccv_nnc_tensor_symbol_t s1 = ccv_nnc_tensor_symbol_new(case_of_1, CPU_TENSOR_NHWC(32F, 1), "s");
    338
    1
      ccv_nnc_tensor_symbol_t z1 = ccv_nnc_tensor_symbol_new(case_of_1, CPU_TENSOR_NHWC(32F, 1), "z1");
    339
    1
      ccv_nnc_tensor_symbol_t p1 = ccv_nnc_tensor_symbol_new(case_of_1, CPU_TENSOR_NHWC(32F, 1), "p");
    340
    1
      ccv_nnc_graph_exec_symbol_new(case_of_1, CMD_EWPROD_FORWARD(), TENSOR_SYMBOL_LIST(x, s1), TENSOR_SYMBOL_LIST(z1), "prod0");
    341
    1
      ccv_nnc_graph_exec_symbol_new(case_of_1, CMD_EWSUM_FORWARD(), TENSOR_SYMBOL_LIST(z1, p1), TENSOR_SYMBOL_LIST(y1), "sum");
    342
    1
      ccv_nnc_graph_exec_symbol_autogen(case_of_1, 0, 0, CCV_NNC_AUTOGEN_ALL_EXECS | CCV_NNC_AUTOGEN_SOURCES_AND_DESTINATIONS);
    343
    1
      ccv_nnc_symbolic_graph_t* const case_of_2 = ccv_nnc_symbolic_graph_new();
    344
    1
      ccv_nnc_tensor_symbol_t y2 = ccv_nnc_tensor_symbol_new(case_of_2, CPU_TENSOR_NHWC(32F, 1), "y2");
    345
    1
      ccv_nnc_symbolic_graph_set_case_of(while_graph, case_of, case_of_2, 2, TENSOR_SYMBOL_MAP(KV(y2, y)));
    346
    1
      ccv_nnc_graph_exec_symbol_new(case_of_2, CMD_SET_FORWARD(1.5), 0, 0, TENSOR_SYMBOL_LIST(y2), "set");
    347
    1
      ccv_nnc_graph_exec_symbol_autogen(case_of_2, 0, 0, CCV_NNC_AUTOGEN_ALL_EXECS | CCV_NNC_AUTOGEN_SOURCES_AND_DESTINATIONS);
    348
    1
      ccv_nnc_symbolic_graph_set_carry_overs(while_graph, TENSOR_SYMBOL_MAP(KV(y, b)));
    349
    1
      ccv_nnc_tensor_symbol_t z = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 1), "z");
    350
    1
      ccv_nnc_tensor_symbol_t a = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 1), "a");
    351
    1
      ccv_nnc_graph_exec_symbol_new(symbolic_graph, CMD_EWPROD_FORWARD(), TENSOR_SYMBOL_LIST(a, y), TENSOR_SYMBOL_LIST(z), "prod1");
    352
    1
      ccv_nnc_graph_exec_symbol_autogen(symbolic_graph, 0, 0, CCV_NNC_AUTOGEN_ALL_EXECS | CCV_NNC_AUTOGEN_SOURCES_AND_DESTINATIONS);
    353
    1
      SYMBOLIC_GRAPH_GEN(symbolic_graph, CCV_NNC_LONG_DOT_GRAPH);
    354
    1
      ccv_nnc_graph_t* graph = 0;
    355
    1
      ccv_nnc_tensor_arena_t* tensor_arena = 0;
    356
    1
      ccv_nnc_graph_exec_arena_t* graph_exec_arena = 0;
    357
    1
      ccv_nnc_symbolic_graph_compile(symbolic_graph, ccv_nnc_default_compile_params, 0, 0, 0, 0, ccv_nnc_symbolic_graph_sources(symbolic_graph), ccv_nnc_symbolic_graph_source_size(symbolic_graph), ccv_nnc_symbolic_graph_destinations(symbolic_graph), ccv_nnc_symbolic_graph_destination_size(symbolic_graph), &graph, &tensor_arena, &graph_exec_arena);
    358
    1
      GRAPH_GEN(graph, CCV_NNC_LONG_DOT_GRAPH);
    359
    1
      ccv_nnc_tensor_t* b_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, b);
    360
    1
      ccv_nnc_tensor_t* s0_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, s0);
    361
    1
      s0_tensor->data.f32[0] = 0.8;
    362
    1
      ccv_nnc_tensor_t* s1_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, s1);
    363
    1
      s1_tensor->data.f32[0] = 0.5;
    364
    1
      ccv_nnc_tensor_t* p1_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, p1);
    365
    1
      p1_tensor->data.f32[0] = 0.5;
    366
    1
      ccv_nnc_tensor_t* a_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, a);
    367
    1
      a_tensor->data.f32[0] = 0.3;
    368
    1
      b_tensor->data.f32[0] = 2.5;
    369
    1
      ccv_nnc_graph_run(graph, 0, TRAVERSE_FULL, 0, 0);
    370
    1
      ccv_nnc_tensor_t* z_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, z);
    371
    1
      REQUIRE_EQ_WITH_TOLERANCE(1.1 * 0.8 * 0.8 * 0.3, z_tensor->data.f32[0], 1e-6, "The piece-wise linear function applied 4 times");
    372
    1
      ccv_nnc_symbolic_graph_free(symbolic_graph);
    373
    1
      ccv_nnc_graph_exec_arena_free(graph_exec_arena);
    374
    1
      ccv_nnc_tensor_arena_free(tensor_arena);
    375
    1
      ccv_nnc_graph_free(graph);
    376
    1
    }
    377
    378
    #include "case_main.h"