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` 个元素表示一个非零元素的索引。
    - **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 sparsereshape_s(int* in_indices_ptr, int* in_inshape_ptr, int* in_outshape_ptr, int* out_indices_ptr, int* out_outshape_ptr, int input_rank, int output_rank, int N, int* in_stride, int* out_stride, int core_mask)

**C调用示例：**

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

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

    int main(int argc, char* argv[]) {
        // 假设在DDR空间
        int N = 3;  // 有3个非零元素
        int input_rank = 2;  // 输入是2维
        int output_rank = 2;  // 输出也是2维
        
        // 输入形状 [2, 3]，输出形状 [3, 2]
        int in_inshape[] = {2, 3};
        int in_outshape[] = {3, 2};
        int out_outshape[] = {3, 2};  // 应该和 in_outshape 一致
        
        // 输入索引：[[0,0], [0,1], [1,2]]
        int *in_indices_ptr = (int *)0xA0000000;
        in_indices_ptr[0] = 0; in_indices_ptr[1] = 0;  // 第一个元素在位置(0,0)
        in_indices_ptr[2] = 0; in_indices_ptr[3] = 1;  // 第二个元素在位置(0,1)
        in_indices_ptr[4] = 1; in_indices_ptr[5] = 2;  // 第三个元素在位置(1,2)
        
        // 输出索引（待填充）
        int *out_indices_ptr = (int *)0xB0000000;
        
        // 临时空间：步长数组
        int *in_stride = (int *)0xC0000000;   // 大小为 input_rank
        int *out_stride = (int *)0xC0100000;  // 大小为 output_rank
        
        int core_mask = 0xff;
        
        sparsereshape_s(in_indices_ptr, in_inshape, in_outshape, out_indices_ptr,
                       out_outshape, input_rank, output_rank, N, in_stride,
                       out_stride, core_mask);
        
        return 0;
    }

**私有存储版本:**

.. c:function:: void sparsereshape_p(int* in_indices_ptr, int* in_inshape_ptr, int* in_outshape_ptr, int* out_indices_ptr, int* out_outshape_ptr, int input_rank, int output_rank, int N, int* in_stride, int* out_stride)

**C调用示例：**

.. code-block:: c
    :linenos:
    :emphasize-lines: 24-26

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

    int main(int argc, char* argv[]) {
        // 假设在L2空间
        int N = 3;
        int input_rank = 2;
        int output_rank = 2;
        
        int in_inshape[] = {2, 3};
        int in_outshape[] = {3, 2};
        int out_outshape[] = {3, 2};
        
        int *in_indices_ptr = (int *)0x10000000;
        in_indices_ptr[0] = 0; in_indices_ptr[1] = 0;
        in_indices_ptr[2] = 0; in_indices_ptr[3] = 1;
        in_indices_ptr[4] = 1; in_indices_ptr[5] = 2;
        
        int *out_indices_ptr = (int *)0x10001000;
        int *in_stride = (int *)0x10002000;
        int *out_stride = (int *)0x10003000;
        
        sparsereshape_p(in_indices_ptr, in_inshape, in_outshape, out_indices_ptr,
                       out_outshape, input_rank, output_rank, N, in_stride,
                       out_stride);
        
        return 0;
    }