TensorListStack
====================

将多个张量（Tensor）堆叠成一个更大的张量。此算子可以处理不同数据类型的张量，将它们按顺序拼接成一个连续的内存块。

.. math::

    \text{output\_data} = [\text{tensor}_1, \text{tensor}_2, \ldots, \text{tensor}_n]

其中每个张量的数据类型和元素数量可以不同。

输入：
    - **tensor_num** - 张量数量，tensor_num > 0
    - **tensor_element_nums** - 每个张量的元素数量（int* 类型）
    - **tensor_data_type** - 每个张量元素的数据类型，以字节数表示
    - **tensor_data** - 每个张量数据的起始地址（void** 类型）
    - **output_data** - 输出结果的数组起始位置（void* 类型）
    - **unknown_type_offset** - 未知类型数据在输出结果中的偏移量
    - **core_mask** - 核掩码（int），仅共享存储版本需要

输出：
    - **output_data** - 堆叠后的张量数据，按输入顺序连续存储

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

.. note::
    - FT78NE 支持 int8, int16, int32, fp32, fp64, cplx64, cplx128
    - MT7004 支持 fp16, fp32, int16, int32, cplx64
    - 该算子不区分具体的数据类型，数据类型信息通过tensor_data_type参数传递
    - 当tensor_data_type[i]为0（kTypeUnknown）时，算子会将输出内存清零
    - 当tensor_data_type[i]不为0时，算子会按字节复制数据
    - 调用前需要确保output_data指向的内存空间足够大以容纳所有张量数据
    - TensorList中不同的Tensor数据类型可能不同，类型信息已经在算子中包含

**共享存储版本：**

.. c:function:: void i8_tensorlist_stack_s(int tensor_num, int *tensor_element_nums, int *tensor_data_type, void **tensor_data, void *output_data, int unknown_type_offset, int core_mask)
.. c:function:: void i16_tensorlist_stack_s(int tensor_num, int *tensor_element_nums, int *tensor_data_type, void **tensor_data, void *output_data, int unknown_type_offset, int core_mask)
.. c:function:: void i32_tensorlist_stack_s(int tensor_num, int *tensor_element_nums, int *tensor_data_type, void **tensor_data, void *output_data, int unknown_type_offset, int core_mask)
.. c:function:: void hp_tensorlist_stack_s(int tensor_num, int *tensor_element_nums, int *tensor_data_type, void **tensor_data, void *output_data, int unknown_type_offset, int core_mask)
.. c:function:: void fp_tensorlist_stack_s(int tensor_num, int *tensor_element_nums, int *tensor_data_type, void **tensor_data, void *output_data, int unknown_type_offset, int core_mask)
.. c:function:: void dp_tensorlist_stack_s(int tensor_num, int *tensor_element_nums, int *tensor_data_type, void **tensor_data, void *output_data, int unknown_type_offset, int core_mask)
.. c:function:: void c64_tensorlist_stack_s(int tensor_num, int *tensor_element_nums, int *tensor_data_type, void **tensor_data, void *output_data, int unknown_type_offset, int core_mask)
.. c:function:: void c128_tensorlist_stack_s(int tensor_num, int *tensor_element_nums, int *tensor_data_type, void **tensor_data, void *output_data, int unknown_type_offset, int core_mask)

