LCOV - code coverage report
Current view: top level - nnstreamer-2.4.2/gst/nnstreamer - tensor_data.c (source / functions) Coverage Total Hit
Test: nnstreamer 2.4.2-0 nnstreamer/nnstreamer#eca68b8d050408568af95d831a8eef62aaee7784 Lines: 88.6 % 228 202
Test Date: 2025-03-13 05:38:21 Functions: 100.0 % 8 8

            Line data    Source code
       1              : /* SPDX-License-Identifier: LGPL-2.1-only */
       2              : /**
       3              :  * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved.
       4              :  *
       5              :  * @file        tensor_data.c
       6              :  * @date        10 Mar 2021
       7              :  * @brief       Internal functions to handle various tensor type and value.
       8              :  * @see http://github.com/nnstreamer/nnstreamer
       9              :  * @author      Jaeyun Jung <jy1210.jung@samsung.com>
      10              :  * @bug No known bugs except for NYI items
      11              :  */
      12              : 
      13              : #include <math.h>
      14              : #include "tensor_data.h"
      15              : #include "nnstreamer_log.h"
      16              : #include "nnstreamer_plugin_api.h"
      17              : 
      18              : /**
      19              :  * @brief Macro to set data in struct.
      20              :  */
      21              : #define td_set_data(td,v,dtype) do { \
      22              :     (td)->data._##dtype = *((dtype *) v); \
      23              :   } while (0)
      24              : 
      25              : /**
      26              :  * @brief Macro to get data from struct.
      27              :  */
      28              : #define td_get_data(td,v,dtype) do { \
      29              :     *((dtype *) v) = (td)->data._##dtype; \
      30              :   } while (0)
      31              : 
      32              : /**
      33              :  * @brief Macro for typecast.
      34              :  */
      35              : #define td_typecast_to(td,itype,otype) do { \
      36              :     itype in_val = (td)->data._##itype; \
      37              :     otype out_val = (otype) in_val; \
      38              :     (td)->data._##otype = out_val; \
      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._##otype = out_val; \
      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              : 
      71              : /**
      72              :  * @brief Set tensor element data with given type.
      73              :  * @param td struct for tensor data
      74              :  * @param type tensor type
      75              :  * @param value pointer of tensor element value
      76              :  * @return TRUE if no error
      77              :  */
      78              : gboolean
      79      3785079 : gst_tensor_data_set (tensor_data_s * td, tensor_type type, gpointer value)
      80              : {
      81      3785079 :   g_return_val_if_fail (td != NULL, FALSE);
      82      3785079 :   g_return_val_if_fail (value != NULL, FALSE);
      83              : 
      84      3785079 :   td->data._int64_t = 0;
      85      3785079 :   td->type = _NNS_END;
      86              : 
      87      3785079 :   switch (type) {
      88          114 :     case _NNS_INT32:
      89          114 :       td_set_data (td, value, int32_t);
      90          114 :       break;
      91         5051 :     case _NNS_UINT32:
      92         5051 :       td_set_data (td, value, uint32_t);
      93         5051 :       break;
      94           16 :     case _NNS_INT16:
      95           16 :       td_set_data (td, value, int16_t);
      96           16 :       break;
      97           24 :     case _NNS_UINT16:
      98           24 :       td_set_data (td, value, uint16_t);
      99           24 :       break;
     100         5016 :     case _NNS_INT8:
     101         5016 :       td_set_data (td, value, int8_t);
     102         5016 :       break;
     103      2868606 :     case _NNS_UINT8:
     104      2868606 :       td_set_data (td, value, uint8_t);
     105      2868606 :       break;
     106       686143 :     case _NNS_FLOAT64:
     107       686143 :       td_set_data (td, value, double);
     108       686143 :       break;
     109       220056 :     case _NNS_FLOAT32:
     110       220056 :       td_set_data (td, value, float);
     111       220056 :       break;
     112            0 :     case _NNS_FLOAT16:
     113              : #ifdef FLOAT16_SUPPORT
     114              :       td_set_data (td, value, float16);
     115              :       break;
     116              : #else
     117            0 :       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            0 :       return FALSE;
     120              : #endif
     121           37 :     case _NNS_INT64:
     122           37 :       td_set_data (td, value, int64_t);
     123           37 :       break;
     124           16 :     case _NNS_UINT64:
     125           16 :       td_set_data (td, value, uint64_t);
     126           16 :       break;
     127            0 :     default:
     128            0 :       nns_logw ("Unknown tensor type %d", type);
     129            0 :       return FALSE;
     130              :   }
     131              : 
     132      3785079 :   td->type = type;
     133      3785079 :   return TRUE;
     134              : }
     135              : 
     136              : /**
     137              :  * @brief Get tensor element value.
     138              :  * @param td struct for tensor data
     139              :  * @param value pointer of tensor element value
     140              :  * @return TRUE if no error
     141              :  */
     142              : gboolean
     143      3784930 : gst_tensor_data_get (tensor_data_s * td, gpointer value)
     144              : {
     145      3784930 :   g_return_val_if_fail (td != NULL, FALSE);
     146      3784930 :   g_return_val_if_fail (value != NULL, FALSE);
     147              : 
     148      3784930 :   switch (td->type) {
     149        15390 :     case _NNS_INT32:
     150        15390 :       td_get_data (td, value, int32_t);
     151        15390 :       break;
     152        20434 :     case _NNS_UINT32:
     153        20434 :       td_get_data (td, value, uint32_t);
     154        20434 :       break;
     155        15375 :     case _NNS_INT16:
     156        15375 :       td_get_data (td, value, int16_t);
     157        15375 :       break;
     158        15375 :     case _NNS_UINT16:
     159        15375 :       td_get_data (td, value, uint16_t);
     160        15375 :       break;
     161        20375 :     case _NNS_INT8:
     162        20375 :       td_get_data (td, value, int8_t);
     163        20375 :       break;
     164       591375 :     case _NNS_UINT8:
     165       591375 :       td_get_data (td, value, uint8_t);
     166       591375 :       break;
     167      2975741 :     case _NNS_FLOAT64:
     168      2975741 :       td_get_data (td, value, double);
     169      2975741 :       break;
     170       100115 :     case _NNS_FLOAT32:
     171       100115 :       td_get_data (td, value, float);
     172       100115 :       break;
     173            0 :     case _NNS_FLOAT16:
     174              : #ifdef FLOAT16_SUPPORT
     175              :       td_get_data (td, value, float16);
     176              :       break;
     177              : #else
     178            0 :       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            0 :       return FALSE;
     181              : #endif
     182        15375 :     case _NNS_INT64:
     183        15375 :       td_get_data (td, value, int64_t);
     184        15375 :       break;
     185        15375 :     case _NNS_UINT64:
     186        15375 :       td_get_data (td, value, uint64_t);
     187        15375 :       break;
     188            0 :     default:
     189            0 :       nns_logw ("Unknown tensor type %d", td->type);
     190            0 :       return FALSE;
     191              :   }
     192              : 
     193      3784930 :   return TRUE;
     194              : }
     195              : 
     196              : /**
     197              :  * @brief Typecast tensor element data.
     198              :  * @param td struct for tensor data
     199              :  * @param type tensor type to be transformed
     200              :  * @return TRUE if no error
     201              :  */
     202              : gboolean
     203      3869638 : gst_tensor_data_typecast (tensor_data_s * td, tensor_type type)
     204              : {
     205              :   gboolean is_float;
     206              : 
     207      3869638 :   g_return_val_if_fail (td != NULL, FALSE);
     208              : 
     209              :   /* do nothing when transform to same type */
     210      3869638 :   if (td->type != type) {
     211      3549645 :     is_float = (td->type == _NNS_FLOAT32 || td->type == _NNS_FLOAT64
     212      7319320 :         || td->type == _NNS_FLOAT16);
     213              : 
     214      3769675 :     switch (type) {
     215        15419 :       case _NNS_INT32:
     216        15419 :         td_typecast (td, int32_t);
     217        15419 :         break;
     218        20418 :       case _NNS_UINT32:
     219        20418 :         if (is_float) {
     220         5015 :           td_typecast (td, int32_t);
     221         5015 :           td->type = _NNS_INT32;
     222              :         }
     223        20418 :         td_typecast (td, uint32_t);
     224        20418 :         break;
     225        15378 :       case _NNS_INT16:
     226        15378 :         td_typecast (td, int16_t);
     227        15378 :         break;
     228        15378 :       case _NNS_UINT16:
     229        15378 :         if (is_float) {
     230           15 :           td_typecast (td, int16_t);
     231           15 :           td->type = _NNS_INT16;
     232              :         }
     233        15378 :         td_typecast (td, uint16_t);
     234        15378 :         break;
     235        20378 :       case _NNS_INT8:
     236        20378 :         td_typecast (td, int8_t);
     237        20378 :         break;
     238       576078 :       case _NNS_UINT8:
     239       576078 :         if (is_float) {
     240       576031 :           td_typecast (td, int8_t);
     241       576031 :           td->type = _NNS_INT8;
     242              :         }
     243       576078 :         td_typecast (td, uint8_t);
     244       576078 :         break;
     245      2975728 :       case _NNS_FLOAT64:
     246      2975728 :         td_typecast (td, double);
     247      2975728 :         break;
     248       100145 :       case _NNS_FLOAT32:
     249       100145 :         td_typecast (td, float);
     250       100145 :         break;
     251            0 :       case _NNS_FLOAT16:
     252              : #ifdef FLOAT16_SUPPORT
     253              :         td_typecast (td, float16);
     254              : #else
     255            0 :         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            0 :         return FALSE;
     258              : #endif
     259              :         break;
     260        15375 :       case _NNS_INT64:
     261        15375 :         td_typecast (td, int64_t);
     262        15375 :         break;
     263        15378 :       case _NNS_UINT64:
     264        15378 :         if (is_float) {
     265           15 :           td_typecast (td, int64_t);
     266           15 :           td->type = _NNS_INT64;
     267              :         }
     268        15378 :         td_typecast (td, uint64_t);
     269        15378 :         break;
     270            0 :       default:
     271            0 :         nns_logw ("Unknown tensor type %d", type);
     272            0 :         return FALSE;
     273              :     }
     274              : 
     275      3769675 :     td->type = type;
     276              :   }
     277              : 
     278      3869638 :   return TRUE;
     279              : }
     280              : 
     281              : /**
     282              :  * @brief Typecast tensor element value.
     283              :  * @param input pointer of input tensor data
     284              :  * @param in_type input tensor type
     285              :  * @param output pointer of output tensor data
     286              :  * @param out_type output tensor type
     287              :  * @return TRUE if no error
     288              :  */
     289              : gboolean
     290      3723390 : 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      7446780 :   g_return_val_if_fail (input != NULL, FALSE);
     296      3723390 :   g_return_val_if_fail (output != NULL, FALSE);
     297      3723390 :   g_return_val_if_fail (in_type != _NNS_END, FALSE);
     298      3723390 :   g_return_val_if_fail (out_type != _NNS_END, FALSE);
     299              : 
     300      3723390 :   gst_tensor_data_set (&td, in_type, input);
     301      3723390 :   gst_tensor_data_typecast (&td, out_type);
     302      3723390 :   gst_tensor_data_get (&td, output);
     303      3723390 :   return TRUE;
     304              : }
     305              : 
     306              : /**
     307              :  * @brief Calculate average value of the tensor.
     308              :  * @param raw pointer of raw tensor data
     309              :  * @param length byte size of raw tensor data
     310              :  * @param type tensor type
     311              :  * @param result double pointer for average value of given tensor. Caller should release allocated memory.
     312              :  * @return TRUE if no error
     313              :  */
     314              : gboolean
     315           26 : 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           52 :   g_return_val_if_fail (raw != NULL, FALSE);
     324           26 :   g_return_val_if_fail (length > 0, FALSE);
     325           26 :   g_return_val_if_fail (type != _NNS_END, FALSE);
     326              : 
     327           26 :   element_size = gst_tensor_get_element_size (type);
     328           26 :   num = length / element_size;
     329              : 
     330           26 :   average = 0.0;
     331           26 :   *result = (gdouble *) g_try_malloc0 (sizeof (gdouble));
     332           26 :   if (*result == NULL) {
     333            0 :     nns_loge ("Failed to allocate memory for calculating average");
     334            0 :     return FALSE;
     335              :   }
     336              : 
     337      2209722 :   for (i = 0; i < num; ++i) {
     338              :     /* extract value and typecast to double */
     339      2209696 :     data = (guint8 *) raw + element_size * i;
     340      2209696 :     gst_tensor_data_raw_typecast (data, type, &value, _NNS_FLOAT64);
     341              : 
     342      2209696 :     average = (value - average) / (i + 1) + average;
     343              :   }
     344              : 
     345           26 :   **result = average;
     346              : 
     347           26 :   return TRUE;
     348              : }
     349              : 
     350              : /**
     351              :  * @brief Calculate average value of the tensor per channel (the first dim).
     352              :  * @param raw pointer of raw tensor data
     353              :  * @param length byte size of raw tensor data
     354              :  * @param type tensor type
     355              :  * @param tensor_dim tensor dimension
     356              :  * @param results double array contains average values of each channel. Caller should release allocated array.
     357              :  * @return TRUE if no error
     358              :  */
     359              : gboolean
     360            8 : 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           16 :   g_return_val_if_fail (raw != NULL, FALSE);
     369            8 :   g_return_val_if_fail (length > 0, FALSE);
     370            8 :   g_return_val_if_fail (dim[0] > 0, FALSE);
     371            8 :   g_return_val_if_fail (type != _NNS_END, FALSE);
     372              : 
     373            8 :   element_size = gst_tensor_get_element_size (type);
     374            8 :   num = length / element_size;
     375              : 
     376            8 :   offset = dim[0];
     377            8 :   num = num / offset;
     378            8 :   *results = (gdouble *) g_try_malloc0 (sizeof (gdouble) * offset);
     379            8 :   if (*results == NULL) {
     380            0 :     nns_loge ("Failed to allocate memory for calculating average");
     381            0 :     return FALSE;
     382              :   }
     383              : 
     384          408 :   for (ch = 0; ch < offset; ++ch) {
     385          400 :     average = 0.0;
     386        40400 :     for (i = 0; i < num; ++i) {
     387              :       /* extract value and typecast to double */
     388        40000 :       data = (guint8 *) raw + element_size * ((i * offset) + ch);
     389        40000 :       gst_tensor_data_raw_typecast (data, type, &value, _NNS_FLOAT64);
     390        40000 :       average = (value - average) / (i + 1) + average;
     391              :     }
     392              : 
     393          400 :     (*results)[ch] = average;
     394              :   }
     395              : 
     396            8 :   return TRUE;
     397              : }
     398              : 
     399              : /**
     400              :  * @brief Calculate standard deviation of the tensor.
     401              :  * @param raw pointer of raw tensor data
     402              :  * @param length byte size of raw tensor data
     403              :  * @param type tensor type
     404              :  * @param average average value of given tensor
     405              :  * @param result double pointer for standard deviation of given tensor. Caller should release allocated memory.
     406              :  * @return TRUE if no error
     407              :  */
     408              : gboolean
     409            4 : 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            8 :   g_return_val_if_fail (raw != NULL, FALSE);
     418            4 :   g_return_val_if_fail (length > 0, FALSE);
     419            4 :   g_return_val_if_fail (type != _NNS_END, FALSE);
     420              : 
     421            4 :   element_size = gst_tensor_get_element_size (type);
     422            4 :   num = length / element_size;
     423            4 :   *result = (gdouble *) g_try_malloc0 (sizeof (gdouble));
     424            4 :   if (*result == NULL) {
     425            0 :     nns_loge ("Failed to allocate memory for calculating standard deviation");
     426            0 :     return FALSE;
     427              :   }
     428              : 
     429            4 :   std = 0.0;
     430        20004 :   for (i = 0; i < num; ++i) {
     431              :     /* extract value and typecast to double */
     432        20000 :     data = (guint8 *) raw + element_size * i;
     433        20000 :     gst_tensor_data_raw_typecast (data, type, &value, _NNS_FLOAT64);
     434              : 
     435        20000 :     std += pow (value - *average, 2) / num;
     436              :   }
     437              : 
     438            4 :   std = (std != 0.0) ? sqrt (std) : (1e-10);
     439            4 :   **result = std;
     440              : 
     441            4 :   return TRUE;
     442              : }
     443              : 
     444              : /**
     445              :  * @brief Calculate standard deviation of the tensor per channel (the first dim).
     446              :  * @param raw pointer of raw tensor data
     447              :  * @param length byte size of raw tensor data
     448              :  * @param type tensor type
     449              :  * @param tensor_dim tensor dimension
     450              :  * @param averages average values of given tensor per-channel
     451              :  * @param results double array contains standard deviation of each channel. Caller should release allocated array.
     452              :  * @return TRUE if no error
     453              :  */
     454              : gboolean
     455            4 : 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            8 :   g_return_val_if_fail (raw != NULL, FALSE);
     464            4 :   g_return_val_if_fail (length > 0, FALSE);
     465            4 :   g_return_val_if_fail (dim[0] > 0, FALSE);
     466            4 :   g_return_val_if_fail (type != _NNS_END, FALSE);
     467              : 
     468            4 :   element_size = gst_tensor_get_element_size (type);
     469            4 :   num = length / element_size;
     470              : 
     471            4 :   offset = dim[0];
     472            4 :   num = num / offset;
     473            4 :   *results = (gdouble *) g_try_malloc0 (sizeof (gdouble) * offset);
     474            4 :   if (*results == NULL) {
     475            0 :     nns_loge ("Failed to allocate memory for calculating standard deviation");
     476            0 :     return FALSE;
     477              :   }
     478              : 
     479          204 :   for (ch = 0; ch < offset; ++ch) {
     480          200 :     std = 0.0;
     481        20200 :     for (i = 0; i < num; ++i) {
     482              :       /* extract value and typecast to double */
     483        20000 :       data = (guint8 *) raw + element_size * ((i * offset) + ch);
     484        20000 :       gst_tensor_data_raw_typecast (data, type, &value, _NNS_FLOAT64);
     485        20000 :       std += pow (value - averages[ch], 2) / num;
     486              :     }
     487              : 
     488          200 :     std = (std != 0.0) ? sqrt (std) : (1e-10);
     489          200 :     (*results)[ch] = std;
     490              :   }
     491              : 
     492            4 :   return TRUE;
     493              : }
        

Generated by: LCOV version 2.0-1