## 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/while.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 while_5(ccv_nnc_tensor_t* const* const inputs, const int input_size, const void* const data)
    15
    96
    {
    16
    96
      int i;
    17
    234
      for (i = 0; i < input_size; i++138)
    18
    138
        { assert(!CCV_IS_TENSOR_MULTIVIEW(inputs[i])); }
    19
    96
      return inputs[0]->data.i64[0] < 5;
    20
    96
    }
    21
    22
    TEST_CASE("graph for a while loop to compute 0.34 * 1.11 ^ 5")
    23
    1
    {
    24
    1
      ccv_nnc_graph_t* graph = ccv_nnc_graph_new();
    25
    1
      ccv_nnc_tensor_t* x = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 1), 0);
    26
    1
      ccv_nnc_tensor_t* y = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 1), 0);
    27
    1
      ccv_nnc_tensor_t* z = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 1), 0);
    28
    1
      ccv_nnc_graph_t* while_graph = ccv_nnc_graph_new();
    29
    1
      ccv_nnc_graph_exec_t noop = ccv_nnc_graph_exec_new(while_graph, CMD_NOOP(), ccv_nnc_no_hint, 0, 0, 0, 0);
    30
    1
      ccv_nnc_graph_exec_t prod0 = ccv_nnc_graph_exec_new(while_graph, CMD_EWPROD_FORWARD(), ccv_nnc_no_hint, TENSOR_LIST(y, z), TENSOR_LIST(z));
    31
    1
      ccv_nnc_graph_exec_concat(while_graph, noop, prod0);
    32
    1
      ccv_nnc_graph_exec_t loop = ccv_nnc_graph_while(graph, CCV_NNC_GRAPH_FORWARD, while_graph);
    33
    1
      ccv_nnc_graph_set_sources(while_graph, GRAPH_EXEC_LIST(noop));
    34
    1
      ccv_nnc_graph_set_destinations(while_graph, GRAPH_EXEC_LIST(prod0));
    35
    1
      ccv_nnc_tensor_t count_tensor = ccv_nnc_tensor_for_while_count(while_graph);
    36
    1
      ccv_nnc_graph_set_while_expr(while_graph, while_5, 0, TENSOR_LIST(&count_tensor), GRAPH_EXEC_LIST(noop));
    37
    1
      ccv_nnc_graph_exec_t prod1 = ccv_nnc_graph_exec_new(graph, CMD_EWPROD_FORWARD(), ccv_nnc_no_hint, TENSOR_LIST(x, z), TENSOR_LIST(z));
    38
    1
      ccv_nnc_graph_exec_concat(graph, loop, prod1);
    39
    1
      GRAPH_GEN(graph, CCV_NNC_LONG_DOT_GRAPH);
    40
    1
      x->data.f32[0] = 0.34;
    41
    1
      y->data.f32[0] = 1.11;
    42
    1
      z->data.f32[0] = 1;
    43
    1
      ccv_nnc_graph_autotune(graph, 0, 0, TRAVERSE_FULL);
    44
    1
      ccv_nnc_graph_run(graph, 0, GRAPH_EXEC_LIST(loop), GRAPH_EXEC_LIST(prod1), 0, 0);
    45
    1
      ccv_nnc_graph_free(graph);
    46
    1
      REQUIRE_EQ_WITH_TOLERANCE(z->data.f32[0], 0.34 * 1.11 * 1.11 * 1.11 * 1.11 * 1.11, 1e-6, "computed result of 0.34 * 1.11 ^ 5 should be the same");
    47
    1
      ccv_nnc_tensor_free(x);
    48
    1
      ccv_nnc_tensor_free(y);
    49
    1
      ccv_nnc_tensor_free(z);
    50
    1
    }
    51
    52
    TEST_CASE("graph for a while loop by reuse tensor allocations for 0.32 * 2.8 ^ 5")
    53
    1
    {
    54
    1
      ccv_nnc_graph_t* graph = ccv_nnc_graph_new();
    55
    1
      ccv_nnc_graph_t* while_graph = ccv_nnc_graph_new();
    56
    1
      ccv_nnc_graph_exec_t loop = ccv_nnc_graph_while(graph, CCV_NNC_GRAPH_FORWARD, while_graph);
    57
    1
      ccv_nnc_graph_exec_t noop = ccv_nnc_graph_exec_new(while_graph, CMD_NOOP(), ccv_nnc_no_hint, 0, 0, 0, 0);
    58
    1
      ccv_nnc_tensor_t* x = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 1), 0);
    59
    1
      ccv_nnc_tensor_t* y = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 1), 0);
    60
    1
      ccv_nnc_tensor_t* z = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 1), 0);
    61
    1
      ccv_nnc_tensor_multiview_t xx;
    62
    1
      ccv_nnc_tensor_multiview((ccv_nnc_tensor_t*[]){
    63
    1
          x, z
    64
    1
      }, CCV_NNC_MULTIVIEW_K0N, 2, while_graph, &xx);
    65
    1
      ccv_nnc_tensor_multiview_t zz;
    66
    1
      ccv_nnc_tensor_multiview((ccv_nnc_tensor_t*[]){
    67
    1
          z, x
    68
    1
      }, CCV_NNC_MULTIVIEW_K0N, 2, while_graph, &zz);
    69
    1
      ccv_nnc_tensor_t zbb = ccv_nnc_tensor(0, CPU_TENSOR_NHWC(32F, 1), 0);
    70
    1
      ccv_nnc_tensor_synchronize_to_multiview(&zz, &zbb);
    71
    1
      ccv_nnc_graph_exec_t prod = ccv_nnc_graph_exec_new(while_graph, CMD_EWPROD_FORWARD(), ccv_nnc_no_hint, TENSOR_LIST((ccv_nnc_tensor_t*)&xx, y), TENSOR_LIST((ccv_nnc_tensor_t*)&zz));
    72
    1
      ccv_nnc_graph_set_sources(while_graph, GRAPH_EXEC_LIST(noop));
    73
    1
      ccv_nnc_graph_set_destinations(while_graph, GRAPH_EXEC_LIST(prod));
    74
    1
      ccv_nnc_tensor_t count_tensor = ccv_nnc_tensor_for_while_count(while_graph);
    75
    1
      ccv_nnc_graph_set_while_expr(while_graph, while_5, 0, TENSOR_LIST(&count_tensor), GRAPH_EXEC_LIST(noop));
    76
    1
      ccv_nnc_graph_exec_concat(while_graph, noop, prod);
    77
    1
      GRAPH_GEN(graph, CCV_NNC_LONG_DOT_GRAPH);
    78
    1
      x->data.f32[0] = 0.32;
    79
    1
      y->data.f32[0] = 2.8;
    80
    1
      ccv_nnc_graph_autotune(graph, 0, 0, TRAVERSE_FULL);
    81
    1
      ccv_nnc_graph_run(graph, 0, GRAPH_EXEC_LIST(loop), GRAPH_EXEC_LIST(loop), 0, 0);
    82
    1
      REQUIRE_EQ_WITH_TOLERANCE(z->data.f32[0], 0.32 * 2.8 * 2.8 * 2.8 * 2.8 * 2.8, 1e-5, "computed result of 0.32 * 2.8 ^ 5 should be the same");
    83
    1
      REQUIRE(z->data.f32 == zbb.data.f32, "Two pointers should be the same");
    84
    1
      ccv_nnc_tensor_multiview_free(xx);
    85
    1
      ccv_nnc_tensor_multiview_free(zz);
    86
    1
      ccv_nnc_graph_free(graph);
    87
    1
      ccv_nnc_tensor_free(x);
    88
    1
      ccv_nnc_tensor_free(y);
    89
    1
      ccv_nnc_tensor_free(z);
    90
    1
    }
    91
    92
    TEST_CASE("while graph add and re-add reuse tensor allocations for 0.47 * 5.5 ^ 5")
    93
    1
    {
    94
    1
      ccv_nnc_graph_t* graph = ccv_nnc_graph_new();
    95
    1
      ccv_nnc_graph_t* while_graph = ccv_nnc_graph_new();
    96
    1
      ccv_nnc_graph_exec_t loop = ccv_nnc_graph_while(graph, CCV_NNC_GRAPH_FORWARD, while_graph);
    97
    1
      ccv_nnc_graph_exec_t noop = ccv_nnc_graph_exec_new(while_graph, CMD_NOOP(), ccv_nnc_no_hint, 0, 0, 0, 0);
    98
    1
      ccv_nnc_tensor_t* x = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 1), 0);
    99
    1
      ccv_nnc_tensor_t* y = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 1), 0);
    100
    1
      ccv_nnc_tensor_t* z = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 1), 0);
    101
    1
      ccv_nnc_tensor_multiview_t xx;
    102
    1
      ccv_nnc_tensor_multiview((ccv_nnc_tensor_t*[]){
    103
    1
          x, z
    104
    1
      }, CCV_NNC_MULTIVIEW_K0N, 2, while_graph, &xx);
    105
    1
      ccv_nnc_tensor_multiview_t zz;
    106
    1
      ccv_nnc_tensor_multiview((ccv_nnc_tensor_t*[]){
    107
    1
          z, x
    108
    1
      }, CCV_NNC_MULTIVIEW_K0N, 2, while_graph, &zz);
    109
    1
      ccv_nnc_graph_exec_t prod = ccv_nnc_graph_exec_new(while_graph, CMD_EWPROD_FORWARD(), ccv_nnc_no_hint, TENSOR_LIST((ccv_nnc_tensor_t*)&xx, y), TENSOR_LIST((ccv_nnc_tensor_t*)&zz));
    110
    1
      ccv_nnc_graph_set_sources(while_graph, GRAPH_EXEC_LIST(noop));
    111
    1
      ccv_nnc_graph_set_destinations(while_graph, GRAPH_EXEC_LIST(prod));
    112
    1
      ccv_nnc_tensor_t count_tensor = ccv_nnc_tensor_for_while_count(while_graph);
    113
    1
      ccv_nnc_graph_set_while_expr(while_graph, while_5, 0, TENSOR_LIST(&count_tensor), GRAPH_EXEC_LIST(noop));
    114
    1
      ccv_nnc_graph_exec_concat(while_graph, noop, prod);
    115
    1
      ccv_nnc_graph_exec_set_io(while_graph, prod, TENSOR_LIST(x, y), TENSOR_LIST(z));
    116
    1
      ccv_nnc_graph_exec_set_io(while_graph, prod, TENSOR_LIST((ccv_nnc_tensor_t*)&zz, y), TENSOR_LIST((ccv_nnc_tensor_t*)&xx));
    117
    1
      GRAPH_GEN(graph, CCV_NNC_LONG_DOT_GRAPH);
    118
    1
      x->data.f32[0] = 0.32;
    119
    1
      z->data.f32[0] = 0.47;
    120
    1
      y->data.f32[0] = 5.5;
    121
    1
      ccv_nnc_graph_autotune(graph, 0, 0, TRAVERSE_FULL);
    122
    1
      ccv_nnc_graph_run(graph, 0, GRAPH_EXEC_LIST(loop), GRAPH_EXEC_LIST(loop), 0, 0);
    123
    1
      REQUIRE_EQ_WITH_TOLERANCE(x->data.f32[0], 0.47 * 5.5 * 5.5 * 5.5 * 5.5 * 5.5, 1e-2, "computed result of 0.47 * 5.5 ^ 5 should be the same");
    124
    1
      ccv_nnc_graph_free(graph);
    125
    1
      ccv_nnc_tensor_free(x);
    126
    1
      ccv_nnc_tensor_free(y);
    127
    1
      ccv_nnc_tensor_free(z);
    128
    1
    }
    129
    130
    TEST_CASE("symbolic graph get while graph from symbol")
    131
    1
    {
    132
    1
      ccv_nnc_symbolic_graph_t* const symbolic_graph = ccv_nnc_symbolic_graph_new();
    133
    1
      ccv_nnc_symbolic_graph_t* const while_graph_0 = ccv_nnc_symbolic_graph_new();
    134
    1
      ccv_nnc_graph_exec_symbol_t while_0 = ccv_nnc_symbolic_graph_while(symbolic_graph, CCV_NNC_GRAPH_FORWARD, while_graph_0, "while 0");
    135
    1
      ccv_nnc_symbolic_graph_t* const while_graph_1 = ccv_nnc_symbolic_graph_new();
    136
    1
      ccv_nnc_graph_exec_symbol_t while_1 = ccv_nnc_symbolic_graph_while(symbolic_graph, CCV_NNC_GRAPH_FORWARD, while_graph_1, "while 1");
    137
    1
      REQUIRE(while_graph_0 == ccv_nnc_symbolic_graph_from_while_symbol(symbolic_graph, while_0), "graph extracted from symbol should be equal");
    138
    1
      REQUIRE(while_graph_1 == ccv_nnc_symbolic_graph_from_while_symbol(symbolic_graph, while_1), "graph extracted from symbol should be equal");
    139
    1
      ccv_nnc_symbolic_graph_free(symbolic_graph);
    140
    1
    }
    141
    142
    TEST_CASE("symbolic graph for a while loop to compute x ^ 5 * y")
    143
    1
    {
    144
    1
      ccv_nnc_symbolic_graph_t* symbolic_graph = ccv_nnc_symbolic_graph_new();
    145
    1
      ccv_nnc_tensor_symbol_t x = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 1), "x");
    146
    1
      ccv_nnc_tensor_symbol_t y = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 1), "y");
    147
    1
      ccv_nnc_symbolic_graph_t* while_graph = ccv_nnc_symbolic_graph_new();
    148
    1
      ccv_nnc_symbolic_graph_while(symbolic_graph, CCV_NNC_GRAPH_FORWARD, while_graph, "for 1..5");
    149
    1
      ccv_nnc_tensor_symbol_t z0 = ccv_nnc_tensor_symbol_new(while_graph, CPU_TENSOR_NHWC(32F, 1), "z0");
    150
    1
      ccv_nnc_tensor_symbol_t z1 = ccv_nnc_tensor_symbol_new(while_graph, CPU_TENSOR_NHWC(32F, 1), "z1");
    151
    1
      ccv_nnc_graph_exec_symbol_t noop = ccv_nnc_graph_exec_symbol_new(while_graph, CMD_NOOP(), 0, 0, 0, 0, "noop");
    152
    1
      ccv_nnc_graph_exec_symbol_t prod0 = ccv_nnc_graph_exec_symbol_new(while_graph, CMD_EWPROD_FORWARD(), TENSOR_SYMBOL_LIST(z0, x), TENSOR_SYMBOL_LIST(z1), "prod0");
    153
    1
      ccv_nnc_graph_exec_symbol_concat(while_graph, noop, prod0);
    154
    1
      ccv_nnc_tensor_symbol_t z2 = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 1), "z2");
    155
    1
      ccv_nnc_graph_exec_symbol_new(symbolic_graph, CMD_EWPROD_FORWARD(), TENSOR_SYMBOL_LIST(z1, y), TENSOR_SYMBOL_LIST(z2), "prod1");
    156
    1
      ccv_nnc_graph_exec_symbol_autogen(symbolic_graph, 0, 0, CCV_NNC_AUTOGEN_ALL_EXECS | CCV_NNC_AUTOGEN_SOURCES_AND_DESTINATIONS);
    157
      // Test whether we can ignore the noop graph properly in compilation.
    158
    1
      ccv_nnc_symbolic_graph_t* noop_graph = ccv_nnc_symbolic_graph_new();
    159
    1
      ccv_nnc_symbolic_graph_while(symbolic_graph, CCV_NNC_GRAPH_FORWARD, noop_graph, "no op");
    160
    1
      ccv_nnc_symbolic_graph_set_while_expr(while_graph, while_5, 0, TENSOR_SYMBOL_LIST(ccv_nnc_tensor_symbol_for_while_count(while_graph)), GRAPH_EXEC_SYMBOL_LIST(noop));
    161
    1
      ccv_nnc_symbolic_graph_set_carry_overs(while_graph, TENSOR_SYMBOL_MAP(KV(z1, z0)));
    162
    1
      ccv_nnc_symbolic_graph_set_sources(while_graph, GRAPH_EXEC_SYMBOL_LIST(noop));
    163
    1
      ccv_nnc_symbolic_graph_set_destinations(while_graph, GRAPH_EXEC_SYMBOL_LIST(prod0));
    164
    1
      ccv_nnc_graph_t* graph = 0;
    165
    1
      ccv_nnc_tensor_arena_t* tensor_arena = 0;
    166
    1
      ccv_nnc_graph_exec_arena_t* graph_exec_arena = 0;
    167
    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);
    168
    1
      SYMBOLIC_GRAPH_GEN(symbolic_graph, CCV_NNC_LONG_DOT_GRAPH);
    169
    1
      GRAPH_GEN(graph, CCV_NNC_LONG_DOT_GRAPH);
    170
    1
      ccv_nnc_tensor_t* x_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, x);
    171
    1
      ccv_nnc_tensor_t* y_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, y);
    172
    1
      ccv_nnc_tensor_t* z0_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, z0);
    173
    1
      ccv_nnc_tensor_t* z_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, z2);
    174
    1
      x_tensor->data.f32[0] = 0.92;
    175
    1
      y_tensor->data.f32[0] = 3.2;
    176
    1
      z0_tensor->data.f32[0] = 1;
    177
    1
      ccv_nnc_graph_autotune(graph, 0, 0, TRAVERSE_FULL);
    178
    1
      ccv_nnc_graph_run(graph, 0, TRAVERSE_FULL, 0, 0);
    179
    1
      REQUIRE_EQ_WITH_TOLERANCE(z_tensor->data.f32[0], 0.92 * 0.92 * 0.92 * 0.92 * 0.92 * 3.2, 1e-6, "z should be equal to x ^ 5 * y");
    180
    1
      ccv_nnc_symbolic_graph_free(symbolic_graph);
    181
    1
      ccv_nnc_graph_exec_arena_free(graph_exec_arena);
    182
    1
      ccv_nnc_tensor_arena_free(tensor_arena);
    183
    1
      ccv_nnc_graph_free(graph);
    184
    1
    }
    185
    186
    TEST_CASE("symbolic graph for a while loop to compute z * x ^ 5 * y + z")
    187
    1
    {
    188
    1
      ccv_nnc_symbolic_graph_t* symbolic_graph = ccv_nnc_symbolic_graph_new();
    189
    1
      ccv_nnc_tensor_symbol_t x = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 1), "x");
    190
    1
      ccv_nnc_tensor_symbol_t y = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 1), "y");
    191
    1
      ccv_nnc_tensor_symbol_t z0 = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 1), "z0");
    192
    1
      ccv_nnc_symbolic_graph_t* while_graph = ccv_nnc_symbolic_graph_new();
    193
    1
      ccv_nnc_symbolic_graph_while(symbolic_graph, CCV_NNC_GRAPH_FORWARD, while_graph, "for 1..5");
    194
    1
      ccv_nnc_tensor_symbol_t z1 = ccv_nnc_tensor_symbol_new(while_graph, CPU_TENSOR_NHWC(32F, 1), "z1");
    195
    1
      ccv_nnc_graph_exec_symbol_t noop = ccv_nnc_graph_exec_symbol_new(while_graph, CMD_NOOP(), 0, 0, 0, 0, "noop");
    196
    1
      ccv_nnc_graph_exec_symbol_t prod0 = ccv_nnc_graph_exec_symbol_new(while_graph, CMD_EWPROD_FORWARD(), TENSOR_SYMBOL_LIST(z0, x), TENSOR_SYMBOL_LIST(z1), "prod0");
    197
    1
      ccv_nnc_graph_exec_symbol_concat(while_graph, noop, prod0);
    198
    1
      ccv_nnc_tensor_symbol_t z2 = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 1), "z2");
    199
    1
      ccv_nnc_tensor_symbol_t z3 = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 1), "z3");
    200
    1
      ccv_nnc_graph_exec_symbol_new(symbolic_graph, CMD_EWPROD_FORWARD(), TENSOR_SYMBOL_LIST(z1, y), TENSOR_SYMBOL_LIST(z2), "prod1");
    201
    1
      ccv_nnc_graph_exec_symbol_new(symbolic_graph, CMD_EWSUM_FORWARD(), TENSOR_SYMBOL_LIST(z2, z0), TENSOR_SYMBOL_LIST(z3), "sum");
    202
    1
      ccv_nnc_graph_exec_symbol_autogen(symbolic_graph, 0, 0, CCV_NNC_AUTOGEN_ALL_EXECS | CCV_NNC_AUTOGEN_SOURCES_AND_DESTINATIONS);
    203
    1
      ccv_nnc_symbolic_graph_set_while_expr(while_graph, while_5, 0, TENSOR_SYMBOL_LIST(ccv_nnc_tensor_symbol_for_while_count(while_graph), z0), GRAPH_EXEC_SYMBOL_LIST(noop));
    204
    1
      ccv_nnc_symbolic_graph_set_carry_overs(while_graph, TENSOR_SYMBOL_MAP(KV(z1, z0)));
    205
    1
      ccv_nnc_symbolic_graph_set_sources(while_graph, GRAPH_EXEC_SYMBOL_LIST(noop));
    206
    1
      ccv_nnc_symbolic_graph_set_destinations(while_graph, GRAPH_EXEC_SYMBOL_LIST(prod0));
    207
    1
      ccv_nnc_graph_t* graph = 0;
    208
    1
      ccv_nnc_tensor_arena_t* tensor_arena = 0;
    209
    1
      ccv_nnc_graph_exec_arena_t* graph_exec_arena = 0;
    210
    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);
    211
    1
      SYMBOLIC_GRAPH_GEN(symbolic_graph, CCV_NNC_LONG_DOT_GRAPH);
    212
    1
      GRAPH_GEN(graph, CCV_NNC_LONG_DOT_GRAPH);
    213
    1
      ccv_nnc_tensor_t* x_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, x);
    214
    1
      ccv_nnc_tensor_t* y_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, y);
    215
    1
      ccv_nnc_tensor_t* z0_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, z0);
    216
    1
      x_tensor->data.f32[0] = 0.92;
    217
    1
      y_tensor->data.f32[0] = 3.2;
    218
    1
      z0_tensor->data.f32[0] = 1.2;
    219
    1
      ccv_nnc_graph_autotune(graph, 0, 0, TRAVERSE_FULL);
    220
    1
      ccv_nnc_graph_run(graph, 0, TRAVERSE_FULL, 0, 0);
    221
    1
      ccv_nnc_tensor_t* z_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, z3);
    222
    1
      REQUIRE_EQ_WITH_TOLERANCE(z_tensor->data.f32[0], 1.2 * 0.92 * 0.92 * 0.92 * 0.92 * 0.92 * 3.2 + 1.2, 1e-6, "z should be equal to z * x ^ 5 * y + z");
    223
    1
      ccv_nnc_symbolic_graph_free(symbolic_graph);
    224
    1
      ccv_nnc_graph_exec_arena_free(graph_exec_arena);
    225
    1
      ccv_nnc_tensor_arena_free(tensor_arena);
    226
    1
      ccv_nnc_graph_free(graph);
    227
    1
    }
    228
    229
    TEST_CASE("symbolic graph for a while loop to compute x = max(conv(x, w, b), 3x3) 5 times")
    230
    1
    {
    231
    1
      ccv_nnc_symbolic_graph_t* symbolic_graph = ccv_nnc_symbolic_graph_new();
    232
    1
      ccv_nnc_symbolic_graph_t* while_graph = ccv_nnc_symbolic_graph_new();
    233
    1
      ccv_nnc_symbolic_graph_while(symbolic_graph, CCV_NNC_GRAPH_FORWARD, while_graph, "while 1..5");
    234
    1
      ccv_nnc_tensor_symbol_t x = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 5, 5, 4), "x");
    235
    1
      ccv_nnc_tensor_symbol_t w = ccv_nnc_tensor_symbol_new(while_graph, CPU_TENSOR_NHWC(32F, 4, 3, 3, 4), "w");
    236
    1
      ccv_nnc_tensor_symbol_t b = ccv_nnc_tensor_symbol_new(while_graph, CPU_TENSOR_NHWC(32F, 4), "b");
    237
    1
      ccv_nnc_tensor_symbol_t y = ccv_nnc_tensor_symbol_new(while_graph, CPU_TENSOR_NHWC(32F, 5, 5, 4), "y");
    238
    1
      ccv_nnc_tensor_symbol_t z = ccv_nnc_tensor_symbol_new(while_graph, CPU_TENSOR_NHWC(32F, 5, 5, 4), "z");
    239
    1
      ccv_nnc_graph_exec_symbol_t noop = ccv_nnc_graph_exec_symbol_new(while_graph, CMD_NOOP(), 0, 0, 0, 0, "noop");
    240
    1
      ccv_nnc_graph_exec_symbol_t conv = ccv_nnc_graph_exec_symbol_new(while_graph, CMD_CONVOLUTION_FORWARD(1, 4, 3, 3, 4), TENSOR_SYMBOL_LIST(x, w, b), TENSOR_SYMBOL_LIST(y), "conv");
    241
    1
      ccv_nnc_graph_exec_symbol_t avg = ccv_nnc_graph_exec_symbol_new(while_graph, CMD_AVERAGE_POOL_FORWARD(3, 3), TENSOR_SYMBOL_LIST(y), TENSOR_SYMBOL_LIST(z), "avg");
    242
    1
      ccv_nnc_graph_exec_symbol_concat(while_graph, noop, conv);
    243
    1
      ccv_nnc_symbolic_graph_set_while_expr(while_graph, while_5, 0, TENSOR_SYMBOL_LIST(ccv_nnc_tensor_symbol_for_while_count(while_graph), w), GRAPH_EXEC_SYMBOL_LIST(noop));
    244
    1
      ccv_nnc_symbolic_graph_set_carry_overs(while_graph, TENSOR_SYMBOL_MAP(KV(z, x)));
    245
    1
      ccv_nnc_symbolic_graph_set_sources(while_graph, GRAPH_EXEC_SYMBOL_LIST(noop));
    246
    1
      ccv_nnc_symbolic_graph_set_destinations(while_graph, GRAPH_EXEC_SYMBOL_LIST(avg));
    247
    1
      ccv_nnc_graph_t* graph = 0;
    248
    1
      ccv_nnc_tensor_arena_t* tensor_arena = 0;
    249
    1
      ccv_nnc_graph_exec_arena_t* graph_exec_arena = 0;
    250
    1
      ccv_nnc_graph_exec_symbol_autogen(symbolic_graph, 0, 0, CCV_NNC_AUTOGEN_ALL_EXECS | CCV_NNC_AUTOGEN_SOURCES_AND_DESTINATIONS);
    251
    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);
    252
    1
      SYMBOLIC_GRAPH_GEN(symbolic_graph, CCV_NNC_LONG_DOT_GRAPH);
    253
    1
      GRAPH_GEN(graph, CCV_NNC_LONG_DOT_GRAPH);
    254
    1
      ccv_nnc_tensor_t* x_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, x);
    255
    1
      ccv_nnc_tensor_t* w_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, w);
    256
    1
      ccv_nnc_tensor_t* b_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, b);
    257
    1
      int i;
    258
    1
      dsfmt_t dsfmt;
    259
    1
      dsfmt_init_gen_rand(&dsfmt, 0);
    260
    101
      for (i = 0; i < 5 * 5 * 4; i++100)
    261
    100
        x_tensor->data.f32[i] = dsfmt_genrand_open_close(&dsfmt);
    262
    145
      for (i = 0; i < 4 * 3 * 3 * 4; i++144)
    263
    144
        w_tensor->data.f32[i] = dsfmt_genrand_open_close(&dsfmt) / (4 * 3 * 3);
    264
    5
      for (i = 0; i < 4; i++4)
    265
    4
        b_tensor->data.f32[i] = 3.2;
    266
    1
      ccv_nnc_tensor_t* x1 = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 5, 5, 4), 0);
    267
    1
      memcpy(x1->data.f32, x_tensor->data.f32, sizeof(float) * 5 * 5 * 4);
    268
    1
      ccv_nnc_tensor_t* y1 = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 5, 5, 4), 0);
    269
    6
      for (i = 0; i < 5; i++5)
    270
    5
      {
    271
    5
        ccv_nnc_cmd_exec(CMD_CONVOLUTION_FORWARD(1, 4, 3, 3, 4), HINT((1, 1), (1, 1)), 0, TENSOR_LIST(x1, w_tensor, b_tensor), TENSOR_LIST(y1), 0);
    272
    5
        ccv_nnc_cmd_exec(CMD_AVERAGE_POOL_FORWARD(3, 3), HINT((1, 1), (1, 1)), 0, TENSOR_LIST(y1), TENSOR_LIST(x1), 0);
    273
    5
      }
    274
    1
      ccv_nnc_graph_autotune(graph, 0, 0, TRAVERSE_FULL);
    275
    1
      ccv_nnc_graph_run(graph, 0, TRAVERSE_FULL, 0, 0);
    276
    1
      ccv_nnc_tensor_t* z_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, z);
    277
    1
      REQUIRE_MATRIX_EQ(x1, z_tensor, "5x5x4 matrix should be exactly the same");
    278
    1
      ccv_nnc_tensor_free(x1);
    279
    1
      ccv_nnc_tensor_free(y1);
    280
    1
      ccv_nnc_symbolic_graph_free(symbolic_graph);
    281
    1
      ccv_nnc_graph_exec_arena_free(graph_exec_arena);
    282
    1
      ccv_nnc_tensor_arena_free(tensor_arena);
    283
    1
      ccv_nnc_graph_free(graph);
    284
    1
    }
    285
    286
    TEST_CASE("symbolic graph for a while loop to compute x = conv(x, w, b) 5 times")
    287
    1
    {
    288
    1
      ccv_nnc_symbolic_graph_t* symbolic_graph = ccv_nnc_symbolic_graph_new();
    289
    1
      ccv_nnc_symbolic_graph_t* while_graph = ccv_nnc_symbolic_graph_new();
    290
    1
      ccv_nnc_symbolic_graph_while(symbolic_graph, CCV_NNC_GRAPH_FORWARD, while_graph, "while 1..5");
    291
    1
      ccv_nnc_tensor_symbol_t x = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 5, 5, 4), "x");
    292
    1
      ccv_nnc_tensor_symbol_t w = ccv_nnc_tensor_symbol_new(while_graph, CPU_TENSOR_NHWC(32F, 4, 3, 3, 4), "w");
    293
    1
      ccv_nnc_tensor_symbol_t b = ccv_nnc_tensor_symbol_new(while_graph, CPU_TENSOR_NHWC(32F, 4), "b");
    294
    1
      ccv_nnc_tensor_symbol_t y = ccv_nnc_tensor_symbol_new(while_graph, CPU_TENSOR_NHWC(32F, 5, 5, 4), "y");
    295
    1
      ccv_nnc_tensor_symbol_t z0 = ccv_nnc_tensor_symbol_alias_new(while_graph, y, DIM_ALLOC(0, 0, 1), DIM_ALLOC(5 * 4, 4, 1), CPU_TENSOR_NHWC(32F, 5, 5, 3), "z0");
    296
    1
      ccv_nnc_tensor_symbol_t z1 = ccv_nnc_tensor_symbol_alias_new(while_graph, y, DIM_ALLOC(4), DIM_ALLOC(1), CPU_TENSOR_NHWC(32F, 6), "z1");
    297
    1
      ccv_nnc_graph_exec_symbol_t noop = ccv_nnc_graph_exec_symbol_new(while_graph, CMD_NOOP(), 0, 0, 0, 0, "noop");
    298
    1
      ccv_nnc_graph_exec_symbol_t conv = ccv_nnc_graph_exec_symbol_new(while_graph, CMD_CONVOLUTION_FORWARD(1, 4, 3, 3, 4), TENSOR_SYMBOL_LIST(x, w, b), TENSOR_SYMBOL_LIST(y), "conv");
    299
    1
      ccv_nnc_graph_exec_symbol_concat(while_graph, noop, conv);
    300
    1
      ccv_nnc_symbolic_graph_set_while_expr(while_graph, while_5, 0, TENSOR_SYMBOL_LIST(ccv_nnc_tensor_symbol_for_while_count(while_graph)), GRAPH_EXEC_SYMBOL_LIST(noop));
    301
    1
      ccv_nnc_symbolic_graph_set_carry_overs(while_graph, TENSOR_SYMBOL_MAP(KV(y, x)));
    302
    1
      ccv_nnc_symbolic_graph_set_sources(while_graph, GRAPH_EXEC_SYMBOL_LIST(noop));
    303
    1
      ccv_nnc_symbolic_graph_set_destinations(while_graph, GRAPH_EXEC_SYMBOL_LIST(conv));
    304
    1
      ccv_nnc_graph_t* graph = 0;
    305
    1
      ccv_nnc_tensor_arena_t* tensor_arena = 0;
    306
    1
      ccv_nnc_graph_exec_arena_t* graph_exec_arena = 0;
    307
    1
      ccv_nnc_graph_exec_symbol_autogen(symbolic_graph, 0, 0, CCV_NNC_AUTOGEN_ALL_EXECS | CCV_NNC_AUTOGEN_SOURCES_AND_DESTINATIONS);
    308
    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);
    309
    1
      SYMBOLIC_GRAPH_GEN(symbolic_graph, CCV_NNC_LONG_DOT_GRAPH);
    310
    1
      GRAPH_GEN(graph, CCV_NNC_LONG_DOT_GRAPH);
    311
    1
      ccv_nnc_tensor_t* x_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, x);
    312
    1
      ccv_nnc_tensor_t* w_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, w);
    313
    1
      ccv_nnc_tensor_t* b_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, b);
    314
    1
      ccv_nnc_tensor_t* y_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, y);
    315
    1
      ccv_nnc_tensor_t* z0_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, z0);
    316
    1
      ccv_nnc_tensor_t* z1_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, z1);
    317
    1
      int i;
    318
    1
      dsfmt_t dsfmt;
    319
    1
      dsfmt_init_gen_rand(&dsfmt, 0);
    320
    101
      for (i = 0; i < 5 * 5 * 4; i++100)
    321
    100
        x_tensor->data.f32[i] = dsfmt_genrand_open_close(&dsfmt);
    322
    1
      ccv_nnc_tensor_t* x1 = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 5, 5, 4), 0);
    323
    1
      memcpy(x1->data.f32, x_tensor->data.f32, sizeof(float) * 5 * 5 * 4);
    324
    145
      for (i = 0; i < 4 * 3 * 3 * 4; i++144)
    325
    144
        w_tensor->data.f32[i] = dsfmt_genrand_open_close(&dsfmt) / (4 * 3 * 3);
    326
    5
      for (i = 0; i < 4; i++4)
    327
    4
        b_tensor->data.f32[i] = 0.1;
    328
    101
      for (i = 0; i < 5 * 5 * 4; i++100)
    329
    100
        y_tensor->data.f32[i] = 1;
    330
    1
      REQUIRE(y_tensor->data.f32 != x_tensor->data.f32, "y tensor and x tensor should point to different data");
    331
    1
      ccv_nnc_tensor_t* y1 = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 5, 5, 4), 0);
    332
    6
      for (i = 0; i < 5; i++5)
    333
    5
      {
    334
    5
        ccv_nnc_cmd_exec(CMD_CONVOLUTION_FORWARD(1, 4, 3, 3, 4), HINT((1, 1), (1, 1)), 0, TENSOR_LIST(x1, w_tensor, b_tensor), TENSOR_LIST(y1), 0);
    335
    5
        memcpy(x1->data.f32, y1->data.f32, sizeof(float) * 5 * 5 * 4);
    336
    5
      }
    337
    1
      ccv_nnc_graph_autotune(graph, 0, 0, TRAVERSE_FULL);
    338
    1
      ccv_nnc_graph_run(graph, 0, TRAVERSE_FULL, 0, 0);
    339
    1
      REQUIRE_MATRIX_EQ(y1, y_tensor, "5x5x4 matrix should be exactly the same");
    340
    1
      REQUIRE(z0_tensor->data.f32 == y_tensor->data.f32 + 1, "z0 should point to the same memory region as y, offset by 1");
    341
      // z0 and z1 trigger different code path (z1 will trigger one additional tensor setup).
    342
    1
      REQUIRE(z1_tensor->data.f32 == y_tensor->data.f32 + 4, "z1 should point to the same memory region as y, offset by 4");
    343
    1
      ccv_nnc_tensor_free(x1);
    344
    1
      ccv_nnc_tensor_free(y1);
    345
    1
      ccv_nnc_symbolic_graph_free(symbolic_graph);
    346
    1
      ccv_nnc_graph_exec_arena_free(graph_exec_arena);
    347
    1
      ccv_nnc_tensor_arena_free(tensor_arena);
    348
    1
      ccv_nnc_graph_free(graph);
    349
    1
    }
    350
    351
    TEST_CASE("symbolic graph for a while loop to compute x = conv(x, w, b) 5 times then z = x0 + x")
    352
    1
    {
    353
    1
      ccv_nnc_symbolic_graph_t* symbolic_graph = ccv_nnc_symbolic_graph_new();
    354
    1
      ccv_nnc_symbolic_graph_t* while_graph = ccv_nnc_symbolic_graph_new();
    355
    1
      ccv_nnc_symbolic_graph_while(symbolic_graph, CCV_NNC_GRAPH_FORWARD, while_graph, "while 1..5");
    356
    1
      ccv_nnc_tensor_symbol_t x = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 5, 5, 4), "x");
    357
    1
      ccv_nnc_tensor_symbol_t w = ccv_nnc_tensor_symbol_new(while_graph, CPU_TENSOR_NHWC(32F, 4, 3, 3, 4), "w");
    358
    1
      ccv_nnc_tensor_symbol_t b = ccv_nnc_tensor_symbol_new(while_graph, CPU_TENSOR_NHWC(32F, 4), "b");
    359
    1
      ccv_nnc_tensor_symbol_t y = ccv_nnc_tensor_symbol_new(while_graph, CPU_TENSOR_NHWC(32F, 5, 5, 4), "y");
    360
    1
      ccv_nnc_graph_exec_symbol_t noop = ccv_nnc_graph_exec_symbol_new(while_graph, CMD_NOOP(), 0, 0, 0, 0, "noop");
    361
    1
      ccv_nnc_graph_exec_symbol_t conv = ccv_nnc_graph_exec_symbol_new(while_graph, CMD_CONVOLUTION_FORWARD(1, 4, 3, 3, 4), TENSOR_SYMBOL_LIST(x, w, b), TENSOR_SYMBOL_LIST(y), "conv");
    362
    1
      ccv_nnc_graph_exec_symbol_concat(while_graph, noop, conv);
    363
    1
      ccv_nnc_tensor_symbol_t xz = ccv_nnc_tensor_symbol_alias_new(symbolic_graph, x, ccv_nnc_no_ofs, DIM_ALLOC(1), CPU_TENSOR_NHWC(32F, 5 * 5 * 4), "x0");
    364
    1
      ccv_nnc_tensor_symbol_t yz = ccv_nnc_tensor_symbol_alias_new(while_graph, y, ccv_nnc_no_ofs, DIM_ALLOC(1), CPU_TENSOR_NHWC(32F, 5 * 5 * 4), "y0");
    365
    1
      ccv_nnc_tensor_symbol_t z = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 5 * 5 * 4), "z");
    366
    1
      ccv_nnc_graph_exec_symbol_new(symbolic_graph, CMD_EWSUM_FORWARD(), TENSOR_SYMBOL_LIST(xz, yz), TENSOR_SYMBOL_LIST(z), "sum");
    367
    1
      ccv_nnc_symbolic_graph_set_while_expr(while_graph, while_5, 0, TENSOR_SYMBOL_LIST(ccv_nnc_tensor_symbol_for_while_count(while_graph)), GRAPH_EXEC_SYMBOL_LIST(noop));
    368
    1
      ccv_nnc_symbolic_graph_set_carry_overs(while_graph, TENSOR_SYMBOL_MAP(KV(y, x)));
    369
    1
      ccv_nnc_symbolic_graph_set_sources(while_graph, GRAPH_EXEC_SYMBOL_LIST(noop));
    370
    1
      ccv_nnc_symbolic_graph_set_destinations(while_graph, GRAPH_EXEC_SYMBOL_LIST(conv));
    371
    1
      ccv_nnc_graph_t* graph = 0;
    372
    1
      ccv_nnc_tensor_arena_t* tensor_arena = 0;
    373
    1
      ccv_nnc_graph_exec_arena_t* graph_exec_arena = 0;
    374
    1
      ccv_nnc_graph_exec_symbol_autogen(symbolic_graph, 0, 0, CCV_NNC_AUTOGEN_ALL_EXECS | CCV_NNC_AUTOGEN_SOURCES_AND_DESTINATIONS);
    375
    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);
    376
    1
      SYMBOLIC_GRAPH_GEN(symbolic_graph, CCV_NNC_LONG_DOT_GRAPH);
    377
    1
      GRAPH_GEN(graph, CCV_NNC_LONG_DOT_GRAPH);
    378
    1
      ccv_nnc_tensor_t* x_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, x);
    379
    1
      ccv_nnc_tensor_t* w_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, w);
    380
    1
      ccv_nnc_tensor_t* b_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, b);
    381
    1
      ccv_nnc_tensor_t* y_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, y);
    382
    1
      ccv_nnc_tensor_t* z_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, z);
    383
    1
      int i;
    384
    1
      dsfmt_t dsfmt;
    385
    1
      dsfmt_init_gen_rand(&dsfmt, 0);
    386
    101
      for (i = 0; i < 5 * 5 * 4; i++100)
    387
    100
        x_tensor->data.f32[i] = dsfmt_genrand_open_close(&dsfmt);
    388
    1
      ccv_nnc_tensor_t* x0 = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 5, 5, 4), 0);
    389
    1
      ccv_nnc_tensor_t* x1 = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 5, 5, 4), 0);
    390
    1
      memcpy(x0->data.f32, x_tensor->data.f32, sizeof(float) * 5 * 5 * 4);
    391
    1
      memcpy(x1->data.f32, x_tensor->data.f32, sizeof(float) * 5 * 5 * 4);
    392
    145
      for (i = 0; i < 4 * 3 * 3 * 4; i++144)
    393
    144
        w_tensor->data.f32[i] = dsfmt_genrand_open_close(&dsfmt) / (4 * 3 * 3);
    394
    5
      for (i = 0; i < 4; i++4)
    395
    4
        b_tensor->data.f32[i] = 0.1;
    396
    101
      for (i = 0; i < 5 * 5 * 4; i++100)
    397
    100
        y_tensor->data.f32[i] = 1;
    398
    1
      REQUIRE(y_tensor->data.f32 != x_tensor->data.f32, "y tensor and x tensor should point to different data");
    399
    1
      ccv_nnc_tensor_t* y1 = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 5, 5, 4), 0);
    400
    6
      for (i = 0; i < 5; i++5)
    401
    5
      {
    402
    5
        ccv_nnc_cmd_exec(CMD_CONVOLUTION_FORWARD(1, 4, 3, 3, 4), HINT((1, 1), (1, 1)), 0, TENSOR_LIST(x1, w_tensor, b_tensor), TENSOR_LIST(y1), 0);
    403
    5
        memcpy(x1->data.f32, y1->data.f32, sizeof(float) * 5 * 5 * 4);
    404
    5
      }
    405
    101
      for (i = 0; i < 5 * 5 * 4; i++100)
    406
    100
        x0->data.f32[i] += y1->data.f32[i];
    407
    1
      ccv_nnc_tensor_t z0 = ccv_nnc_tensor(x0->data.f32, CPU_TENSOR_NHWC(32F, 5 * 5 * 4), 0);
    408
    1
      ccv_nnc_graph_autotune(graph, 0, 0, TRAVERSE_FULL);
    409
    1
      ccv_nnc_graph_run(graph, 0, TRAVERSE_FULL, 0, 0);
    410
    1
      REQUIRE_MATRIX_EQ(&z0, z_tensor, "5x5x4 matrix should be exactly the same");
    411
    1
      ccv_nnc_tensor_free(x0);
    412
    1
      ccv_nnc_tensor_free(x1);
    413
    1
      ccv_nnc_tensor_free(y1);
    414
    1
      ccv_nnc_symbolic_graph_free(symbolic_graph);
    415
    1
      ccv_nnc_graph_exec_arena_free(graph_exec_arena);
    416
    1
      ccv_nnc_tensor_arena_free(tensor_arena);
    417
    1
      ccv_nnc_graph_free(graph);
    418
    1
    }
    419
    420
    TEST_CASE("symbolic graph for a while loop to compute (x = conv(x, w, b) 5 times, z = x0 + x (x <- z)) 5 times")
    421
    1
    {
    422
    1
      ccv_nnc_symbolic_graph_t* symbolic_graph = ccv_nnc_symbolic_graph_new();
    423
    1
      ccv_nnc_symbolic_graph_t* while_graph = ccv_nnc_symbolic_graph_new();
    424
    1
      ccv_nnc_symbolic_graph_t* sub_while_graph = ccv_nnc_symbolic_graph_new();
    425
    1
      ccv_nnc_symbolic_graph_while(symbolic_graph, CCV_NNC_GRAPH_FORWARD, while_graph, "while 1..5");
    426
    1
      ccv_nnc_graph_exec_symbol_t sub_while = ccv_nnc_symbolic_graph_while(while_graph, CCV_NNC_GRAPH_FORWARD, sub_while_graph, "while 1..5");
    427
    1
      ccv_nnc_tensor_symbol_t x = ccv_nnc_tensor_symbol_new(while_graph, CPU_TENSOR_NHWC(32F, 5, 5, 4), "x");
    428
    1
      ccv_nnc_tensor_symbol_t w = ccv_nnc_tensor_symbol_new(sub_while_graph, CPU_TENSOR_NHWC(32F, 4, 3, 3, 4), "w");
    429
    1
      ccv_nnc_tensor_symbol_t b = ccv_nnc_tensor_symbol_new(sub_while_graph, CPU_TENSOR_NHWC(32F, 4), "b");
    430
    1
      ccv_nnc_tensor_symbol_t y = ccv_nnc_tensor_symbol_new(while_graph, CPU_TENSOR_NHWC(32F, 5, 5, 4), "y");
    431
    1
      ccv_nnc_graph_exec_symbol_t sub_noop = ccv_nnc_graph_exec_symbol_new(sub_while_graph, CMD_NOOP(), 0, 0, 0, 0, "noop");
    432
    1
      ccv_nnc_graph_exec_symbol_t conv = ccv_nnc_graph_exec_symbol_new(sub_while_graph, CMD_CONVOLUTION_FORWARD(1, 4, 3, 3, 4), TENSOR_SYMBOL_LIST(x, w, b), TENSOR_SYMBOL_LIST(y), "conv");
    433
    1
      ccv_nnc_graph_exec_symbol_concat(sub_while_graph, sub_noop, conv);
    434
    1
      ccv_nnc_tensor_symbol_t xz = ccv_nnc_tensor_symbol_alias_new(while_graph, x, ccv_nnc_no_ofs, DIM_ALLOC(1), CPU_TENSOR_NHWC(32F, 5 * 5 * 4), "x0");
    435
    1
      ccv_nnc_tensor_symbol_t yz = ccv_nnc_tensor_symbol_alias_new(while_graph, y, ccv_nnc_no_ofs, DIM_ALLOC(1), CPU_TENSOR_NHWC(32F, 5 * 5 * 4), "y0");
    436
    1
      ccv_nnc_tensor_symbol_t z = ccv_nnc_tensor_symbol_new(while_graph, CPU_TENSOR_NHWC(32F, 5, 5, 4), "z");
    437
    1
      ccv_nnc_tensor_symbol_t zz = ccv_nnc_tensor_symbol_alias_new(while_graph, z, ccv_nnc_no_ofs, DIM_ALLOC(1), CPU_TENSOR_NHWC(32F, 5 * 5 * 4), "z0");
    438
    1
      ccv_nnc_graph_exec_symbol_t sum = ccv_nnc_graph_exec_symbol_new(while_graph, CMD_EWSUM_FORWARD(), TENSOR_SYMBOL_LIST(xz, yz), TENSOR_SYMBOL_LIST(zz), "sum");
    439
    1
      ccv_nnc_symbolic_graph_set_while_expr(sub_while_graph, while_5, 0, TENSOR_SYMBOL_LIST(ccv_nnc_tensor_symbol_for_while_count(sub_while_graph), ccv_nnc_tensor_symbol_for_while_count(while_graph)), GRAPH_EXEC_SYMBOL_LIST(sub_noop));
    440
    1
      ccv_nnc_symbolic_graph_set_carry_overs(sub_while_graph, TENSOR_SYMBOL_MAP(KV(y, x)));
    441
    1
      ccv_nnc_symbolic_graph_set_sources(sub_while_graph, GRAPH_EXEC_SYMBOL_LIST(sub_noop));
    442
    1
      ccv_nnc_symbolic_graph_set_destinations(sub_while_graph, GRAPH_EXEC_SYMBOL_LIST(conv));
    443
    1
      ccv_nnc_graph_exec_symbol_t noop = ccv_nnc_graph_exec_symbol_new(while_graph, CMD_NOOP(), 0, 0, 0, 0, "noop");
    444
    1
      ccv_nnc_graph_exec_symbol_concat(while_graph, noop, sub_while);
    445
    1
      ccv_nnc_graph_exec_symbol_concat(while_graph, sub_while, sum);
    446
    1
      ccv_nnc_symbolic_graph_set_while_expr(while_graph, while_5, 0, TENSOR_SYMBOL_LIST(ccv_nnc_tensor_symbol_for_while_count(while_graph)), GRAPH_EXEC_SYMBOL_LIST(noop));
    447
    1
      ccv_nnc_symbolic_graph_set_carry_overs(while_graph, TENSOR_SYMBOL_MAP(KV(z, x)));
    448
    1
      ccv_nnc_symbolic_graph_set_sources(while_graph, GRAPH_EXEC_SYMBOL_LIST(noop));
    449
    1
      ccv_nnc_symbolic_graph_set_destinations(while_graph, GRAPH_EXEC_SYMBOL_LIST(sum));
    450
    1
      ccv_nnc_graph_exec_symbol_autogen(symbolic_graph, 0, 0, CCV_NNC_AUTOGEN_ALL_EXECS | CCV_NNC_AUTOGEN_SOURCES_AND_DESTINATIONS);
    451
    1
      SYMBOLIC_GRAPH_GEN(symbolic_graph, CCV_NNC_LONG_DOT_GRAPH);
    452
    1
      ccv_nnc_graph_t* graph = 0;
    453
    1
      ccv_nnc_tensor_arena_t* tensor_arena = 0;
    454
    1
      ccv_nnc_graph_exec_arena_t* graph_exec_arena = 0;
    455
    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);
    456
    1
      GRAPH_GEN(graph, CCV_NNC_LONG_DOT_GRAPH);
    457
    1
      ccv_nnc_tensor_t* x_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, x);
    458
    1
      ccv_nnc_tensor_t* w_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, w);
    459
    1
      ccv_nnc_tensor_t* b_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, b);
    460
    1
      ccv_nnc_tensor_t* y_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, y);
    461
    1
      ccv_nnc_tensor_t* z_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, z);
    462
    1
      int i, j;
    463
    1
      dsfmt_t dsfmt;
    464
    1
      dsfmt_init_gen_rand(&dsfmt, 0);
    465
    101
      for (i = 0; i < 5 * 5 * 4; i++100)
    466
    100
        x_tensor->data.f32[i] = dsfmt_genrand_open_close(&dsfmt);
    467
    1
      ccv_nnc_tensor_t* x0 = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 5, 5, 4), 0);
    468
    1
      ccv_nnc_tensor_t* x1 = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 5, 5, 4), 0);
    469
    1
      memcpy(x0->data.f32, x_tensor->data.f32, sizeof(float) * 5 * 5 * 4);
    470
    145
      for (i = 0; i < 4 * 3 * 3 * 4; i++144)
    471
    144
        w_tensor->data.f32[i] = dsfmt_genrand_open_close(&dsfmt) / (4 * 3 * 3);
    472
    5
      for (i = 0; i < 4; i++4)
    473
    4
        b_tensor->data.f32[i] = 0.1;
    474
    101
      for (i = 0; i < 5 * 5 * 4; i++100)
    475
    100
        y_tensor->data.f32[i] = 1;
    476
    1
      REQUIRE(y_tensor->data.f32 != x_tensor->data.f32, "y tensor and x tensor should point to different data");
    477
    1
      ccv_nnc_tensor_t* y1 = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 5, 5, 4), 0);
    478
    6
      for (i = 0; i < 5; i++5)
    479
    5
      {
    480
    5
        memcpy(x1->data.f32, x0->data.f32, sizeof(float) * 5 * 5 * 4);
    481
    30
        for (j = 0; j < 5; j++25)
    482
    25
        {
    483
    25
          ccv_nnc_cmd_exec(CMD_CONVOLUTION_FORWARD(1, 4, 3, 3, 4), HINT((1, 1), (1, 1)), 0, TENSOR_LIST(x1, w_tensor, b_tensor), TENSOR_LIST(y1), 0);
    484
    25
          memcpy(x1->data.f32, y1->data.f32, sizeof(float) * 5 * 5 * 4);
    485
    25
        }
    486
    505
        for (j = 0; j < 5 * 5 * 4; j++500)
    487
    500
          x0->data.f32[j] += y1->data.f32[j];
    488
    5
      }
    489
    1
      ccv_nnc_graph_autotune(graph, 0, 0, TRAVERSE_FULL);
    490
    1
      ccv_nnc_graph_run(graph, 0, TRAVERSE_FULL, 0, 0);
    491
    1
      REQUIRE_MATRIX_EQ(x0, z_tensor, "5x5x4 matrix should be exactly the same");
    492
    1
      ccv_nnc_tensor_free(x0);
    493
    1
      ccv_nnc_tensor_free(x1);
    494
    1
      ccv_nnc_tensor_free(y1);
    495
    1
      ccv_nnc_graph_exec_arena_free(graph_exec_arena);
    496
    1
      ccv_nnc_tensor_arena_free(tensor_arena);
    497
    1
      ccv_nnc_graph_free(graph);
    498
    1
      ccv_nnc_symbolic_graph_free(symbolic_graph);
    499
    1
    }
    500
    501
    TEST_CASE("symbolic graph for a while loop to compute y = conv(x1, w, b), x2 = x0 + y 5 times, (x0 <- x1, x1 <- x2)")
    502
    1
    {
    503
    1
      ccv_nnc_symbolic_graph_t* symbolic_graph = ccv_nnc_symbolic_graph_new();
    504
    1
      ccv_nnc_symbolic_graph_t* while_graph = ccv_nnc_symbolic_graph_new();
    505
    1
      ccv_nnc_symbolic_graph_while(symbolic_graph, CCV_NNC_GRAPH_FORWARD, while_graph, "while 1..5");
    506
    1
      ccv_nnc_tensor_symbol_t x1 = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 5, 5, 4), "x1");
    507
    1
      ccv_nnc_tensor_symbol_t x0 = ccv_nnc_tensor_symbol_new(while_graph, CPU_TENSOR_NHWC(32F, 5, 5, 4), "x0");
    508
    1
      ccv_nnc_tensor_symbol_t w = ccv_nnc_tensor_symbol_new(while_graph, CPU_TENSOR_NHWC(32F, 4, 3, 3, 4), "w");
    509
    1
      ccv_nnc_tensor_symbol_t b = ccv_nnc_tensor_symbol_new(while_graph, CPU_TENSOR_NHWC(32F, 4), "b");
    510
    1
      ccv_nnc_tensor_symbol_t y = ccv_nnc_tensor_symbol_new(while_graph, CPU_TENSOR_NHWC(32F, 5, 5, 4), "y");
    511
    1
      ccv_nnc_graph_exec_symbol_t noop = ccv_nnc_graph_exec_symbol_new(while_graph, CMD_NOOP(), 0, 0, 0, 0, "noop");
    512
    1
      ccv_nnc_graph_exec_symbol_t conv = ccv_nnc_graph_exec_symbol_new(while_graph, CMD_CONVOLUTION_FORWARD(1, 4, 3, 3, 4), TENSOR_SYMBOL_LIST(x1, w, b), TENSOR_SYMBOL_LIST(y), "conv");
    513
    1
      ccv_nnc_graph_exec_symbol_concat(while_graph, noop, conv);
    514
    1
      ccv_nnc_tensor_symbol_t x0z = ccv_nnc_tensor_symbol_alias_new(while_graph, x0, ccv_nnc_no_ofs, DIM_ALLOC(1), CPU_TENSOR_NHWC(32F, 5 * 5 * 4), "x0");
    515
    1
      ccv_nnc_tensor_symbol_t yz = ccv_nnc_tensor_symbol_alias_new(while_graph, y, ccv_nnc_no_ofs, DIM_ALLOC(1), CPU_TENSOR_NHWC(32F, 5 * 5 * 4), "y");
    516
    1
      ccv_nnc_tensor_symbol_t x2 = ccv_nnc_tensor_symbol_new(while_graph, CPU_TENSOR_NHWC(32F, 5, 5, 4), "x2");
    517
    1
      ccv_nnc_tensor_symbol_t x2z = ccv_nnc_tensor_symbol_alias_new(while_graph, x2, ccv_nnc_no_ofs, DIM_ALLOC(1), CPU_TENSOR_NHWC(32F, 5 * 5 * 4), "x2");
    518
    1
      ccv_nnc_graph_exec_symbol_new(while_graph, CMD_EWSUM_FORWARD(), TENSOR_SYMBOL_LIST(x0z, yz), TENSOR_SYMBOL_LIST(x2z), "sum");
    519
    1
      ccv_nnc_symbolic_graph_set_while_expr(while_graph, while_5, 0, TENSOR_SYMBOL_LIST(ccv_nnc_tensor_symbol_for_while_count(while_graph)), GRAPH_EXEC_SYMBOL_LIST(noop));
    520
    1
      ccv_nnc_symbolic_graph_set_carry_overs(while_graph, TENSOR_SYMBOL_MAP(KV(x2, x1), KV(x1, x0)));
    521
    1
      ccv_nnc_symbolic_graph_set_sources(while_graph, GRAPH_EXEC_SYMBOL_LIST(noop));
    522
    1
      ccv_nnc_symbolic_graph_set_destinations(while_graph, GRAPH_EXEC_SYMBOL_LIST(conv));
    523
    1
      ccv_nnc_graph_t* graph = 0;
    524
    1
      ccv_nnc_tensor_arena_t* tensor_arena = 0;
    525
    1
      ccv_nnc_graph_exec_arena_t* graph_exec_arena = 0;
    526
    1
      ccv_nnc_graph_exec_symbol_autogen(symbolic_graph, 0, 0, CCV_NNC_AUTOGEN_ALL_EXECS | CCV_NNC_AUTOGEN_SOURCES_AND_DESTINATIONS);
    527
    1
      SYMBOLIC_GRAPH_GEN(symbolic_graph, CCV_NNC_LONG_DOT_GRAPH);
    528
    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);
    529
    1
      GRAPH_GEN(graph, CCV_NNC_LONG_DOT_GRAPH);
    530
    1
      ccv_nnc_tensor_t* x0_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, x0);
    531
    1
      ccv_nnc_tensor_t* x1_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, x1);
    532
    1
      ccv_nnc_tensor_t* w_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, w);
    533
    1
      ccv_nnc_tensor_t* b_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, b);
    534
    1
      ccv_nnc_tensor_t* y_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, y);
    535
    1
      int i, j;
    536
    1
      memset(x0_tensor->data.f32, 0, sizeof(float) * 5 * 5 * 4);
    537
    1
      dsfmt_t dsfmt;
    538
    1
      dsfmt_init_gen_rand(&dsfmt, 0);
    539
    101
      for (i = 0; i < 5 * 5 * 4; i++100)
    540
    100
        x1_tensor->data.f32[i] = dsfmt_genrand_open_close(&dsfmt);
    541
    145
      for (i = 0; i < 4 * 3 * 3 * 4; i++144)
    542
    144
        w_tensor->data.f32[i] = dsfmt_genrand_open_close(&dsfmt) / (4 * 3 * 3);
    543
    5
      for (i = 0; i < 4; i++4)
    544
    4
        b_tensor->data.f32[i] = 0.1;
    545
    101
      for (i = 0; i < 5 * 5 * 4; i++100)
    546
    100
        y_tensor->data.f32[i] = 1;
    547
    1
      ccv_nnc_tensor_t* x0t = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 5, 5, 4), 0);
    548
    1
      memset(x0t->data.f32, 0, sizeof(float) * 5 * 5 * 4);
    549
    1
      ccv_nnc_tensor_t* x1t = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 5, 5, 4), 0);
    550
    1
      memcpy(x1t->data.f32, x1_tensor->data.f32, sizeof(float) * 5 * 5 * 4);
    551
    1
      ccv_nnc_tensor_t* x2t = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 5, 5, 4), 0);
    552
    6
      for (i = 0; i < 5; i++5)
    553
    5
      {
    554
    5
        ccv_nnc_cmd_exec(CMD_CONVOLUTION_FORWARD(1, 4, 3, 3, 4), HINT((1, 1), (1, 1)), 0, TENSOR_LIST(x1t, w_tensor, b_tensor), TENSOR_LIST(x2t), 0);
    555
    505
        for (j = 0; j < 5 * 5 * 4; j++500)
    556
    500
          x2t->data.f32[j] += x0t->data.f32[j];
    557
    5
        memcpy(x0t->data.f32, x1t->data.f32, sizeof(float) * 5 * 5 * 4);
    558
    5
        memcpy(x1t->data.f32, x2t->data.f32, sizeof(float) * 5 * 5 * 4);
    559
    5
      }
    560
    1
      ccv_nnc_graph_autotune(graph, 0, 0, TRAVERSE_FULL);
    561
    1
      ccv_nnc_graph_run(graph, 0, TRAVERSE_FULL, 0, 0);
    562
    1
      ccv_nnc_tensor_t* x2_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, x2);
    563
    1
      REQUIRE_MATRIX_EQ(x2t, x2_tensor, "5x5x4 matrix should be exactly the same");
    564
    1
      ccv_nnc_tensor_free(x0t);
    565
    1
      ccv_nnc_tensor_free(x1t);
    566
    1
      ccv_nnc_tensor_free(x2t);
    567
    1
      ccv_nnc_symbolic_graph_free(symbolic_graph);
    568
    1
      ccv_nnc_graph_exec_arena_free(graph_exec_arena);
    569
    1
      ccv_nnc_tensor_arena_free(tensor_arena);
    570
    1
      ccv_nnc_graph_free(graph);
    571
    1
    }
    572
    573
    TEST_CASE("a while loop to compute y = conv(x1, w, b), y1 = 1.2 * y, x3 = x0 + y1 5 times, then z = y + x3 + x2 + x1 + x0, (x0 <- x1, x1 <- x2, x2 <- x3)")
    574
    1
    {
    575
    1
      ccv_nnc_symbolic_graph_t* symbolic_graph = ccv_nnc_symbolic_graph_new();
    576
    1
      ccv_nnc_symbolic_graph_t* while_graph = ccv_nnc_symbolic_graph_new();
    577
    1
      ccv_nnc_symbolic_graph_while(symbolic_graph, CCV_NNC_GRAPH_FORWARD, while_graph, "while 1..5");
    578
    1
      ccv_nnc_tensor_symbol_t x1 = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 5, 5, 4), "x1");
    579
    1
      ccv_nnc_tensor_symbol_t y0 = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 5 * 5 * 4), "y0");
    580
    1
      ccv_nnc_tensor_symbol_t x0 = ccv_nnc_tensor_symbol_new(while_graph, CPU_TENSOR_NHWC(32F, 5, 5, 4), "x0");
    581
    1
      ccv_nnc_tensor_symbol_t w = ccv_nnc_tensor_symbol_new(while_graph, CPU_TENSOR_NHWC(32F, 4, 3, 3, 4), "w");
    582
    1
      ccv_nnc_tensor_symbol_t b = ccv_nnc_tensor_symbol_new(while_graph, CPU_TENSOR_NHWC(32F, 4), "b");
    583
    1
      ccv_nnc_tensor_symbol_t y = ccv_nnc_tensor_symbol_new(while_graph, CPU_TENSOR_NHWC(32F, 5, 5, 4), "y");
    584
    1
      ccv_nnc_tensor_symbol_t y1 = ccv_nnc_tensor_symbol_new(while_graph, CPU_TENSOR_NHWC(32F, 5 * 5 * 4), "y1");
    585
    1
      ccv_nnc_graph_exec_symbol_t noop = ccv_nnc_graph_exec_symbol_new(while_graph, CMD_NOOP(), 0, 0, 0, 0, "noop");
    586
    1
      ccv_nnc_graph_exec_symbol_t conv = ccv_nnc_graph_exec_symbol_new(while_graph, CMD_CONVOLUTION_FORWARD(1, 4, 3, 3, 4), TENSOR_SYMBOL_LIST(x1, w, b), TENSOR_SYMBOL_LIST(y), "conv");
    587
    1
      ccv_nnc_graph_exec_symbol_concat(while_graph, noop, conv);
    588
    1
      ccv_nnc_tensor_symbol_t x0z = ccv_nnc_tensor_symbol_alias_new(while_graph, x0, ccv_nnc_no_ofs, DIM_ALLOC(1), CPU_TENSOR_NHWC(32F, 5 * 5 * 4), "x0");
    589
    1
      ccv_nnc_tensor_symbol_t yz = ccv_nnc_tensor_symbol_alias_new(while_graph, y, ccv_nnc_no_ofs, DIM_ALLOC(1), CPU_TENSOR_NHWC(32F, 5 * 5 * 4), "y");
    590
    1
      ccv_nnc_graph_exec_symbol_new(while_graph, CMD_EWPROD_FORWARD(), TENSOR_SYMBOL_LIST(yz, y0), TENSOR_SYMBOL_LIST(y1), "prod");
    591
    1
      ccv_nnc_tensor_symbol_t x2 = ccv_nnc_tensor_symbol_new(while_graph, CPU_TENSOR_NHWC(32F, 5, 5, 4), "x2");
    592
    1
      ccv_nnc_tensor_symbol_t x2z = ccv_nnc_tensor_symbol_alias_new(while_graph, x2, ccv_nnc_no_ofs, DIM_ALLOC(1), CPU_TENSOR_NHWC(32F, 5 * 5 * 4), "x2");
    593
    1
      ccv_nnc_tensor_symbol_t x3 = ccv_nnc_tensor_symbol_new(while_graph, CPU_TENSOR_NHWC(32F, 5, 5, 4), "x3");
    594
    1
      ccv_nnc_tensor_symbol_t x3z = ccv_nnc_tensor_symbol_alias_new(while_graph, x3, ccv_nnc_no_ofs, DIM_ALLOC(1), CPU_TENSOR_NHWC(32F, 5 * 5 * 4), "x2");
    595
    1
      ccv_nnc_graph_exec_symbol_new(while_graph, CMD_EWSUM_FORWARD(), TENSOR_SYMBOL_LIST(x0z, y1), TENSOR_SYMBOL_LIST(x3z), "sum");
    596
    1
      ccv_nnc_tensor_symbol_t x1s = ccv_nnc_tensor_symbol_resolve(while_graph, x1);
    597
    1
      ccv_nnc_tensor_symbol_t x1z = ccv_nnc_tensor_symbol_alias_new(while_graph, x1s, ccv_nnc_no_ofs, DIM_ALLOC(1), CPU_TENSOR_NHWC(32F, 5 * 5 * 4), "x1");
    598
    1
      ccv_nnc_symbolic_graph_set_while_expr(while_graph, while_5, 0, TENSOR_SYMBOL_LIST(ccv_nnc_tensor_symbol_for_while_count(while_graph)), GRAPH_EXEC_SYMBOL_LIST(noop));
    599
    1
      ccv_nnc_symbolic_graph_set_carry_overs(while_graph, TENSOR_SYMBOL_MAP(KV(x3, x2), KV(x2, x1), KV(x1, x0)));
    600
    1
      ccv_nnc_symbolic_graph_set_sources(while_graph, GRAPH_EXEC_SYMBOL_LIST(noop));
    601
    1
      ccv_nnc_symbolic_graph_set_destinations(while_graph, GRAPH_EXEC_SYMBOL_LIST(conv));
    602
    1
      ccv_nnc_tensor_symbol_t z = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 5 * 5 * 4), "z");
    603
    1
      ccv_nnc_graph_exec_symbol_new(symbolic_graph, CMD_EWSUM_FORWARD(), TENSOR_SYMBOL_LIST(yz, x0z, x1z, x2z, x3z), TENSOR_SYMBOL_LIST(z), "sum1");
    604
    1
      ccv_nnc_graph_t* graph = 0;
    605
    1
      ccv_nnc_tensor_arena_t* tensor_arena = 0;
    606
    1
      ccv_nnc_graph_exec_arena_t* graph_exec_arena = 0;
    607
    1
      ccv_nnc_graph_exec_symbol_autogen(symbolic_graph, 0, 0, CCV_NNC_AUTOGEN_ALL_EXECS | CCV_NNC_AUTOGEN_SOURCES_AND_DESTINATIONS);
    608
    1
      SYMBOLIC_GRAPH_GEN(symbolic_graph, CCV_NNC_LONG_DOT_GRAPH);
    609
    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);
    610
    1
      GRAPH_GEN(graph, CCV_NNC_LONG_DOT_GRAPH);
    611
    1
      ccv_nnc_tensor_t* x0_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, x0);
    612
    1
      ccv_nnc_tensor_t* x1_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, x1);
    613
    1
      ccv_nnc_tensor_t* w_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, w);
    614
    1
      ccv_nnc_tensor_t* b_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, b);
    615
    1
      ccv_nnc_tensor_t* y_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, y);
    616
    1
      ccv_nnc_tensor_t* y0_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, y0);
    617
    1
      int i, j;
    618
    1
      memset(x0_tensor->data.f32, 0, sizeof(float) * 5 * 5 * 4);
    619
    1
      dsfmt_t dsfmt;
    620
    1
      dsfmt_init_gen_rand(&dsfmt, 0);
    621
    101
      for (i = 0; i < 5 * 5 * 4; i++100)
    622
    100
        x1_tensor->data.f32[i] = dsfmt_genrand_open_close(&dsfmt);
    623
    145
      for (i = 0; i < 4 * 3 * 3 * 4; i++144)
    624
    144
        w_tensor->data.f32[i] = dsfmt_genrand_open_close(&dsfmt) / (4 * 3 * 3);
    625
    5
      for (i = 0; i < 4; i++4)
    626
    4
        b_tensor->data.f32[i] = 0.1;
    627
    101
      for (i = 0; i < 5 * 5 * 4; i++100)
    628
    100
        y_tensor->data.f32[i] = 1;
    629
    101
      for (i = 0; i < 5 * 5 * 4; i++100)
    630
    100
        y0_tensor->data.f32[i] = 1.2;
    631
    1
      ccv_nnc_tensor_t* yt = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 5, 5, 4), 0);
    632
    1
      ccv_nnc_tensor_t* x0t = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 5, 5, 4), 0);
    633
    1
      memset(x0t->data.f32, 0, sizeof(float) * 5 * 5 * 4);
    634
    1
      ccv_nnc_tensor_t* x1t = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 5, 5, 4), 0);
    635
    1
      memcpy(x1t->data.f32, x1_tensor->data.f32, sizeof(float) * 5 * 5 * 4);
    636
    1
      ccv_nnc_tensor_t* x2t = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 5, 5, 4), 0);
    637
    1
      ccv_nnc_tensor_t* x3t = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 5, 5, 4), 0);
    638
    6
      for (i = 0; i < 5; i++5)
    639
    5
      {
    640
    5
        ccv_nnc_cmd_exec(CMD_CONVOLUTION_FORWARD(1, 4, 3, 3, 4), HINT((1, 1), (1, 1)), 0, TENSOR_LIST(x1t, w_tensor, b_tensor), TENSOR_LIST(yt), 0);
    641
    505
        for (j = 0; j < 5 * 5 * 4; j++500)
    642
    500
          x3t->data.f32[j] = 1.2 * yt->data.f32[j] + x0t->data.f32[j];
    643
    5
        memcpy(x0t->data.f32, x1t->data.f32, sizeof(float) * 5 * 5 * 4);
    644
    5
        memcpy(x1t->data.f32, x2t->data.f32, sizeof(float) * 5 * 5 * 4);
    645
    5
        memcpy(x2t->data.f32, x3t->data.f32, sizeof(float) * 5 * 5 * 4);
    646
    5
      }
    647
    101
      for (j = 0; j < 5 * 5 * 4; j++100)
    648
    100
        x3t->data.f32[j] += yt->data.f32[j] + x2t->data.f32[j] + x1t->data.f32[j] + x0t->data.f32[j];
    649
    1
      ccv_nnc_tensor_t zt = ccv_nnc_tensor(x3t->data.f32, CPU_TENSOR_NHWC(32F, 5 * 5 * 4), 0);
    650
    1
      ccv_nnc_graph_autotune(graph, 0, 0, TRAVERSE_FULL);
    651
    1
      ccv_nnc_graph_run(graph, 0, TRAVERSE_FULL, 0, 0);
    652
    1
      ccv_nnc_tensor_t* z_tensor = ccv_nnc_tensor_from_symbol(tensor_arena, z);
    653
    1
      REQUIRE_MATRIX_EQ(&zt, z_tensor, "100 vector should be exactly the same");
    654
    1
      ccv_nnc_tensor_free(yt);
    655
    1
      ccv_nnc_tensor_free(x0t);
    656
    1
      ccv_nnc_tensor_free(x1t);
    657
    1
      ccv_nnc_tensor_free(x2t);
    658
    1
      ccv_nnc_tensor_free(x3t);
    659
    1
      ccv_nnc_symbolic_graph_free(symbolic_graph);
    660
    1
      ccv_nnc_graph_exec_arena_free(graph_exec_arena);
    661
    1
      ccv_nnc_tensor_arena_free(tensor_arena);
    662
    1
      ccv_nnc_graph_free(graph);
    663
    1
    }
    664
    665
    #include "case_main.h"