**C调用示例（共享存储版本）：**

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

    //FT78NE示例
    #include <stdio.h>
    #include <tensorlist_stack.h>
    #include <string.h>

    int main(int argc, char* argv[]) {
        void* output_data = (void*)0x10010000;
        void* check_data = (void*)0x10020000;
        int tensor_num = 4; // 测试一个包含向量部分和尾部的数据长度

        int tensor_element_nums[4] = {4096, 4096, 4096, 4096};
        int tensor_data_type[4] = {4, 2, 4, 0};//4种数据类型
        
        void* tensor_data[4] = {(void *)0x10030000, (void *)0x10040000, (void *)0x10050000, (void *)0x10060000};
        
        srand(seed++);
        // 初始化测试数据，包含各种情况
        int i, j;
        
        //tensor 1 int32
        for(i = 0; i < tensor_element_nums[0]; i ++) {
            ((int *)tensor_data[0])[i] = rand()%100;
        }

        //tensor 2 int16
        for(i = 0; i < tensor_element_nums[1]; i ++) {
            ((int16_t *)tensor_data[1])[i] = rand()%100;
        }

        //tensor 3 fp32
        for (i = 0; i < tensor_element_nums[2]; i ++) {
            ((float *)tensor_data[2])[i] = (float)rand()/RAND_MAX;
        }

        //tensor 4 fp16
        for(i = 0; i < tensor_element_nums[3]; i ++) {
            //类型为kTypeUnknown，不需要初始化
        } 
        int core_mask = 0x0f;
        fp_tensorlist_stack_s(tensor_num, tensor_element_nums, tensor_data_type, tensor_data, output_data, unknown_type_offset, core_mask);

        return 0;
    }

**私有存储版本：**

.. c:function:: void i8_tensorlist_stack_p(int tensor_num, int *tensor_element_nums, int *tensor_data_type, void **tensor_data, void *output_data, int unknown_type_offset)
.. c:function:: void i16_tensorlist_stack_p(int tensor_num, int *tensor_element_nums, int *tensor_data_type, void **tensor_data, void *output_data, int unknown_type_offset)
.. c:function:: void i32_tensorlist_stack_p(int tensor_num, int *tensor_element_nums, int *tensor_data_type, void **tensor_data, void *output_data, int unknown_type_offset)
.. c:function:: void hp_tensorlist_stack_p(int tensor_num, int *tensor_element_nums, int *tensor_data_type, void **tensor_data, void *output_data, int unknown_type_offset)
.. c:function:: void fp_tensorlist_stack_p(int tensor_num, int *tensor_element_nums, int *tensor_data_type, void **tensor_data, void *output_data, int unknown_type_offset)
.. c:function:: void dp_tensorlist_stack_p(int tensor_num, int *tensor_element_nums, int *tensor_data_type, void **tensor_data, void *output_data, int unknown_type_offset)
.. c:function:: void c64_tensorlist_stack_p(int tensor_num, int *tensor_element_nums, int *tensor_data_type, void **tensor_data, void *output_data, int unknown_type_offset)
.. c:function:: void c128_tensorlist_stack_p(int tensor_num, int *tensor_element_nums, int *tensor_data_type, void **tensor_data, void *output_data, int unknown_type_offset)

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

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

    //FT04示例
    #include <stdio.h>
    #include <tensorlist_stack.h>
    #include <string.h>

    int main(int argc, char* argv[]) {
        void* output_data = (void*)0x10010000;
        void* check_data = (void*)0x10020000;
        int tensor_num = 4; // 测试一个包含向量部分和尾部的数据长度

        int tensor_element_nums[4] = {4096, 4096, 4096, 4096};
        int tensor_data_type[4] = {4, 2, 4, 0};//4种数据类型
        
        void* tensor_data[4] = {(void *)0x10030000, (void *)0x10040000, (void *)0x10050000, (void *)0x10060000};
        
        srand(seed++);
        // 初始化测试数据，包含各种情况
        int i, j;
        
        //tensor 1 int32
        for(i = 0; i < tensor_element_nums[0]; i ++) {
            ((int *)tensor_data[0])[i] = rand()%100;
        }

        //tensor 2 int16
        for(i = 0; i < tensor_element_nums[1]; i ++) {
            ((int16_t *)tensor_data[1])[i] = rand()%100;
        }

        //tensor 3 fp32
        for (i = 0; i < tensor_element_nums[2]; i ++) {
            ((float *)tensor_data[2])[i] = (float)rand()/RAND_MAX;
        }

        //tensor 4 fp16
        for(i = 0; i < tensor_element_nums[3]; i ++) {
            //类型为kTypeUnknown，不需要初始化
        } 
        
        fp_tensorlist_stack_p(tensor_num, tensor_element_nums, tensor_data_type, tensor_data, output_data, unknown_type_offset);
        
        return 0;
    }