LCOV - code coverage report
Current view: top level - nnstreamer-2.4.2/gst/nnstreamer/elements - gsttensor_sparseutil.c (source / functions) Coverage Total Hit
Test: nnstreamer 2.4.2-0 nnstreamer/nnstreamer#eca68b8d050408568af95d831a8eef62aaee7784 Lines: 91.6 % 154 141
Test Date: 2025-03-14 05:36:58 Functions: 100.0 % 2 2

            Line data    Source code
       1              : /* SPDX-License-Identifier: LGPL-2.1-only */
       2              : /**
       3              :  * GStreamer / NNStreamer Sparse Tensor support
       4              :  * Copyright (C) 2021 Yongjoo Ahn <yongjoo1.ahn@samsung.com>
       5              :  */
       6              : /**
       7              :  * @file        gsttensor_sparseutil.c
       8              :  * @date        27 Jul 2021
       9              :  * @brief       Util functions for tensor_sparse encoder and decoder.
      10              :  * @see         https://github.com/nnstreamer/nnstreamer
      11              :  * @author      Yongjoo Ahn <yongjoo1.ahn@samsung.com>
      12              :  * @bug         No known bugs except for NYI items
      13              :  */
      14              : 
      15              : #include <string.h>
      16              : #include <tensor_common.h>
      17              : #include <tensor_data.h>
      18              : #include "gsttensor_sparseutil.h"
      19              : 
      20              : /**
      21              :  * @brief Make dense tensor with input sparse tensor.
      22              :  * @param[in,out] meta tensor meta structure to be updated
      23              :  * @param[in] mem gst-memory of sparse tensor data
      24              :  * @return pointer of GstMemory with dense tensor data or NULL on error. Caller should handle this newly allocated memory.
      25              :  */
      26              : GstMemory *
      27           36 : gst_tensor_sparse_to_dense (GstTensorMetaInfo * meta, GstMemory * mem)
      28              : {
      29           36 :   GstMemory *dense = NULL;
      30              :   GstMapInfo map;
      31              :   guint i, nnz;
      32              :   guint8 *output, *input;
      33              :   guint *indices;
      34              :   gsize output_size, element_size;
      35              : 
      36           36 :   if (!gst_memory_map (mem, &map, GST_MAP_READ)) {
      37            0 :     nns_loge ("Failed to map given memory");
      38           36 :     return NULL;
      39              :   }
      40              : 
      41           36 :   if (!gst_tensor_meta_info_parse_header (meta, map.data)) {
      42            1 :     nns_loge ("Failed to parse meta info from given memory");
      43            1 :     goto done;
      44              :   }
      45              : 
      46           35 :   meta->format = _NNS_TENSOR_FORMAT_STATIC;
      47              : 
      48           35 :   element_size = gst_tensor_get_element_size (meta->type);
      49           35 :   output_size = gst_tensor_meta_info_get_data_size (meta);
      50              : 
      51           35 :   if (element_size == 0 || output_size == 0) {
      52            0 :     nns_loge ("Got invalid meta info");
      53            0 :     goto done;
      54              :   }
      55              : 
      56           35 :   output = (guint8 *) g_malloc0 (output_size);
      57              : 
      58           35 :   nnz = meta->sparse_info.nnz;
      59           35 :   input = map.data + gst_tensor_meta_info_get_header_size (meta);
      60           35 :   indices = (guint *) (input + element_size * nnz);
      61              : 
      62         1498 :   for (i = 0; i < nnz; ++i) {
      63         1463 :     switch (meta->type) {
      64            6 :       case _NNS_INT32:
      65            6 :         ((int32_t *) output)[indices[i]] = ((int32_t *) input)[i];
      66            6 :         break;
      67            6 :       case _NNS_UINT32:
      68            6 :         ((uint32_t *) output)[indices[i]] = ((uint32_t *) input)[i];
      69            6 :         break;
      70            6 :       case _NNS_INT16:
      71            6 :         ((int16_t *) output)[indices[i]] = ((int16_t *) input)[i];
      72            6 :         break;
      73            6 :       case _NNS_UINT16:
      74            6 :         ((uint16_t *) output)[indices[i]] = ((uint16_t *) input)[i];
      75            6 :         break;
      76            6 :       case _NNS_INT8:
      77            6 :         ((int8_t *) output)[indices[i]] = ((int8_t *) input)[i];
      78            6 :         break;
      79           18 :       case _NNS_UINT8:
      80           18 :         ((uint8_t *) output)[indices[i]] = ((uint8_t *) input)[i];
      81           18 :         break;
      82            6 :       case _NNS_FLOAT64:
      83            6 :         ((double *) output)[indices[i]] = ((double *) input)[i];
      84            6 :         break;
      85         1397 :       case _NNS_FLOAT32:
      86         1397 :         ((float *) output)[indices[i]] = ((float *) input)[i];
      87         1397 :         break;
      88            6 :       case _NNS_INT64:
      89            6 :         ((int64_t *) output)[indices[i]] = ((int64_t *) input)[i];
      90            6 :         break;
      91            6 :       case _NNS_UINT64:
      92            6 :         ((uint64_t *) output)[indices[i]] = ((uint64_t *) input)[i];
      93            6 :         break;
      94            0 :       default:
      95            0 :         nns_loge ("Error occurred during get tensor value");
      96            0 :         g_free (output);
      97            0 :         goto done;
      98              :     }
      99              :   }
     100              : 
     101           35 :   dense = gst_memory_new_wrapped (0, output, output_size, 0, output_size,
     102              :       output, g_free);
     103              : 
     104           36 : done:
     105           36 :   gst_memory_unmap (mem, &map);
     106           36 :   return dense;
     107              : }
     108              : 
     109              : /**
     110              :  * @brief Make sparse tensor with input dense tensor.
     111              :  * @param[in,out] meta tensor meta structure to be updated
     112              :  * @param[in] mem gst-memory of dense tensor data
     113              :  * @return pointer of GstMemory with sparse tensor data or NULL on error. Caller should handle this newly allocated memory.
     114              :  */
     115              : GstMemory *
     116           77 : gst_tensor_sparse_from_dense (GstTensorMetaInfo * meta, GstMemory * mem)
     117              : {
     118           77 :   GstMemory *sparse = NULL;
     119              :   GstMapInfo map;
     120           77 :   guint i, nnz = 0;
     121              :   guint8 *output;
     122              :   tensor_type data_type;
     123              :   void *values;
     124              :   guint *indices;
     125              :   gsize output_size, header_size, element_size;
     126              :   gulong element_count;
     127              : 
     128           77 :   if (!gst_memory_map (mem, &map, GST_MAP_READ)) {
     129            0 :     nns_loge ("Failed to map given memory");
     130           77 :     return NULL;
     131              :   }
     132              : 
     133           77 :   header_size = gst_tensor_meta_info_get_header_size (meta);
     134           77 :   element_size = gst_tensor_get_element_size (meta->type);
     135           77 :   element_count = gst_tensor_get_element_count (meta->dimension);
     136              : 
     137           77 :   if (element_size == 0 || element_count == 0) {
     138            1 :     nns_loge ("Got invalid meta info");
     139            1 :     goto done;
     140              :   }
     141              : 
     142              :   /** alloc maximum possible size of memory */
     143           76 :   values = g_malloc0 (element_size * element_count);
     144           76 :   indices = g_malloc0 (sizeof (guint) * element_count);
     145              : 
     146           76 :   data_type = meta->type;
     147              : 
     148              :   /** Consider using macro to reduce loc and readability */
     149        24381 :   for (i = 0; i < element_count; ++i) {
     150        24305 :     switch (data_type) {
     151           40 :       case _NNS_INT32:
     152           40 :         if (((int32_t *) map.data)[i] != 0) {
     153            6 :           ((int32_t *) values)[nnz] = ((int32_t *) map.data)[i];
     154            6 :           indices[nnz] = i;
     155            6 :           nnz += 1;
     156              :         }
     157           40 :         break;
     158           40 :       case _NNS_UINT32:
     159           40 :         if (((uint32_t *) map.data)[i] != 0) {
     160            6 :           ((uint32_t *) values)[nnz] = ((uint32_t *) map.data)[i];
     161            6 :           indices[nnz] = i;
     162            6 :           nnz += 1;
     163              :         }
     164           40 :         break;
     165           40 :       case _NNS_INT16:
     166           40 :         if (((int16_t *) map.data)[i] != 0) {
     167            6 :           ((int16_t *) values)[nnz] = ((int16_t *) map.data)[i];
     168            6 :           indices[nnz] = i;
     169            6 :           nnz += 1;
     170              :         }
     171           40 :         break;
     172           40 :       case _NNS_UINT16:
     173           40 :         if (((uint16_t *) map.data)[i] != 0) {
     174            6 :           ((uint16_t *) values)[nnz] = ((uint16_t *) map.data)[i];
     175            6 :           indices[nnz] = i;
     176            6 :           nnz += 1;
     177              :         }
     178           40 :         break;
     179           40 :       case _NNS_INT8:
     180           40 :         if (((int8_t *) map.data)[i] != 0) {
     181            6 :           ((int8_t *) values)[nnz] = ((int8_t *) map.data)[i];
     182            6 :           indices[nnz] = i;
     183            6 :           nnz += 1;
     184              :         }
     185           40 :         break;
     186          100 :       case _NNS_UINT8:
     187          100 :         if (((uint8_t *) map.data)[i] != 0) {
     188           23 :           ((uint8_t *) values)[nnz] = ((uint8_t *) map.data)[i];
     189           23 :           indices[nnz] = i;
     190           23 :           nnz += 1;
     191              :         }
     192          100 :         break;
     193           40 :       case _NNS_FLOAT64:
     194           40 :         if (((double *) map.data)[i] != 0) {
     195            6 :           ((double *) values)[nnz] = ((double *) map.data)[i];
     196            6 :           indices[nnz] = i;
     197            6 :           nnz += 1;
     198              :         }
     199           40 :         break;
     200        23885 :       case _NNS_FLOAT32:
     201        23885 :         if (((float *) map.data)[i] != 0) {
     202         4175 :           ((float *) values)[nnz] = ((float *) map.data)[i];
     203         4175 :           indices[nnz] = i;
     204         4175 :           nnz += 1;
     205              :         }
     206        23885 :         break;
     207           40 :       case _NNS_INT64:
     208           40 :         if (((int64_t *) map.data)[i] != 0) {
     209            6 :           ((int64_t *) values)[nnz] = ((int64_t *) map.data)[i];
     210            6 :           indices[nnz] = i;
     211            6 :           nnz += 1;
     212              :         }
     213           40 :         break;
     214           40 :       case _NNS_UINT64:
     215           40 :         if (((uint64_t *) map.data)[i] != 0) {
     216            6 :           ((uint64_t *) values)[nnz] = ((uint64_t *) map.data)[i];
     217            6 :           indices[nnz] = i;
     218            6 :           nnz += 1;
     219              :         }
     220           40 :         break;
     221            0 :       default:
     222            0 :         nns_loge ("Error occurred during get tensor value");
     223            0 :         g_free (values);
     224            0 :         g_free (indices);
     225            0 :         goto done;
     226              :     }
     227              :   }
     228              : 
     229              :   /** update meta nnz info */
     230           76 :   meta->format = _NNS_TENSOR_FORMAT_SPARSE;
     231           76 :   meta->sparse_info.nnz = nnz;
     232              : 
     233              :   /** write to output buffer */
     234           76 :   output_size = element_size * nnz + sizeof (guint) * nnz;
     235              : 
     236              :   /** add meta info header */
     237           76 :   output_size += header_size;
     238           76 :   output = g_malloc0 (output_size);
     239              : 
     240           76 :   gst_tensor_meta_info_update_header (meta, output);
     241              : 
     242           76 :   memcpy (output + header_size, values, element_size * nnz);
     243           76 :   memcpy (output + header_size + (element_size * nnz),
     244              :       indices, sizeof (guint) * nnz);
     245              : 
     246           76 :   g_free (values);
     247           76 :   g_free (indices);
     248              : 
     249           76 :   sparse = gst_memory_new_wrapped (0, output, output_size, 0, output_size,
     250              :       output, g_free);
     251              : 
     252           77 : done:
     253           77 :   gst_memory_unmap (mem, &map);
     254           77 :   return sparse;
     255              : }
        

Generated by: LCOV version 2.0-1