@@ -51,14 +51,53 @@ void k2c_pad2d(k2c_tensor* output, k2c_tensor* input, float fill, size_t pad[])
51
51
output -> array [i ] = fill ;}
52
52
}
53
53
// memcpy the old array in the middle
54
- size_t offset = in_channels * (pad_left + pad_right + in_width )* pad_top + in_channels * pad_left ;
54
+ size_t offset = in_channels * (pad_left + pad_right + in_width )* pad_top +
55
+ in_channels * pad_left ;
55
56
size_t num = in_channels * in_width ;
56
57
for (size_t i = 0 ; i < in_height ; i ++ ) {
57
- memcpy (& output -> array [offset ],& input -> array [i * num ],num * sizeof (input -> array [0 ]));
58
+ memcpy (& output -> array [offset ],
59
+ & input -> array [i * num ],
60
+ num * sizeof (input -> array [0 ]));
58
61
offset += num + in_channels * (pad_left + pad_right );
59
62
}
60
63
}
61
64
65
+ void k2c_pad3d (k2c_tensor * output , k2c_tensor * input , float fill , size_t pad []) {
66
+
67
+ size_t dim1 = input -> shape [0 ];
68
+ size_t dim2 = input -> shape [1 ];
69
+ size_t dim3 = input -> shape [2 ];
70
+ size_t outdim1 = dim1 + pad [0 ] + pad [1 ];
71
+ size_t outdim2 = dim2 + pad [2 ] + pad [3 ];
72
+ size_t outdim3 = dim3 + pad [4 ] + pad [5 ];
73
+ size_t in_channels = input -> shape [3 ];
74
+
75
+ // set output array to fill value
76
+ if (fabs (fill ) < 1e-6 ) {
77
+ // fill is ~zero, use memset
78
+ memset (output -> array ,0 ,output -> numel * sizeof (output -> array [0 ]));
79
+ }
80
+ else {
81
+ for (size_t i = 0 ; i < output -> numel ; i ++ ) {
82
+ output -> array [i ] = fill ;}
83
+ }
84
+ // memcpy the old array in the middle
85
+ size_t offset1 = in_channels * (outdim2 * outdim3 )* pad [0 ] + in_channels * outdim3 * pad [2 ] + in_channels * pad [4 ];
86
+ size_t num = in_channels * dim3 ;
87
+ size_t outstep2 = num + in_channels * (pad [4 ]+ pad [5 ]);
88
+ size_t outstep1 = outdim2 * outdim3 * in_channels ;
89
+ size_t instep1 = dim2 * dim3 * in_channels ;
90
+ size_t instep2 = dim3 * in_channels ;
91
+
92
+ for (size_t i = 0 ; i < dim1 ; i ++ ) {
93
+ for (size_t j = 0 ; j < dim2 ; j ++ ) {
94
+ memcpy (& output -> array [offset1 + i * outstep1 + j * outstep2 ],
95
+ & input -> array [i * instep1 + j * instep2 ],
96
+ num * sizeof (input -> array [0 ]));
97
+ }
98
+ }
99
+ }
100
+
62
101
void k2c_conv1d (k2c_tensor * output , k2c_tensor * input , k2c_tensor * kernel ,
63
102
k2c_tensor * bias , size_t stride , size_t dilation ,
64
103
void (* activation ) (float [], size_t )) {
@@ -108,7 +147,8 @@ void k2c_conv2d(k2c_tensor* output, k2c_tensor* input, k2c_tensor* kernel,
108
147
for (size_t q = 0 ; q < in_channels ; q ++ ) {
109
148
size_t outsub [K2C_MAX_NDIM ] = {x0 ,x1 ,k };
110
149
size_t inpsub [K2C_MAX_NDIM ] = {x0 * stride [0 ] + dilation [0 ]* z0 ,
111
- x1 * stride [1 ] + dilation [1 ]* z1 ,q };
150
+ x1 * stride [1 ] + dilation [1 ]* z1 ,
151
+ q };
112
152
size_t kersub [K2C_MAX_NDIM ] = {z0 ,z1 ,q ,k };
113
153
output -> array [k2c_sub2idx (outsub ,output -> shape ,output -> ndim )] +=
114
154
kernel -> array [k2c_sub2idx (kersub ,kernel -> shape ,kernel -> ndim )]*
@@ -123,6 +163,47 @@ void k2c_conv2d(k2c_tensor* output, k2c_tensor* input, k2c_tensor* kernel,
123
163
activation (output -> array ,output -> numel );
124
164
}
125
165
166
+ void k2c_conv3d (k2c_tensor * output , k2c_tensor * input , k2c_tensor * kernel ,
167
+ k2c_tensor * bias , size_t stride [], size_t dilation [],
168
+ void (* activation ) (float [], size_t )) {
169
+ /* 3D (spatial) convolution. Assumes a "channels last" structure
170
+ */
171
+ memset (output -> array ,0 ,output -> numel * sizeof (output -> array [0 ]));
172
+ size_t dim1 = output -> shape [0 ];
173
+ size_t dim2 = output -> shape [1 ];
174
+ size_t dim3 = output -> shape [2 ];
175
+ size_t out_channels = output -> shape [3 ];
176
+ size_t in_channels = input -> shape [3 ];
177
+
178
+ for (size_t x0 = 0 ; x0 < dim1 ; x0 ++ ){
179
+ for (size_t x1 = 0 ; x1 < dim2 ; x1 ++ ) {
180
+ for (size_t x2 = 0 ; x2 < dim3 ; x2 ++ ) {
181
+ for (size_t k = 0 ; k < out_channels ; k ++ ) {
182
+ for (size_t z0 = 0 ; z0 < kernel -> shape [0 ]; z0 ++ ) {
183
+ for (size_t z1 = 0 ; z1 < kernel -> shape [1 ]; z1 ++ ) {
184
+ for (size_t z2 = 0 ; z2 < kernel -> shape [2 ]; z2 ++ ) {
185
+ for (size_t q = 0 ; q < in_channels ; q ++ ) {
186
+ size_t outsub [K2C_MAX_NDIM ] = {x0 ,x1 ,x2 ,k };
187
+ size_t inpsub [K2C_MAX_NDIM ] = {x0 * stride [0 ] + dilation [0 ]* z0 ,
188
+ x1 * stride [1 ] + dilation [1 ]* z1 ,
189
+ x2 * stride [2 ] + dilation [2 ]* z2 ,
190
+ q };
191
+ size_t kersub [K2C_MAX_NDIM ] = {z0 ,z1 ,z2 ,q ,k };
192
+ output -> array [k2c_sub2idx (outsub ,output -> shape ,output -> ndim )] +=
193
+ kernel -> array [k2c_sub2idx (kersub ,kernel -> shape ,kernel -> ndim )]*
194
+ input -> array [k2c_sub2idx (inpsub ,input -> shape ,input -> ndim )];
195
+ }
196
+ }
197
+ }
198
+ }
199
+ }
200
+ }
201
+ }
202
+ }
203
+ k2c_bias_add (output ,bias );
204
+ activation (output -> array ,output -> numel );
205
+ }
206
+
126
207
void k2c_crop1d (k2c_tensor * output , k2c_tensor * input , size_t crop []) {
127
208
128
209
size_t offset = crop [0 ]* input -> shape [1 ];
@@ -147,6 +228,33 @@ void k2c_crop2d(k2c_tensor* output, k2c_tensor* input, size_t crop[]) {
147
228
}
148
229
}
149
230
231
+ void k2c_crop3d (k2c_tensor * output , k2c_tensor * input , size_t crop []) {
232
+
233
+ size_t dim1 = input -> shape [0 ];
234
+ size_t dim2 = input -> shape [1 ];
235
+ size_t dim3 = input -> shape [2 ];
236
+ size_t outdim1 = dim1 - crop [0 ] - crop [1 ];
237
+ size_t outdim2 = dim2 - crop [2 ] - crop [3 ];
238
+ size_t outdim3 = dim3 - crop [4 ] - crop [5 ];
239
+ size_t in_channels = input -> shape [3 ];
240
+
241
+ size_t offset1 = in_channels * (dim2 * dim3 )* crop [0 ] +
242
+ in_channels * dim3 * crop [2 ] + in_channels * crop [4 ];
243
+ size_t num = in_channels * outdim3 ;
244
+ size_t instep2 = num + in_channels * (crop [4 ]+ crop [5 ]);
245
+ size_t instep1 = dim2 * dim3 * in_channels ;
246
+ size_t outstep1 = outdim2 * outdim3 * in_channels ;
247
+ size_t outstep2 = outdim3 * in_channels ;
248
+
249
+ for (size_t i = 0 ; i < outdim1 ; i ++ ) {
250
+ for (size_t j = 0 ; j < outdim2 ; j ++ ) {
251
+ memcpy (& output -> array [i * outstep1 + j * outstep2 ],
252
+ & input -> array [offset1 + i * instep1 + j * instep2 ],
253
+ num * sizeof (input -> array [0 ]));
254
+ }
255
+ }
256
+ }
257
+
150
258
void k2c_upsampling1d (k2c_tensor * output , k2c_tensor * input , size_t size ) {
151
259
152
260
size_t in_height = input -> shape [0 ];
@@ -178,6 +286,24 @@ void k2c_upsampling2d(k2c_tensor* output, k2c_tensor* input, size_t size[]) {
178
286
}
179
287
}
180
288
289
+ void k2c_upsampling3d (k2c_tensor * output , k2c_tensor * input , size_t size []) {
181
290
291
+ size_t dim1 = output -> shape [0 ];
292
+ size_t dim2 = output -> shape [1 ];
293
+ size_t dim3 = output -> shape [2 ];
294
+ size_t channels = input -> shape [3 ];
295
+
296
+ for (size_t i = 0 ; i < dim1 ; i ++ ) {
297
+ for (size_t j = 0 ; j < dim2 ; j ++ ) {
298
+ for (size_t k = 0 ; k < dim3 ; k ++ ) {
299
+ size_t insub [K2C_MAX_NDIM ] = {i /size [0 ],j /size [1 ],k /size [2 ],0 };
300
+ size_t outsub [K2C_MAX_NDIM ] = {i ,j ,k ,0 };
301
+ memcpy (& output -> array [k2c_sub2idx (outsub ,output -> shape ,output -> ndim )],
302
+ & input -> array [k2c_sub2idx (insub ,input -> shape ,input -> ndim )],
303
+ channels * sizeof (input -> array [0 ]));
304
+ }
305
+ }
306
+ }
307
+ }
182
308
183
309
#endif /* KERAS2C_CONVOLUTION_LAYERS_H */
0 commit comments