InstanceNorm
=================



对输入张量按 **实例（Instance）+ 通道（Channel）** 维度执行归一化操作。
该算子在每个样本的每个通道内，基于 ``inner_size`` 维度计算均值与方差，
并结合可学习参数 ``gamma`` 与 ``beta`` 完成缩放与偏移。

.. math::

    \mu_{b,c} = \frac{1}{N} \sum_{i=1}^{N} x_{b,c,i}

    \sigma^2_{b,c} = \frac{1}{N} \sum_{i=1}^{N} x_{b,c,i}^2 - \mu_{b,c}^2

    y_{b,c,i} = \left( \frac{x_{b,c,i} - \mu_{b,c}}{\sqrt{\sigma^2_{b,c} + \epsilon}} \right)
                \cdot \gamma_c + \beta_c

其中：

- :math:`b` 表示 batch 维度
- :math:`c` 表示通道维度
- :math:`i` 表示 ``inner_size`` 维度
- :math:`\gamma_c`、:math:`\beta_c` 为通道级缩放与偏移参数

输入：
    - **input** - 输入数据地址，形状为 ``[batch, channel, inner_size]``。
    - **params** - 参数打包成数组，格式如下：
        - **gamma** - 缩放参数地址，长度为 ``channel``。
        - **beta** - 偏移参数地址，长度为 ``channel``。
        - **batch** - batch 数。
        - **channel** - 通道数。
        - **inner_size** - 每个通道内的归一化长度。
    - **epsilon** - 数值稳定因子。
    - **core_mask** - 核掩码（仅适用于共享存储版本）。

输出：
    - **output** - InstanceNorm 计算结果地址。

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

.. note::
    - FT78NE 支持 ``fp32`` 类型
    - MT7004 支持 ``fp16``、``fp32`` 类型
    - 归一化统计量仅在单个样本、单个通道内计算

**共享存储版本:**

.. c:function:: void fp_instance_norm_s(float* input, float* output, long long *params, int core_mask, float epsilon)
.. c:function:: void hp_instance_norm_s(half* input, half* output, long long *params, int core_mask, float epsilon)

**C调用示例：**

.. code-block:: c
    :linenos:
    :emphasize-lines: 17-18

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

    int main(int argc, char* argv[]) {
        float *input = (float*)0x81000000;
        float *gamma = (float*)0x82000000;
        float *beta = (float*)0x83000000;
        float *output = (float*)0x84000000;

        int batch;
        int channel;
        int inner_size;
       
        batch = 4;
        channel = 16;
        inner_size = 8;
     
        float epsilon = 0.001;

        long long param[10];
        param[0] = (long long)gamma;
        param[1] = (long long)beta;
        param[2] = (long long)batch;
        param[3] = (long long)channel;
        param[4] = (long long)inner_size;

        int i, j, k;
        for (i = 0; i < batch; i++){
            gamma[i] = 0;
            beta[i] = 0;
            for(j = 0; j < channel; j++){
                for(k = 0; k < inner_size; k++){
                    input[i * channel * inner_size + j * inner_size + k] = (float)rand() / (RAND_MAX + 1.0);
                }
            }
        }
        for(i = 0; i < channel; ++i){
            gamma[i] = ((float)rand() / RAND_MAX) * 2 - 1;
            beta[i] = ((float)rand() / RAND_MAX) * 2 + 0.1;	
        }
        
        int core_mask = 0b1111;
        fp_instance_norm_s(input, output, param, core_mask, epsilon);
        return 0;
    }


**私有存储版本:**

.. c:function:: void fp_instance_norm_p(float* input, float* output, long long *params, float epsilon)
.. c:function:: void hp_instance_norm_p(half* input, half* output, long long *params, float epsilon)


**C调用示例：**

.. code-block:: c
    :linenos:
    :emphasize-lines: 16-17

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

    int main(int argc, char* argv[]) {
        float *input = (float*)0x10010000;
        float *gamma = (float*)0x10020000;
        float *beta = (float*)0x10030000;
        float *output = (float*)0x10040000;

        int batch;
        int channel;
        int inner_size;
       
        batch = 4;
        channel = 16;
        inner_size = 8;
     
        float epsilon = 0.001;

        long long param[10];
        param[0] = (long long)gamma;
        param[1] = (long long)beta;
        param[2] = (long long)batch;
        param[3] = (long long)channel;
        param[4] = (long long)inner_size;

        int i, j, k;
        for (i = 0; i < batch; i++){
            gamma[i] = 0;
            beta[i] = 0;
            for(j = 0; j < channel; j++){
                for(k = 0; k < inner_size; k++){
                    input[i * channel * inner_size + j * inner_size + k] = (float)rand() / (RAND_MAX + 1.0);
                }
            }
        }
        for(i = 0; i < channel; ++i){
            gamma[i] = ((float)rand() / RAND_MAX) * 2 - 1;
            beta[i] = ((float)rand() / RAND_MAX) * 2 + 0.1;	
        }

        fp_instance_norm_p(input, output, param, epsilon);
        return 0;
    }
