ReverseV2
=================

对输入Tensor按指定维度反转。

输入：
        - **src** - 需反转数据的地址
        - **param** - 算子计算所需参数的结构体。其各成员见下述。
        - **core_mask** - 核掩码。

**ReverseV2Parameter定义：**

.. code-block:: c
    :linenos:

    typedef struct ReverseV2Parameter {
        int* axis_flag_; // 用于存储需反转的轴，需反转的轴对应于数组索引的元素被置为1，其余元素为0
        int* input_shape_; // 输入张量的形状
        int* input_strides_; // 一个记录输入张量每一维步长的数组
        int** cur_coord_; // 二维数组，每个元素存储对应核心所使用的cur_coord数组地址，这个数组用于记录当前循环到的元素坐标
        int ndim_; // 输入和输出张量的维度
        int axis_ndim_; // 需反转的轴的数目
        int num_elem_; // 元素总数
        int type_size_; // 输入和输出张量数据类型的长度
    } ReverseV2Parameter;

输出：
        - **dst** - 输出地址。

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

.. note::
    - FT78NE 支持int8, int16, int32, fp32, fp64, cplx64, cplx128
    - MT7004 支持fp16, fp32, int16, int32, cplx64
    
**共享/私有存储版本:**

.. c:function:: void anytype_reversev2_anycore(void* src, void* dst, ReverseV2Parameter* param, int core_mask)

各种数据类型、私有及共享空间版本均使用该函数。对于不同数据类型，改变param中的type_size_参数即可。

**C调用示例：**

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

    void Resize(ReverseV2Parameter* param, int* axis) {
        int i;
        param->input_strides_[param->ndim_ - 1] = 1;
        for (i = param->ndim_ - 1; i > 0; i--) {
            param->input_strides_[i - 1] = param->input_strides_[i] * param->input_shape_[i];
        }
        for (i = 0; i < param->ndim_; i++) {
            // initialize axis_flag array by 0
            param->axis_flag_[i] = 0;
        }
        for (i = 0; i < param->axis_ndim_; i++) {
            param->axis_flag_[axis[i]] = 1;
        }
        param->num_elem_ = 1;
        for (i = 0; i < param->ndim_; i++) {
            param->num_elem_ *= param->input_shape_[i];
        }
    }

    void TestReverseV2(int* shape, int ndim, int* axis, int axis_ndim, int core_mask) {
        int type_size = 4;
        int core_num = GetCoreNum(core_mask);
        int core_id = get_core_id();
        int logic_core_id = GetLogicCoreId(core_mask, core_id);
        float* input_data = (float*)0x88000000; // 测试私有空间时地址设置在私有空间内即可
        float* output_data = (float*)0xA8000000;
        float* check = (float*)0xC8000000;
        ReverseV2Parameter* param = (ReverseV2Parameter*)0x84000000;
        if (logic_core_id == 0) {
            int i, j;
            param->axis_ndim_ =  axis_ndim;
            param->input_shape_ = (int*)0x84003000;
            for (i = 0; i < ndim; i++) {
                param->input_shape_[i] = shape[i];
            }
            param->ndim_ = ndim;
            param->type_size_ = type_size;
            param->input_strides_ = (int*)0x84004000;
            param->axis_flag_ = (int*)0x84005000;
            param->cur_coord_ = (int**)0x84006000;
            for (i = 0; i < 4; i++) {
                param->cur_coord_[i] = (int*)(0x84007000 + i * 0x1000LL);
                for (j = 0; j < ndim; j++) {
                    param->cur_coord_[i][j] = 0;
                }
            }
            Resize(param, axis);
        }
        sys_bar(0, core_num); // 初始化参数完成后进行同步
        anytype_reversev2_anycore(input_data, output_data, param, core_mask);
    }

    void main(){
        int shape[3] = {10, 10, 1000};
        int ndim = 3;
        int axis[3] = {0, 1, 2};
        int axis_ndim = 3;
        int core_mask = 0b1111;
        TestReverseV2(shape, ndim, axis, axis_ndim, core_mask);
    }