SparseReshape
===================

对稀疏张量进行形状重塑（Reshape）。该算子将稀疏张量的索引从输入形状转换到输出形状，不改变稀疏值本身，只更新索引。该算子不区分数据类型，只处理索引信息。


对于每个稀疏元素：
- 计算其在输入形状中的线性索引：
  
  :math:`\text{ori\_index} = \sum_{j=0}^{\text{input\_rank}-1} \text{in\_indices}[j] \times \text{in\_stride}[j]`

- 将线性索引转换为输出形状的多维索引：
  
  :math:`\text{out\_indices}[j] = \text{ori\_index} / \text{out\_stride}[j]`，然后 :math:`\text{ori\_index} = \text{ori\_index} \% \text{out\_stride}[j]`

输入：
    - **in_indices_ptr** - 输入稀疏张量的索引数组，大小为 `N * input\_rank`，每 `input\_rank` 个元素表示一个非零元素的索引。
    - **params** - 参数打包成数组：
        - **in_inshape_ptr** - 输入稀疏张量的形状数组，大小为 `input\_rank`，例如 `[2, 3]` 表示 2×3 的矩阵。
        - **in_outshape_ptr** - 目标输出形状数组，大小为 `output_rank`，例如 `[3, 2]` 表示要将形状转换为 3×2。
        - **out_outshape_ptr** - 输出形状数组，应该与 `in_outshape_ptr` 一致，大小为 `output_rank`。
        - **input_rank** - 输入稀疏张量的维度数。
        - **output_rank** - 输出稀疏张量的维度数。
        - **N** - 稀疏张量中非零元素的数量。
        - **in_stride** - 输入形状的步长数组（临时空间），大小为 `input_rank`，用于中间计算。 
        - **out_stride** - 输出形状的步长数组（临时空间），大小为 `output_rank`，用于中间计算。
    - **core_mask** - 核掩码（仅共享存储版本需要）。

输出：
    - **out_indices_ptr** - 转换后的索引数组，大小为 `N * output_rank`，每 `output_rank` 个元素表示一个非零元素在输出形状中的索引。

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

.. note::
    - FT78NE 支持fp32
    - MT7004 支持fp32

**共享存储版本:**

.. c:function:: void fp_sparse_reshape_s(int *in_indices_ptr, int *out_indices_ptr, long long *params, int core_mask);
.. c:function:: void hp_sparse_reshape_s(int *in_indices_ptr, int *out_indices_ptr, long long *params, int core_mask);
.. c:function:: void i32_sparse_reshape_s(int *in_indices_ptr, int *out_indices_ptr, long long *params, int core_mask);
.. c:function:: void i16_sparse_reshape_s(int *in_indices_ptr, int *out_indices_ptr, long long *params, int core_mask);
.. c:function:: void c64_sparse_reshape_s(int *in_indices_ptr, int *out_indices_ptr, long long *params, int core_mask);

**C调用示例：**

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

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

    int main(int argc, char* argv[]) {
        int *in_indices_ptr = (int *) 0x81000000; 
        int *out_indices_ptr = (int *)0x82000000; // 修改这里：原 0x10020000 -> 0x10030000
        int *in_stride = (int *)0x83000000; // 修改这里：顺延
        int *out_stride = (int *)0x84000000; // 修改这里：顺延
        
        int input_rank = 3; 
        int in_inshape_ptr[3] = {200, 30, 10}; 
    
        int output_rank = 2;
        int N = 8192; //元素个数
        int in_outshape_ptr[2] = {120, 500}; //注意保证和in_shape_ptr总元素个数相同
        int out_outshape_ptr[2] = {120, 500}; //注意保证和in_shape_ptr总元素个数相同

        srand(seed++);

        int i,j;
        for (i = 0; i < N; i++) {
            for(j = 0; j < input_rank; j++) {
                in_indices_ptr[i * input_rank + j] = rand() % in_inshape_ptr[j];
            }
        }
        
        //
        long long params[11];
        params[0] = (long long)in_inshape_ptr;
        params[1] = (long long)in_outshape_ptr;
        params[2] = (long long)out_outshape_ptr;
        params[3] = (long long)input_rank;
        params[4] = (long long)output_rank;
        params[5] = (long long)N;
        params[6] = (long long)in_stride;
        params[7] = (long long)out_stride;
        
        int core_mask = 0b1111;
        fp_sparse_reshape_s(in_indices_ptr, out_indices_ptr, params, core_mask);
        
        return 0;
    }

**私有存储版本:**

.. c:function:: void fp_sparse_reshape_p(int *in_indices_ptr, int *out_indices_ptr, long long *params);
.. c:function:: void hp_sparse_reshape_p(int *in_indices_ptr, int *out_indices_ptr, long long *params);
.. c:function:: void i32_sparse_reshape_p(int *in_indices_ptr, int *out_indices_ptr, long long *params);
.. c:function:: void i16_sparse_reshape_p(int *in_indices_ptr, int *out_indices_ptr, long long *params);
.. c:function:: void c64_sparse_reshape_p(int *in_indices_ptr, int *out_indices_ptr, long long *params);

**C调用示例：**

.. code-block:: c
    :linenos:
    :emphasize-lines: 39

    //FT04示例
    #include <stdio.h>
    #include <sparsereshape.h>

    int main(int argc, char* argv[]) {
        int *in_indices_ptr = (int *) 0x10010000; 
        int *out_indices_ptr = (int *)0x10030000; // 修改这里：原 0x10020000 -> 0x10030000
        int *in_stride = (int *)0x10050000; // 修改这里：顺延
        int *out_stride = (int *)0x10060000; // 修改这里：顺延
        
        int input_rank = 3; 
        int in_inshape_ptr[3] = {200, 30, 10}; 
    
        int output_rank = 2;
        int N = 8192; //元素个数
        int in_outshape_ptr[2] = {120, 500}; //注意保证和in_shape_ptr总元素个数相同
        int out_outshape_ptr[2] = {120, 500}; //注意保证和in_shape_ptr总元素个数相同

        srand(seed++);

        int i,j;
        for (i = 0; i < N; i++) {
            for(j = 0; j < input_rank; j++) {
                in_indices_ptr[i * input_rank + j] = rand() % in_inshape_ptr[j];
            }
        }
        
        //
        long long params[11];
        params[0] = (long long)in_inshape_ptr;
        params[1] = (long long)in_outshape_ptr;
        params[2] = (long long)out_outshape_ptr;
        params[3] = (long long)input_rank;
        params[4] = (long long)output_rank;
        params[5] = (long long)N;
        params[6] = (long long)in_stride;
        params[7] = (long long)out_stride;

        fp_sparse_reshape_p(in_indices_ptr, out_indices_ptr, params);
        
        return 0;
    }