Doxygen Book
tensor_data.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: LGPL-2.1-only */
13 #include <math.h>
14 #include "tensor_data.h"
15 #include "nnstreamer_log.h"
16 #include "nnstreamer_plugin_api.h"
17 
21 #define td_set_data(td,v,dtype) do { \
22  (td)->data._
23  } while (0)
24 
28 #define td_get_data(td,v,dtype) do { \
29  *((dtype *) v) = (td)->data._
30  } while (0)
31 
35 #define td_typecast_to(td,itype,otype) do { \
36  itype in_val = (td)->data._
37  otype out_val = (otype) in_val; \
38  (td)->data._
39  } while (0)
40 
41 #ifdef FLOAT16_SUPPORT
42 #define td_typecast_to_fromf16(td,otype) do { \
43  float16 in_val = (td)->data._float16; \
44  otype out_val = (otype) in_val; \
45  (td)->data._
46  } while (0)
47 #else /* FLOAT16_SUPPORT */
48 #define td_typecast_to_fromf16(td,itype) do { \
49  nns_loge ("Your nnstreamer binary is built without -DFLOAT16_SUPPORT option; thus float16 is not supported.\n"); \
50  g_assert (0); \
51  } while (0)
52 #endif
53 
54 #define td_typecast(td,otype) do { \
55  switch ((td)->type) { \
56  case _NNS_INT32: td_typecast_to (td, int32_t, otype); break; \
57  case _NNS_UINT32: td_typecast_to (td, uint32_t, otype); break; \
58  case _NNS_INT16: td_typecast_to (td, int16_t, otype); break; \
59  case _NNS_UINT16: td_typecast_to (td, uint16_t, otype); break; \
60  case _NNS_INT8: td_typecast_to (td, int8_t, otype); break; \
61  case _NNS_UINT8: td_typecast_to (td, uint8_t, otype); break; \
62  case _NNS_FLOAT64: td_typecast_to (td, double, otype); break; \
63  case _NNS_FLOAT32: td_typecast_to (td, float, otype); break; \
64  case _NNS_FLOAT16: td_typecast_to_fromf16 (td, otype); break; \
65  case _NNS_INT64: td_typecast_to (td, int64_t, otype); break; \
66  case _NNS_UINT64: td_typecast_to (td, uint64_t, otype); break; \
67  default: g_assert (0); break; \
68  } \
69  } while (0)
70 
78 gboolean
79 gst_tensor_data_set (tensor_data_s * td, tensor_type type, gpointer value)
80 {
81  g_return_val_if_fail (td != NULL, FALSE);
82  g_return_val_if_fail (value != NULL, FALSE);
83 
84  td->data._int64_t = 0;
85  td->type = _NNS_END;
86 
87  switch (type) {
88  case _NNS_INT32:
89  td_set_data (td, value, int32_t);
90  break;
91  case _NNS_UINT32:
92  td_set_data (td, value, uint32_t);
93  break;
94  case _NNS_INT16:
95  td_set_data (td, value, int16_t);
96  break;
97  case _NNS_UINT16:
98  td_set_data (td, value, uint16_t);
99  break;
100  case _NNS_INT8:
101  td_set_data (td, value, int8_t);
102  break;
103  case _NNS_UINT8:
104  td_set_data (td, value, uint8_t);
105  break;
106  case _NNS_FLOAT64:
107  td_set_data (td, value, double);
108  break;
109  case _NNS_FLOAT32:
110  td_set_data (td, value, float);
111  break;
112  case _NNS_FLOAT16:
113 #ifdef FLOAT16_SUPPORT
114  td_set_data (td, value, float16);
115  break;
116 #else
117  nns_loge
118  ("NNStreamer requires -DFLOAT16_SUPPORT as a build option to enable float16 type. This binary does not have float16 feature enabled; thus, float16 type is not supported in this instance.\n");
119  return FALSE;
120 #endif
121  case _NNS_INT64:
122  td_set_data (td, value, int64_t);
123  break;
124  case _NNS_UINT64:
125  td_set_data (td, value, uint64_t);
126  break;
127  default:
128  nns_logw ("Unknown tensor type %d", type);
129  return FALSE;
130  }
131 
132  td->type = type;
133  return TRUE;
134 }
135 
142 gboolean
143 gst_tensor_data_get (tensor_data_s * td, gpointer value)
144 {
145  g_return_val_if_fail (td != NULL, FALSE);
146  g_return_val_if_fail (value != NULL, FALSE);
147 
148  switch (td->type) {
149  case _NNS_INT32:
150  td_get_data (td, value, int32_t);
151  break;
152  case _NNS_UINT32:
153  td_get_data (td, value, uint32_t);
154  break;
155  case _NNS_INT16:
156  td_get_data (td, value, int16_t);
157  break;
158  case _NNS_UINT16:
159  td_get_data (td, value, uint16_t);
160  break;
161  case _NNS_INT8:
162  td_get_data (td, value, int8_t);
163  break;
164  case _NNS_UINT8:
165  td_get_data (td, value, uint8_t);
166  break;
167  case _NNS_FLOAT64:
168  td_get_data (td, value, double);
169  break;
170  case _NNS_FLOAT32:
171  td_get_data (td, value, float);
172  break;
173  case _NNS_FLOAT16:
174 #ifdef FLOAT16_SUPPORT
175  td_get_data (td, value, float16);
176  break;
177 #else
178  nns_loge
179  ("NNStreamer requires -DFLOAT16_SUPPORT as a build option to enable float16 type. This binary does not have float16 feature enabled; thus, float16 type is not supported in this instance.\n");
180  return FALSE;
181 #endif
182  case _NNS_INT64:
183  td_get_data (td, value, int64_t);
184  break;
185  case _NNS_UINT64:
186  td_get_data (td, value, uint64_t);
187  break;
188  default:
189  nns_logw ("Unknown tensor type %d", td->type);
190  return FALSE;
191  }
192 
193  return TRUE;
194 }
195 
202 gboolean
204 {
205  gboolean is_float;
206 
207  g_return_val_if_fail (td != NULL, FALSE);
208 
209  /* do nothing when transform to same type */
210  if (td->type != type) {
211  is_float = (td->type == _NNS_FLOAT32 || td->type == _NNS_FLOAT64
212  || td->type == _NNS_FLOAT16);
213 
214  switch (type) {
215  case _NNS_INT32:
216  td_typecast (td, int32_t);
217  break;
218  case _NNS_UINT32:
219  if (is_float) {
220  td_typecast (td, int32_t);
221  td->type = _NNS_INT32;
222  }
223  td_typecast (td, uint32_t);
224  break;
225  case _NNS_INT16:
226  td_typecast (td, int16_t);
227  break;
228  case _NNS_UINT16:
229  if (is_float) {
230  td_typecast (td, int16_t);
231  td->type = _NNS_INT16;
232  }
233  td_typecast (td, uint16_t);
234  break;
235  case _NNS_INT8:
236  td_typecast (td, int8_t);
237  break;
238  case _NNS_UINT8:
239  if (is_float) {
240  td_typecast (td, int8_t);
241  td->type = _NNS_INT8;
242  }
243  td_typecast (td, uint8_t);
244  break;
245  case _NNS_FLOAT64:
246  td_typecast (td, double);
247  break;
248  case _NNS_FLOAT32:
249  td_typecast (td, float);
250  break;
251  case _NNS_FLOAT16:
252 #ifdef FLOAT16_SUPPORT
253  td_typecast (td, float16);
254 #else
255  nns_loge
256  ("NNStreamer requires -DFLOAT16_SUPPORT as a build option to enable float16 type. This binary does not have float16 feature enabled; thus, float16 type is not supported in this instance.\n");
257  return FALSE;
258 #endif
259  break;
260  case _NNS_INT64:
261  td_typecast (td, int64_t);
262  break;
263  case _NNS_UINT64:
264  if (is_float) {
265  td_typecast (td, int64_t);
266  td->type = _NNS_INT64;
267  }
268  td_typecast (td, uint64_t);
269  break;
270  default:
271  nns_logw ("Unknown tensor type %d", type);
272  return FALSE;
273  }
274 
275  td->type = type;
276  }
277 
278  return TRUE;
279 }
280 
289 gboolean
290 gst_tensor_data_raw_typecast (gpointer input, tensor_type in_type,
291  gpointer output, tensor_type out_type)
292 {
293  tensor_data_s td;
294 
295  g_return_val_if_fail (input != NULL, FALSE);
296  g_return_val_if_fail (output != NULL, FALSE);
297  g_return_val_if_fail (in_type != _NNS_END, FALSE);
298  g_return_val_if_fail (out_type != _NNS_END, FALSE);
299 
300  gst_tensor_data_set (&td, in_type, input);
301  gst_tensor_data_typecast (&td, out_type);
302  gst_tensor_data_get (&td, output);
303  return TRUE;
304 }
305 
314 gboolean
315 gst_tensor_data_raw_average (gpointer raw, gsize length, tensor_type type,
316  gdouble ** result)
317 {
318  gdouble value, average;
319  gulong i, num;
320  gsize element_size;
321  guint8 *data;
322 
323  g_return_val_if_fail (raw != NULL, FALSE);
324  g_return_val_if_fail (length > 0, FALSE);
325  g_return_val_if_fail (type != _NNS_END, FALSE);
326 
327  element_size = gst_tensor_get_element_size (type);
328  num = length / element_size;
329 
330  average = 0.0;
331  *result = (gdouble *) g_try_malloc0 (sizeof (gdouble));
332  if (*result == NULL) {
333  nns_loge ("Failed to allocate memory for calculating average");
334  return FALSE;
335  }
336 
337  for (i = 0; i < num; ++i) {
338  /* extract value and typecast to double */
339  data = (guint8 *) raw + element_size * i;
341 
342  average = (value - average) / (i + 1) + average;
343  }
344 
345  **result = average;
346 
347  return TRUE;
348 }
349 
359 gboolean
360 gst_tensor_data_raw_average_per_channel (gpointer raw, gsize length,
361  tensor_type type, tensor_dim dim, gdouble ** results)
362 {
363  gdouble value, average;
364  gulong ch, i, num, offset;
365  gsize element_size;
366  guint8 *data;
367 
368  g_return_val_if_fail (raw != NULL, FALSE);
369  g_return_val_if_fail (length > 0, FALSE);
370  g_return_val_if_fail (dim[0] > 0, FALSE);
371  g_return_val_if_fail (type != _NNS_END, FALSE);
372 
373  element_size = gst_tensor_get_element_size (type);
374  num = length / element_size;
375 
376  offset = dim[0];
377  num = num / offset;
378  *results = (gdouble *) g_try_malloc0 (sizeof (gdouble) * offset);
379  if (*results == NULL) {
380  nns_loge ("Failed to allocate memory for calculating average");
381  return FALSE;
382  }
383 
384  for (ch = 0; ch < offset; ++ch) {
385  average = 0.0;
386  for (i = 0; i < num; ++i) {
387  /* extract value and typecast to double */
388  data = (guint8 *) raw + element_size * ((i * offset) + ch);
390  average = (value - average) / (i + 1) + average;
391  }
392 
393  (*results)[ch] = average;
394  }
395 
396  return TRUE;
397 }
398 
408 gboolean
409 gst_tensor_data_raw_std (gpointer raw, gsize length, tensor_type type,
410  gdouble * average, gdouble ** result)
411 {
412  gdouble value, std;
413  gulong i, num;
414  gsize element_size;
415  guint8 *data;
416 
417  g_return_val_if_fail (raw != NULL, FALSE);
418  g_return_val_if_fail (length > 0, FALSE);
419  g_return_val_if_fail (type != _NNS_END, FALSE);
420 
421  element_size = gst_tensor_get_element_size (type);
422  num = length / element_size;
423  *result = (gdouble *) g_try_malloc0 (sizeof (gdouble));
424  if (*result == NULL) {
425  nns_loge ("Failed to allocate memory for calculating standard deviation");
426  return FALSE;
427  }
428 
429  std = 0.0;
430  for (i = 0; i < num; ++i) {
431  /* extract value and typecast to double */
432  data = (guint8 *) raw + element_size * i;
434 
435  std += pow (value - *average, 2) / num;
436  }
437 
438  std = (std != 0.0) ? sqrt (std) : (1e-10);
439  **result = std;
440 
441  return TRUE;
442 }
443 
454 gboolean
455 gst_tensor_data_raw_std_per_channel (gpointer raw, gsize length,
456  tensor_type type, tensor_dim dim, gdouble * averages, gdouble ** results)
457 {
458  gdouble value, std;
459  gulong ch, i, num, offset;
460  gsize element_size;
461  guint8 *data;
462 
463  g_return_val_if_fail (raw != NULL, FALSE);
464  g_return_val_if_fail (length > 0, FALSE);
465  g_return_val_if_fail (dim[0] > 0, FALSE);
466  g_return_val_if_fail (type != _NNS_END, FALSE);
467 
468  element_size = gst_tensor_get_element_size (type);
469  num = length / element_size;
470 
471  offset = dim[0];
472  num = num / offset;
473  *results = (gdouble *) g_try_malloc0 (sizeof (gdouble) * offset);
474  if (*results == NULL) {
475  nns_loge ("Failed to allocate memory for calculating standard deviation");
476  return FALSE;
477  }
478 
479  for (ch = 0; ch < offset; ++ch) {
480  std = 0.0;
481  for (i = 0; i < num; ++i) {
482  /* extract value and typecast to double */
483  data = (guint8 *) raw + element_size * ((i * offset) + ch);
485  std += pow (value - averages[ch], 2) / num;
486  }
487 
488  std = (std != 0.0) ? sqrt (std) : (1e-10);
489  (*results)[ch] = std;
490  }
491 
492  return TRUE;
493 }
td_typecast
#define td_typecast(td, otype)
tensor_data.h
Internal functions to handle various tensor type and value.
_NNS_UINT64
@ _NNS_UINT64
Definition: tensor_typedef.h:149
data
svtc_1 data
Definition: gsttensor_if.c:844
tensor_data_s
Structure for tensor data.
Definition: tensor_data.h:23
_NNS_INT64
@ _NNS_INT64
Definition: tensor_typedef.h:148
tensor_dim
uint32_t tensor_dim[NNS_TENSOR_RANK_LIMIT]
Definition: tensor_typedef.h:247
td_set_data
#define td_set_data(td, v, dtype)
Macro to set data in struct.
Definition: tensor_data.c:21
gst_tensor_data_raw_std_per_channel
gboolean gst_tensor_data_raw_std_per_channel(gpointer raw, gsize length, tensor_type type, tensor_dim dim, gdouble *averages, gdouble **results)
Calculate standard deviation of the tensor per channel (the first dim).
Definition: tensor_data.c:455
FALSE
return FALSE
Definition: gsttensor_transform.c:590
result
case tensor_data_s gboolean * result
Definition: gsttensor_if.c:839
_NNS_FLOAT16
@ _NNS_FLOAT16
Definition: tensor_typedef.h:150
_NNS_UINT16
@ _NNS_UINT16
Definition: tensor_typedef.h:143
nnstreamer_log.h
Internal log util for NNStreamer plugins and native APIs.
tensor_element::_int64_t
int64_t _int64_t
Definition: tensor_typedef.h:240
gst_tensor_data_raw_average
gboolean gst_tensor_data_raw_average(gpointer raw, gsize length, tensor_type type, gdouble **result)
Calculate average value of the tensor.
Definition: tensor_data.c:315
tensor_type
enum _nns_tensor_type tensor_type
Possible data element types of other/tensor.
gst_tensor_data_raw_average_per_channel
gboolean gst_tensor_data_raw_average_per_channel(gpointer raw, gsize length, tensor_type type, tensor_dim dim, gdouble **results)
Calculate average value of the tensor per channel (the first dim).
Definition: tensor_data.c:360
_NNS_END
@ _NNS_END
Definition: tensor_typedef.h:152
gst_tensor_data_set
gboolean gst_tensor_data_set(tensor_data_s *td, tensor_type type, gpointer value)
Set tensor element data with given type.
gst_tensor_get_element_size
gsize gst_tensor_get_element_size(tensor_type type)
Get element size of tensor type (byte per element)
Definition: nnstreamer_plugin_api_util_impl.c:1205
gst_tensor_data_raw_typecast
gboolean gst_tensor_data_raw_typecast(gpointer input, tensor_type in_type, gpointer output, tensor_type out_type)
Typecast tensor element value.
Definition: tensor_data.c:290
_NNS_FLOAT32
@ _NNS_FLOAT32
Definition: tensor_typedef.h:147
tensor_data_s::data
tensor_element data
Definition: tensor_data.h:26
gst_tensor_data_get
gboolean gst_tensor_data_get(tensor_data_s *td, gpointer value)
Get tensor element value.
Definition: tensor_data.c:143
gst_tensor_data_raw_std
gboolean gst_tensor_data_raw_std(gpointer raw, gsize length, tensor_type type, gdouble *average, gdouble **result)
Calculate standard deviation of the tensor.
Definition: tensor_data.c:409
_NNS_INT32
@ _NNS_INT32
Definition: tensor_typedef.h:140
TRUE
return TRUE
Definition: gsttensor_if.c:897
nns_loge
#define nns_loge
Definition: nnstreamer_log.h:142
_NNS_INT16
@ _NNS_INT16
Definition: tensor_typedef.h:142
nns_logw
#define nns_logw
Definition: nnstreamer_log.h:141
_NNS_FLOAT64
@ _NNS_FLOAT64
Definition: tensor_typedef.h:146
tensor_data_s::type
tensor_type type
Definition: tensor_data.h:25
_NNS_UINT32
@ _NNS_UINT32
Definition: tensor_typedef.h:141
gst_tensor_data_typecast
gboolean gst_tensor_data_typecast(tensor_data_s *td, tensor_type type)
Typecast tensor element data.
Definition: tensor_data.c:203
_NNS_INT8
@ _NNS_INT8
Definition: tensor_typedef.h:144
td_get_data
#define td_get_data(td, v, dtype)
_NNS_UINT8
@ _NNS_UINT8
Definition: tensor_typedef.h:145
type
svtc_1 type
Definition: gsttensor_if.c:843
nnstreamer_plugin_api.h
Optional/Additional NNStreamer APIs for sub-plugin writers. (Need Gst devel)