Coverage Report

Created: 2019-07-03 22:50

/home/liu/buildslave/linux-x64-runtests/build/lib/nnc/_ccv_nnc_dynamic_graph.h
Line
Count
Source (jump to first uncovered line)
1
/**********************************************************
2
 * C-based/Cached/Core Computer Vision Library
3
 * Liu Liu, 2010-02-01
4
 **********************************************************/
5
6
/**********************************************************
7
 * CCV - Neural Network Collection
8
 **********************************************************/
9
10
#ifndef GUARD_ccv_nnc_dynamic_graph_internal_h
11
#define GUARD_ccv_nnc_dynamic_graph_internal_h
12
13
#include "ccv_nnc.h"
14
#include "ccv_nnc_internal.h"
15
16
6.08k
#define CCV_NNC_IS_EXTERN_TENSOR_VIEW(tv) ((uintptr_t)(tv) & 1)
17
13.3k
#define CCV_NNC_TENSOR_VIEW(tv) ((ccv_nnc_tensor_view_t*)((uintptr_t)(tv) & ~(uintptr_t)1))
18
19
enum {
20
  CCV_NNC_TENSOR_VARIABLE,
21
  CCV_NNC_TENSOR_CONSTANT,
22
};
23
24
struct ccv_nnc_tensor_variable_s {
25
  int type;
26
  int index;
27
  int alias_ref;
28
  ccv_nnc_tensor_param_t info;
29
  ccv_nnc_tensor_symbol_t symbol;
30
  ccv_nnc_tensor_view_t* tensor_view;
31
  int ofs[CCV_NNC_MAX_DIM_ALLOC];
32
  int inc[CCV_NNC_MAX_DIM_ALLOC];
33
};
34
35
enum {
36
  CCV_NNC_TENSOR_NO_VARIABLE = -1,
37
  CCV_NNC_TENSOR_NO_VARIABLE_BUT_USED = -2,
38
};
39
40
typedef struct { // Extra information kept per tensor symbol along with symbolic graph.
41
  int type;
42
  int index; // The index back into the tensor variable. -1 meant no associated tensor vairable.
43
  ccv_array_t* sources; // array of graph_exec_symbol, use this tensor symbol as output.
44
  ccv_array_t* destinations; // array of graph_exec_symbol, use this tensor symbol as input.
45
  ccv_nnc_tensor_view_t* tensor_view; // Transfer ownership of the tensor view to here.
46
} ccv_nnc_tensor_variable_graph_bind_t;
47
48
struct ccv_nnc_dynamic_graph_s {
49
  int reuse_var; // -1 if no var can be reused. Otherwise first locate the reuse var without increase array size.
50
  ccv_array_t* vars; // Array keeps track of all allocated tensor variable.
51
  ccv_array_t* binds; // Array keeps track of extra information for a tensor symbol.
52
  ccv_nnc_symbolic_graph_t* tape; // Symbolic graph to keep track of computation.
53
  ccv_array_t* ws; // array of integers as workspace
54
};
55
56
ccv_nnc_tensor_variable_t ccv_nnc_tensor_variable_exchange_new(ccv_nnc_dynamic_graph_t* const graph, ccv_nnc_tensor_variable_t tensor_variable);
57
58
static inline void ccv_nnc_insert_if_prior_to_any(const ccv_nnc_symbolic_graph_t* const graph, const int d, ccv_array_t* const sources, uint32_t* const visited, int* const buf0, int* const buf1)
59
1.01k
{
60
1.01k
  if (visited[(d >> 5)] & (1u << (d & 31)))
61
5
    return;
62
1.01k
  visited[(d >> 5)] |= (1u << (d & 31));
63
1.01k
  buf0[0] = d;
64
1.01k
  int* buf[2] = {
65
1.01k
    buf0, buf1
66
1.01k
  };
67
1.01k
  int buf_size[2] = {
68
1.01k
    1, 0
69
1.01k
  };
70
1.01k
  int p = 0, q = 1;
71
1.01k
  int i, j, k;
72
1.01k
  int flag = 0;
73
4.03k
  while (buf_size[p] > 0)
74
3.02k
  {
75
3.02k
    buf_size[q] = 0;
76
6.04k
    for (i = 0; i < buf_size[p]; 
i++3.02k
)
77
3.02k
    {
78
3.02k
      const int* outgoings; int outgoing_size;
79
3.02k
      ccv_nnc_graph_exec_symbol_to(graph, (ccv_nnc_graph_exec_symbol_t){
80
3.02k
        .d = buf[p][i],
81
3.02k
        .graph = graph
82
3.02k
      }, &outgoings, &outgoing_size);
83
5.03k
      for (j = 0; j < outgoing_size; 
j++2.01k
)
84
2.01k
      {
85
2.01k
        const int outgoing_idx = outgoings[j];
86
2.01k
        for (k = 0; k < sources->rnum; 
k++3
)
87
3
        {
88
3
          ccv_nnc_graph_exec_symbol_t* const source_symbol = (ccv_nnc_graph_exec_symbol_t*)ccv_array_get(sources, k);
89
3
          // If this outgoing idx is one of the source, replace it with d, or delete it.
90
3
          if (source_symbol->d == outgoing_idx)
91
0
          {
92
0
            if (!flag)
93
0
            {
94
0
              source_symbol->d = d;
95
0
              flag = 1;
96
0
            } else {
97
0
              // Delete this from the list.
98
0
              if (k < sources->rnum - 1)
99
0
                source_symbol->d = ((ccv_nnc_graph_exec_symbol_t*)ccv_array_get(sources, sources->rnum - 1))->d;
100
0
              --sources->rnum;
101
0
            }
102
0
            break;
103
0
          }
104
3
        }
105
2.01k
        if (visited[(outgoing_idx >> 5)] & (1u << (outgoing_idx & 31)))
106
3
          continue;
107
2.01k
        visited[(outgoing_idx >> 5)] |= (1u << (outgoing_idx & 31));
108
2.01k
        buf[q][buf_size[q]] = outgoing_idx;
109
2.01k
        ++buf_size[q];
110
2.01k
      }
111
3.02k
    }
112
3.02k
    CCV_SWAP(p, q, i);
113
3.02k
  }
114
1.01k
  // If this node is not visited, and we cannot find anything in the sources to replace, this is a new top node.
115
1.01k
  if (!flag)
116
1.01k
  {
117
1.01k
    const ccv_nnc_graph_exec_symbol_t source_symbol = {
118
1.01k
      .d = d,
119
1.01k
      .graph = graph
120
1.01k
    };
121
1.01k
    ccv_array_push(sources, &source_symbol);
122
1.01k
  }
123
1.01k
}
Unexecuted instantiation: ccv_nnc_dynamic_graph.c:ccv_nnc_insert_if_prior_to_any
ccv_nnc_dynamic_graph_backward.c:ccv_nnc_insert_if_prior_to_any
Line
Count
Source
59
15
{
60
15
  if (visited[(d >> 5)] & (1u << (d & 31)))
61
5
    return;
62
10
  visited[(d >> 5)] |= (1u << (d & 31));
63
10
  buf0[0] = d;
64
10
  int* buf[2] = {
65
10
    buf0, buf1
66
10
  };
67
10
  int buf_size[2] = {
68
10
    1, 0
69
10
  };
70
10
  int p = 0, q = 1;
71
10
  int i, j, k;
72
10
  int flag = 0;
73
32
  while (buf_size[p] > 0)
74
22
  {
75
22
    buf_size[q] = 0;
76
45
    for (i = 0; i < buf_size[p]; 
i++23
)
77
23
    {
78
23
      const int* outgoings; int outgoing_size;
79
23
      ccv_nnc_graph_exec_symbol_to(graph, (ccv_nnc_graph_exec_symbol_t){
80
23
        .d = buf[p][i],
81
23
        .graph = graph
82
23
      }, &outgoings, &outgoing_size);
83
39
      for (j = 0; j < outgoing_size; 
j++16
)
84
16
      {
85
16
        const int outgoing_idx = outgoings[j];
86
19
        for (k = 0; k < sources->rnum; 
k++3
)
87
3
        {
88
3
          ccv_nnc_graph_exec_symbol_t* const source_symbol = (ccv_nnc_graph_exec_symbol_t*)ccv_array_get(sources, k);
89
3
          // If this outgoing idx is one of the source, replace it with d, or delete it.
90
3
          if (source_symbol->d == outgoing_idx)
91
0
          {
92
0
            if (!flag)
93
0
            {
94
0
              source_symbol->d = d;
95
0
              flag = 1;
96
0
            } else {
97
0
              // Delete this from the list.
98
0
              if (k < sources->rnum - 1)
99
0
                source_symbol->d = ((ccv_nnc_graph_exec_symbol_t*)ccv_array_get(sources, sources->rnum - 1))->d;
100
0
              --sources->rnum;
101
0
            }
102
0
            break;
103
0
          }
104
3
        }
105
16
        if (visited[(outgoing_idx >> 5)] & (1u << (outgoing_idx & 31)))
106
3
          continue;
107
13
        visited[(outgoing_idx >> 5)] |= (1u << (outgoing_idx & 31));
108
13
        buf[q][buf_size[q]] = outgoing_idx;
109
13
        ++buf_size[q];
110
13
      }
111
23
    }
112
22
    CCV_SWAP(p, q, i);
113
22
  }
114
10
  // If this node is not visited, and we cannot find anything in the sources to replace, this is a new top node.
115
10
  if (!flag)
116
10
  {
117
10
    const ccv_nnc_graph_exec_symbol_t source_symbol = {
118
10
      .d = d,
119
10
      .graph = graph
120
10
    };
121
10
    ccv_array_push(sources, &source_symbol);
122
10
  }
123
10
}
ccv_nnc_dynamic_graph_minimize.c:ccv_nnc_insert_if_prior_to_any
Line
Count
Source
59
1.00k
{
60
1.00k
  if (visited[(d >> 5)] & (1u << (d & 31)))
61
0
    return;
62
1.00k
  visited[(d >> 5)] |= (1u << (d & 31));
63
1.00k
  buf0[0] = d;
64
1.00k
  int* buf[2] = {
65
1.00k
    buf0, buf1
66
1.00k
  };
67
1.00k
  int buf_size[2] = {
68
1.00k
    1, 0
69
1.00k
  };
70
1.00k
  int p = 0, q = 1;
71
1.00k
  int i, j, k;
72
1.00k
  int flag = 0;
73
4.00k
  while (buf_size[p] > 0)
74
3.00k
  {
75
3.00k
    buf_size[q] = 0;
76
6.00k
    for (i = 0; i < buf_size[p]; 
i++3.00k
)
77
3.00k
    {
78
3.00k
      const int* outgoings; int outgoing_size;
79
3.00k
      ccv_nnc_graph_exec_symbol_to(graph, (ccv_nnc_graph_exec_symbol_t){
80
3.00k
        .d = buf[p][i],
81
3.00k
        .graph = graph
82
3.00k
      }, &outgoings, &outgoing_size);
83
5.00k
      for (j = 0; j < outgoing_size; 
j++2.00k
)
84
2.00k
      {
85
2.00k
        const int outgoing_idx = outgoings[j];
86
2.00k
        for (k = 0; k < sources->rnum; 
k++0
)
87
0
        {
88
0
          ccv_nnc_graph_exec_symbol_t* const source_symbol = (ccv_nnc_graph_exec_symbol_t*)ccv_array_get(sources, k);
89
0
          // If this outgoing idx is one of the source, replace it with d, or delete it.
90
0
          if (source_symbol->d == outgoing_idx)
91
0
          {
92
0
            if (!flag)
93
0
            {
94
0
              source_symbol->d = d;
95
0
              flag = 1;
96
0
            } else {
97
0
              // Delete this from the list.
98
0
              if (k < sources->rnum - 1)
99
0
                source_symbol->d = ((ccv_nnc_graph_exec_symbol_t*)ccv_array_get(sources, sources->rnum - 1))->d;
100
0
              --sources->rnum;
101
0
            }
102
0
            break;
103
0
          }
104
0
        }
105
2.00k
        if (visited[(outgoing_idx >> 5)] & (1u << (outgoing_idx & 31)))
106
0
          continue;
107
2.00k
        visited[(outgoing_idx >> 5)] |= (1u << (outgoing_idx & 31));
108
2.00k
        buf[q][buf_size[q]] = outgoing_idx;
109
2.00k
        ++buf_size[q];
110
2.00k
      }
111
3.00k
    }
112
3.00k
    CCV_SWAP(p, q, i);
113
3.00k
  }
114
1.00k
  // If this node is not visited, and we cannot find anything in the sources to replace, this is a new top node.
115
1.00k
  if (!flag)
116
1.00k
  {
117
1.00k
    const ccv_nnc_graph_exec_symbol_t source_symbol = {
118
1.00k
      .d = d,
119
1.00k
      .graph = graph
120
1.00k
    };
121
1.00k
    ccv_array_push(sources, &source_symbol);
122
1.00k
  }
123
1.00k
}
124
125
static inline void ccv_nnc_remove_if_prior_to_any(const ccv_nnc_symbolic_graph_t* const graph, const int d, ccv_array_t* const destinations, uint32_t* const visited, int* const buf0, int* const buf1)
126
3
{
127
3
  int i, j, k;
128
3
  // If it is already visited, this is the later one, we are good.
129
3
  if (visited[(d >> 5)] & (1u << (d & 31)))
130
0
    return;
131
3
  visited[(d >> 5)] |= (1u << (d & 31));
132
3
  buf0[0] = d;
133
3
  int* buf[2] = {
134
3
    buf0, buf1
135
3
  };
136
3
  int buf_size[2] = {
137
3
    1, 0
138
3
  };
139
3
  int p = 0, q = 1;
140
3
  int flag = 0;
141
6
  while (!flag && 
buf_size[p] > 04
)
142
3
  {
143
3
    buf_size[q] = 0;
144
6
    for (i = 0; !flag && 
i < buf_size[p]4
;
i++3
)
145
3
    {
146
3
      const int* outgoings; int outgoing_size;
147
3
      ccv_nnc_graph_exec_symbol_to(graph, (ccv_nnc_graph_exec_symbol_t){
148
3
        .d = buf[p][i],
149
3
        .graph = graph
150
3
      }, &outgoings, &outgoing_size);
151
6
      for (j = 0; j < outgoing_size; 
j++3
)
152
3
      {
153
3
        const int outgoing_idx = outgoings[j];
154
3
        // If this node happens to be visited, do nothing.
155
3
        if (visited[(outgoing_idx >> 5)] & (1u << (outgoing_idx & 31)))
156
0
          continue;
157
6
        
for (k = 0; 3
!flag &&
k < destinations->rnum3
;
k++3
)
158
3
        {
159
3
          ccv_nnc_graph_exec_symbol_t* const destination_symbol = (ccv_nnc_graph_exec_symbol_t*)ccv_array_get(destinations, k);
160
3
          // If this outgoing idx is one of the destination, delete current node.
161
3
          flag = (destination_symbol->d == outgoing_idx);
162
3
        }
163
3
        visited[(outgoing_idx >> 5)] |= (1u << (outgoing_idx & 31));
164
3
        buf[q][buf_size[q]] = outgoing_idx;
165
3
        ++buf_size[q];
166
3
      }
167
3
    }
168
3
    CCV_SWAP(p, q, i);
169
3
  }
170
3
  if (flag)
171
3
    
for (i = 0; 2
i < destinations->rnum;
i++1
)
172
3
    {
173
3
      ccv_nnc_graph_exec_symbol_t* const destination_symbol = (ccv_nnc_graph_exec_symbol_t*)ccv_array_get(destinations, i);
174
3
      // If this outgoing idx is one of the destination, delete current node.
175
3
      if (destination_symbol->d == d)
176
2
      {
177
2
        // Delete this from the list.
178
2
        if (i < destinations->rnum - 1)
179
1
          destination_symbol->d = ((ccv_nnc_graph_exec_symbol_t*)ccv_array_get(destinations, destinations->rnum - 1))->d;
180
2
        --destinations->rnum;
181
2
        break;
182
2
      }
183
3
    }
184
3
}
Unexecuted instantiation: ccv_nnc_dynamic_graph.c:ccv_nnc_remove_if_prior_to_any
ccv_nnc_dynamic_graph_backward.c:ccv_nnc_remove_if_prior_to_any
Line
Count
Source
126
3
{
127
3
  int i, j, k;
128
3
  // If it is already visited, this is the later one, we are good.
129
3
  if (visited[(d >> 5)] & (1u << (d & 31)))
130
0
    return;
131
3
  visited[(d >> 5)] |= (1u << (d & 31));
132
3
  buf0[0] = d;
133
3
  int* buf[2] = {
134
3
    buf0, buf1
135
3
  };
136
3
  int buf_size[2] = {
137
3
    1, 0
138
3
  };
139
3
  int p = 0, q = 1;
140
3
  int flag = 0;
141
6
  while (!flag && 
buf_size[p] > 04
)
142
3
  {
143
3
    buf_size[q] = 0;
144
6
    for (i = 0; !flag && 
i < buf_size[p]4
;
i++3
)
145
3
    {
146
3
      const int* outgoings; int outgoing_size;
147
3
      ccv_nnc_graph_exec_symbol_to(graph, (ccv_nnc_graph_exec_symbol_t){
148
3
        .d = buf[p][i],
149
3
        .graph = graph
150
3
      }, &outgoings, &outgoing_size);
151
6
      for (j = 0; j < outgoing_size; 
j++3
)
152
3
      {
153
3
        const int outgoing_idx = outgoings[j];
154
3
        // If this node happens to be visited, do nothing.
155
3
        if (visited[(outgoing_idx >> 5)] & (1u << (outgoing_idx & 31)))
156
0
          continue;
157
6
        
for (k = 0; 3
!flag &&
k < destinations->rnum3
;
k++3
)
158
3
        {
159
3
          ccv_nnc_graph_exec_symbol_t* const destination_symbol = (ccv_nnc_graph_exec_symbol_t*)ccv_array_get(destinations, k);
160
3
          // If this outgoing idx is one of the destination, delete current node.
161
3
          flag = (destination_symbol->d == outgoing_idx);
162
3
        }
163
3
        visited[(outgoing_idx >> 5)] |= (1u << (outgoing_idx & 31));
164
3
        buf[q][buf_size[q]] = outgoing_idx;
165
3
        ++buf_size[q];
166
3
      }
167
3
    }
168
3
    CCV_SWAP(p, q, i);
169
3
  }
170
3
  if (flag)
171
3
    
for (i = 0; 2
i < destinations->rnum;
i++1
)
172
3
    {
173
3
      ccv_nnc_graph_exec_symbol_t* const destination_symbol = (ccv_nnc_graph_exec_symbol_t*)ccv_array_get(destinations, i);
174
3
      // If this outgoing idx is one of the destination, delete current node.
175
3
      if (destination_symbol->d == d)
176
2
      {
177
2
        // Delete this from the list.
178
2
        if (i < destinations->rnum - 1)
179
1
          destination_symbol->d = ((ccv_nnc_graph_exec_symbol_t*)ccv_array_get(destinations, destinations->rnum - 1))->d;
180
2
        --destinations->rnum;
181
2
        break;
182
2
      }
183
3
    }
184
3
}
Unexecuted instantiation: ccv_nnc_dynamic_graph_minimize.c:ccv_nnc_remove_if_prior_to_any
185
186
enum {
187
  CCV_NNC_SYMBOL_TENSOR,
188
  CCV_NNC_SYMBOL_TENSOR_ALIAS,
189
  CCV_NNC_SYMBOL_GRAPH_EXEC,
190
};
191
192
typedef struct {
193
  int type;
194
  int d;
195
} ccv_nnc_tape_symbol_t;
196
197
static inline void ccv_nnc_dynamic_graph_push_backward_tensor_symbol(void* context, const ccv_nnc_tensor_symbol_t symbol, const ccv_nnc_tensor_param_t info, const char* const name)
198
10.0k
{
199
10.0k
  ccv_array_t* const stack = (ccv_array_t*)context;
200
10.0k
  ccv_nnc_tape_symbol_t tape_symbol = {
201
10.0k
    .d = symbol.d,
202
10.0k
    .type = CCV_NNC_SYMBOL_TENSOR,
203
10.0k
  };
204
10.0k
  ccv_array_push(stack, &tape_symbol);
205
10.0k
}
Unexecuted instantiation: ccv_nnc_dynamic_graph.c:ccv_nnc_dynamic_graph_push_backward_tensor_symbol
ccv_nnc_dynamic_graph_backward.c:ccv_nnc_dynamic_graph_push_backward_tensor_symbol
Line
Count
Source
198
52
{
199
52
  ccv_array_t* const stack = (ccv_array_t*)context;
200
52
  ccv_nnc_tape_symbol_t tape_symbol = {
201
52
    .d = symbol.d,
202
52
    .type = CCV_NNC_SYMBOL_TENSOR,
203
52
  };
204
52
  ccv_array_push(stack, &tape_symbol);
205
52
}
ccv_nnc_dynamic_graph_minimize.c:ccv_nnc_dynamic_graph_push_backward_tensor_symbol
Line
Count
Source
198
10.0k
{
199
10.0k
  ccv_array_t* const stack = (ccv_array_t*)context;
200
10.0k
  ccv_nnc_tape_symbol_t tape_symbol = {
201
10.0k
    .d = symbol.d,
202
10.0k
    .type = CCV_NNC_SYMBOL_TENSOR,
203
10.0k
  };
204
10.0k
  ccv_array_push(stack, &tape_symbol);
205
10.0k
}
206
207
static inline void ccv_nnc_dynamic_graph_push_backward_tensor_symbol_alias(void* context, const ccv_nnc_tensor_symbol_t symbol, const ccv_nnc_tensor_symbol_t from_symbol, const int ofs[CCV_NNC_MAX_DIM_ALLOC], const int inc[CCV_NNC_MAX_DIM_ALLOC], const ccv_nnc_tensor_param_t info, const char* const name)
208
6
{
209
6
  ccv_array_t* const stack = (ccv_array_t*)context;
210
6
  ccv_nnc_tape_symbol_t tape_symbol = {
211
6
    .d = symbol.d,
212
6
    .type = CCV_NNC_SYMBOL_TENSOR_ALIAS,
213
6
  };
214
6
  ccv_array_push(stack, &tape_symbol);
215
6
}
Unexecuted instantiation: ccv_nnc_dynamic_graph.c:ccv_nnc_dynamic_graph_push_backward_tensor_symbol_alias
ccv_nnc_dynamic_graph_backward.c:ccv_nnc_dynamic_graph_push_backward_tensor_symbol_alias
Line
Count
Source
208
6
{
209
6
  ccv_array_t* const stack = (ccv_array_t*)context;
210
6
  ccv_nnc_tape_symbol_t tape_symbol = {
211
6
    .d = symbol.d,
212
6
    .type = CCV_NNC_SYMBOL_TENSOR_ALIAS,
213
6
  };
214
6
  ccv_array_push(stack, &tape_symbol);
215
6
}
Unexecuted instantiation: ccv_nnc_dynamic_graph_minimize.c:ccv_nnc_dynamic_graph_push_backward_tensor_symbol_alias
216
217
static inline void ccv_nnc_dynamic_graph_push_backward_graph_exec_symbol(void* context, const ccv_nnc_graph_exec_symbol_t symbol, const ccv_nnc_cmd_t cmd, const ccv_nnc_tensor_symbol_t* const inputs, const int input_size, const ccv_nnc_tensor_symbol_t* const outputs, const int output_size, const char* const name)
218
5.02k
{
219
5.02k
  ccv_array_t* const stack = (ccv_array_t*)context;
220
5.02k
  ccv_nnc_tape_symbol_t tape_symbol = {
221
5.02k
    .d = symbol.d,
222
5.02k
    .type = CCV_NNC_SYMBOL_GRAPH_EXEC,
223
5.02k
  };
224
5.02k
  ccv_array_push(stack, &tape_symbol);
225
5.02k
}
Unexecuted instantiation: ccv_nnc_dynamic_graph.c:ccv_nnc_dynamic_graph_push_backward_graph_exec_symbol
ccv_nnc_dynamic_graph_backward.c:ccv_nnc_dynamic_graph_push_backward_graph_exec_symbol
Line
Count
Source
218
27
{
219
27
  ccv_array_t* const stack = (ccv_array_t*)context;
220
27
  ccv_nnc_tape_symbol_t tape_symbol = {
221
27
    .d = symbol.d,
222
27
    .type = CCV_NNC_SYMBOL_GRAPH_EXEC,
223
27
  };
224
27
  ccv_array_push(stack, &tape_symbol);
225
27
}
ccv_nnc_dynamic_graph_minimize.c:ccv_nnc_dynamic_graph_push_backward_graph_exec_symbol
Line
Count
Source
218
5.00k
{
219
5.00k
  ccv_array_t* const stack = (ccv_array_t*)context;
220
5.00k
  ccv_nnc_tape_symbol_t tape_symbol = {
221
5.00k
    .d = symbol.d,
222
5.00k
    .type = CCV_NNC_SYMBOL_GRAPH_EXEC,
223
5.00k
  };
224
5.00k
  ccv_array_push(stack, &tape_symbol);
225
5.00k
}
226
227
#endif