Sparsetodense
=================

将稀疏张量转换为密集张量。该算子根据稀疏索引和值，将稀疏元素填充到密集张量的对应位置。支持标量值模式（所有位置使用相同的值）和向量值模式（每个索引对应不同的值）。

对于每个稀疏元素，根据其索引计算在密集张量中的线性位置，根据 `is_scalar` 标志，将对应的稀疏值写入密集张量的对应位置

.. math::

    \text{output}[\text{index}] = \begin{cases}
        \text{sparse\_values}[0], & \text{if } \text{is\_scalar} = 1 \\
        \text{sparse\_values}[i], & \text{if } \text{is\_scalar} = 0
    \end{cases}

输入：
    - **indices_vec** - 稀疏张量的索引数组，大小为 `sparse_length * 4`，每4个连续的int值表示一个稀疏元素在4维密集张量中的位置坐标 `[dim0, dim1, dim2, dim3]`。
    - **sparse_values** - 稀疏张量的值数组。如果 `is_scalar = 1`，只需要 `sparse_values[0]` 有效；如果 `is_scalar = 0`，需要 `sparse_length` 个值。
    - **output_strides** - 输出密集张量的步长数组，大小为4，用于将多维索引转换为线性索引。`output_strides[0]`, `output_strides[1]`, `output_strides[2]` 对应前3维的步长，第4维的步长为1。
    - **sparse_length** - 稀疏张量中非零元素的数量。
    - **is_scalar** - 是否为标量值标志。1 表示所有稀疏元素使用相同的值（`sparse_values[0]`），0 表示每个索引对应不同的值。
    - **core_mask** - 核掩码（仅共享存储版本需要）。

输出：
    - **output** - 输出密集张量的数据数组。输出数组的大小由 `output_strides` 和最大索引值确定。未在 `indices_vec` 中指定的位置保持原值（调用前需要初始化）。

支持平台：
    ``FT78NE``
    ``MT7004``

.. note::
    - FT78NE 支持fp32, int8, int16, int32, fp64, cplx64, cplx128
    - MT7004 支持fp16, fp32, int16, int32, cplx64

**共享存储版本:**

.. c:function:: void i8_sparsetodense_s(int* indices_vec, int8_t* sparse_values, int8_t* output, int* output_strides, int sparse_length, int is_scalar, int core_mask)
.. c:function:: void i16_sparsetodense_s(int* indices_vec, int16_t* sparse_values, int16_t* output, int* output_strides, int sparse_length, int is_scalar, int core_mask)
.. c:function:: void i32_sparsetodense_s(int* indices_vec, int32_t* sparse_values, int32_t* output, int* output_strides, int sparse_length, int is_scalar, int core_mask)
.. c:function:: void hp_sparsetodense_s(int* indices_vec, half* sparse_values, half* output, int* output_strides, int sparse_length, int is_scalar, int core_mask)
.. c:function:: void fp_sparsetodense_s(int* indices_vec, float* sparse_values, float* output, int* output_strides, int sparse_length, int is_scalar, int core_mask)
.. c:function:: void dp_sparsetodense_s(int* indices_vec, double* sparse_values, double* output, int* output_strides, int sparse_length, int is_scalar, int core_mask)
.. c:function:: void c64_sparsetodense_s(int* indices_vec, float* sparse_values, float* output, int* output_strides, int sparse_length, int is_scalar, int core_mask)
.. c:function:: void c128_sparsetodense_s(int* indices_vec, double* sparse_values, double* output, int* output_strides, int sparse_length, int is_scalar, int core_mask)

**C调用示例（向量值模式）：**

.. code-block:: c
    :linenos:
    :emphasize-lines: 40-41

    //FT78NE示例
    #include <stdio.h>
    #include <sparsetodense.h>

    int main(int argc, char* argv[]) {
        // 假设在DDR空间
        // 输出密集张量形状 [2, 3, 4, 5]
        int output_shape[] = {2, 3, 4, 5};
        
        // 计算步长：stride0 = 3*4*5 = 60, stride1 = 4*5 = 20, stride2 = 5, stride3 = 1
        int output_strides[4];
        output_strides[0] = 3 * 4 * 5;  // 60
        output_strides[1] = 4 * 5;      // 20
        output_strides[2] = 5;          // 5
        output_strides[3] = 1;          // 第4维步长为1（未使用）
        
        // 稀疏元素：3个非零元素
        int sparse_length = 3;
        
        // 索引：[[0,0,0,0], [0,1,2,3], [1,2,3,4]]
        int *indices_vec = (int *)0xA0000000;
        indices_vec[0] = 0; indices_vec[1] = 0; indices_vec[2] = 0; indices_vec[3] = 0;  // 位置(0,0,0,0)
        indices_vec[4] = 0; indices_vec[5] = 1; indices_vec[6] = 2; indices_vec[7] = 3;  // 位置(0,1,2,3)
        indices_vec[8] = 1; indices_vec[9] = 2; indices_vec[10] = 3; indices_vec[11] = 4; // 位置(1,2,3,4)
        
        // 稀疏值：每个索引对应不同的值
        float *sparse_values = (float *)0xA1000000;
        sparse_values[0] = 1.0f;
        sparse_values[1] = 2.0f;
        sparse_values[2] = 3.0f;
        
        // 输出密集张量（需要预先初始化为0或默认值）
        float *output = (float *)0xB0000000;
        int output_size = 2 * 3 * 4 * 5;  // 120
        memset(output, 0, output_size * sizeof(float));
        
        int is_scalar = 0;  // 向量值模式
        int core_mask = 0xff;
        
        fp_sparsetodense_s(indices_vec, sparse_values, output, output_strides,
                          sparse_length, is_scalar, core_mask);
        
        return 0;
    }

**C调用示例（标量值模式）：**

.. code-block:: c
    :linenos:
    :emphasize-lines: 32-33

    //FT78NE示例
    #include <stdio.h>
    #include <sparsetodense.h>

    int main(int argc, char* argv[]) {
        // 假设在DDR空间
        int output_strides[4];
        output_strides[0] = 3 * 4 * 5;  // 60
        output_strides[1] = 4 * 5;       // 20
        output_strides[2] = 5;           // 5
        output_strides[3] = 1;
        
        int sparse_length = 3;
        
        // 索引：[[0,0,0,0], [0,1,2,3], [1,2,3,4]]
        int *indices_vec = (int *)0xA0000000;
        indices_vec[0] = 0; indices_vec[1] = 0; indices_vec[2] = 0; indices_vec[3] = 0;
        indices_vec[4] = 0; indices_vec[5] = 1; indices_vec[6] = 2; indices_vec[7] = 3;
        indices_vec[8] = 1; indices_vec[9] = 2; indices_vec[10] = 3; indices_vec[11] = 4;
        
        // 所有位置使用相同的值
        float *sparse_values = (float *)0xA1000000;
        sparse_values[0] = 5.0f;  // 只有这个值会被使用
        
        float *output = (float *)0xB0000000;
        int output_size = 2 * 3 * 4 * 5;
        memset(output, 0, output_size * sizeof(float));
        
        int is_scalar = 1;  // 标量值模式
        int core_mask = 0xff;
        
        fp_sparsetodense_s(indices_vec, sparse_values, output, output_strides,
                          sparse_length, is_scalar, core_mask);
        
        return 0;
    }

**私有存储版本:**

.. c:function:: void i8_sparsetodense_p(int* indices_vec, int8_t* sparse_values, int8_t* output, int* output_strides, int sparse_length, int is_scalar)
.. c:function:: void i16_sparsetodense_p(int* indices_vec, int16_t* sparse_values, int16_t* output, int* output_strides, int sparse_length, int is_scalar)
.. c:function:: void i32_sparsetodense_p(int* indices_vec, int32_t* sparse_values, int32_t* output, int* output_strides, int sparse_length, int is_scalar)
.. c:function:: void hp_sparsetodense_p(int* indices_vec, half* sparse_values, half* output, int* output_strides, int sparse_length, int is_scalar)
.. c:function:: void fp_sparsetodense_p(int* indices_vec, float* sparse_values, float* output, int* output_strides, int sparse_length, int is_scalar)
.. c:function:: void dp_sparsetodense_p(int* indices_vec, double* sparse_values, double* output, int* output_strides, int sparse_length, int is_scalar)
.. c:function:: void c64_sparsetodense_p(int* indices_vec, float* sparse_values, float* output, int* output_strides, int sparse_length, int is_scalar)
.. c:function:: void c128_sparsetodense_p(int* indices_vec, double* sparse_values, double* output, int* output_strides, int sparse_length, int is_scalar)

**C调用示例（私有存储版本）：**

.. code-block:: c
    :linenos:
    :emphasize-lines: 31-32

    //FT78NE示例
    #include <stdio.h>
    #include <sparsetodense.h>

    int main(int argc, char* argv[]) {
        // 假设在L2空间
        int output_strides[4];
        output_strides[0] = 3 * 4 * 5;  // 60
        output_strides[1] = 4 * 5;      // 20
        output_strides[2] = 5;          // 5
        output_strides[3] = 1;
        
        int sparse_length = 3;
        
        int *indices_vec = (int *)0x10000000;
        indices_vec[0] = 0; indices_vec[1] = 0; indices_vec[2] = 0; indices_vec[3] = 0;
        indices_vec[4] = 0; indices_vec[5] = 1; indices_vec[6] = 2; indices_vec[7] = 3;
        indices_vec[8] = 1; indices_vec[9] = 2; indices_vec[10] = 3; indices_vec[11] = 4;
        
        float *sparse_values = (float *)0x10001000;
        sparse_values[0] = 1.0f;
        sparse_values[1] = 2.0f;
        sparse_values[2] = 3.0f;
        
        float *output = (float *)0x10002000;
        int output_size = 2 * 3 * 4 * 5;
        memset(output, 0, output_size * sizeof(float));
        
        int is_scalar = 0;
        
        fp_sparsetodense_p(indices_vec, sparse_values, output, output_strides,
                          sparse_length, is_scalar);
        
        return 0;
    }

