ActivationGrad
=================

激活函数梯度计算算子系列。该系列算子根据激活函数的输入（或输出）以及上一层传回的梯度，计算并输出当前层的梯度。

其中 :math:`src0` 为梯度输入（Output Gradient），:math:`src1` 为激活函数的原始输入或输出（取决于具体激活函数类型）。各算子具体计算公式：

- **ReluGrad** - ReLU 激活梯度：

  .. math::
     dst_i = (src1_i > 0) \cdot src0_i

- **Relu6Grad** - ReLU6 激活梯度：

  .. math::
     dst_i = (0 < src1_i \leq 6) \cdot src0_i

- **LReluGrad** - Leaky ReLU 激活梯度，参数 ``alpha``：

  .. math::
     dst_i = (src1_i > 0) \cdot src0_i + (src1_i \leq 0) \cdot \alpha \cdot src0_i

- **SigmoidGrad** - Sigmoid 激活梯度：

  .. math::
     dst_i = src0_i \cdot src1_i \cdot (1 - src1_i)

- **TanhGrad** - Tanh 激活梯度：

  .. math::
     dst_i = src0_i \cdot (1 - src1_i^2)

- **HSigmoidGrad** - Hard Sigmoid 激活梯度：

  .. math::
     dst_i = src0_i \cdot \begin{cases} 0 & src1_i < -3 \\ 1/6 & -3 \leq src1_i \leq 3 \\ 0 & src1_i > 3 \end{cases}

- **HSwishGrad** - Hard Swish 激活梯度：

  .. math::
     dst_i = src0_i \cdot \begin{cases} 0 & src1_i < -3 \\ (2 \cdot src1_i + 3) / 6 & -3 \leq src1_i \leq 3 \\ 1 & src1_i > 3 \end{cases}

- **GeluGrad** - GELU 激活梯度：

  .. math::
     dst_i = src0_i \cdot \left( \frac{1}{2} \left(1 + \text{erf}\left(\frac{src1_i}{\sqrt{2}}\right)\right) + \frac{src1_i \cdot e^{-src1_i^2/2}}{\sqrt{2\pi}} \right)

- **EluGrad** - ELU 激活梯度，参数 ``alpha``：

  .. math::
     dst_i = (src1_i > 0) \cdot src0_i + (src1_i \leq 0) \cdot \alpha \cdot e^{src1_i} \cdot src0_i

- **SoftplusGrad** - Softplus 激活梯度：

  .. math::
     dst_i = \frac{src0_i}{1 + e^{-src1_i}}

- **HardshrinkGrad** - Hard Shrink 激活梯度，参数 ``lambd``：

  .. math::
     dst_i = \begin{cases} 0 & -\lambda \leq src1_i \leq \lambda \\ src0_i & \text{otherwise} \end{cases}

- **SoftshrinkGrad** - Softshrink 激活梯度，参数 ``lambd``：

  .. math::
     dst_i = \begin{cases} 0 & -\lambda \leq src1_i \leq \lambda \\ src0_i & \text{otherwise} \end{cases}

- **CeluGrad** - CELU 激活梯度，参数 ``alpha``：

  .. math::
     dst_i = (src1_i > 0) \cdot src0_i + (src1_i \leq 0) \cdot src0_i \cdot e^{src1_i / \alpha}

- **HardtanhGrad** - Hard Tanh 激活梯度，参数 ``min_val`` 和 ``max_val``：

  .. math::
     dst_i = (min\_val < src1_i \leq max\_val) \cdot src0_i

输入：
    - **src0** - 梯度输入数据地址。
    - **src1** - 原始输入/输出数据地址。
    - **length** - 计算长度。
    - **alpha (float, 可选)** - LReluGrad、EluGrad、CeluGrad 所需的系数。
    - **lambd (float, 可选)** - HardshrinkGrad、SoftshrinkGrad 所需的系数。
    - **min_val / max_val (float, 可选)** - HardtanhGrad 所需的边界值。
    - **core_mask (int, 可选)** - 核掩码（仅适用于共享存储版本）。

输出：
    - **dst** - 梯度计算结果输出地址。

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

.. note::
    - FT78NE 仅支持 fp32。
    - MT7004 支持 fp32, fp16。
    - 对于不同的算子，``src1`` 的含义可能不同（例如 SigmoidGrad 通常使用前向传播的输出作为 src1，而 ReluGrad 使用前向传播的输入作为 src1），需确保上层传入地址正确。

**共享存储版本:**

.. c:function:: void fp_relu_grad_s(float* src0, float* src1, float* dst, int length, int core_mask)
.. c:function:: void hp_relu_grad_s(float16* src0, float16* src1, float16* dst, int length, int core_mask)
.. c:function:: void fp_relu6_grad_s(float* src0, float* src1, float* dst, int length, int core_mask)
.. c:function:: void hp_relu6_grad_s(float16* src0, float16* src1, float16* dst, int length, int core_mask)
.. c:function:: void fp_lrelu_grad_s(float* src0, float* src1, float* dst, int length, float alpha, int core_mask)
.. c:function:: void hp_lrelu_grad_s(float16* src0, float16* src1, float16* dst, int length, float16 alpha, int core_mask)
.. c:function:: void fp_sigmoid_grad_s(float* src0, float* src1, float* dst, int length, int core_mask)
.. c:function:: void hp_sigmoid_grad_s(float16* src0, float16* src1, float16* dst, int length, int core_mask)
.. c:function:: void fp_tanh_grad_s(float* src0, float* src1, float* dst, int length, int core_mask)
.. c:function:: void hp_tanh_grad_s(float16* src0, float16* src1, float16* dst, int length, int core_mask)
.. c:function:: void fp_hsigmoid_grad_s(float* src0, float* src1, float* dst, int length, int core_mask)
.. c:function:: void hp_hsigmoid_grad_s(float16* src0, float16* src1, float16* dst, int length, int core_mask)
.. c:function:: void fp_hswish_grad_s(float* src0, float* src1, float* dst, int length, int core_mask)
.. c:function:: void hp_hswish_grad_s(float16* src0, float16* src1, float16* dst, int length, int core_mask)
.. c:function:: void fp_gelu_grad_s(float* src0, float* src1, float* dst, int length, int core_mask)
.. c:function:: void hp_gelu_grad_s(float16* src0, float16* src1, float16* dst, int length, int core_mask)
.. c:function:: void fp_elu_grad_s(float* src0, float* src1, float* dst, int length, float alpha, int core_mask)
.. c:function:: void hp_elu_grad_s(float16* src0, float16* src1, float16* dst, int length, float16 alpha, int core_mask)
.. c:function:: void fp_softplus_grad_s(float* src0, float* src1, float* dst, int length, int core_mask)
.. c:function:: void hp_softplus_grad_s(float16* src0, float16* src1, float16* dst, int length, int core_mask)
.. c:function:: void fp_hardshrink_grad_s(float* src0, float* src1, float* dst, int length, float lambd, int core_mask)
.. c:function:: void hp_hardshrink_grad_s(float16* src0, float16* src1, float16* dst, int length, float16 lambd, int core_mask)
.. c:function:: void fp_softshrink_grad_s(float* src0, float* src1, float* dst, int length, float lambd, int core_mask)
.. c:function:: void hp_softshrink_grad_s(float16* src0, float16* src1, float16* dst, int length, float16 lambd, int core_mask)
.. c:function:: void fp_celu_grad_s(float* src0, float* src1, float* dst, int length, float alpha, int core_mask)
.. c:function:: void hp_celu_grad_s(float16* src0, float16* src1, float16* dst, int length, float16 alpha, int core_mask)
.. c:function:: void fp_hardtanh_grad_s(float* src0, float* src1, float* dst, int length, float min_val, float max_val, int core_mask)
.. c:function:: void hp_hardtanh_grad_s(float16* src0, float16* src1, float16* dst, int length, float min_val, float max_val, int core_mask)

    **C调用示例：**

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

        //MT7004示例（共享存储）
        #include <stdio.h>

        int main(int argc, char* argv[]) {
            float *src0 = (float *)0xA0000000;   // 梯度输入在共享存储
            float *src1 = (float *)0xA1000000;   // 原始数据在共享存储
            float *dst  = (float *)0xB0000000;   // 结果输出到共享存储
            int length = 1024;
            int core_mask = 0xff;
            fp_relu_grad_s(src0, src1, dst, length, core_mask);
            return 0;
        }


**私有存储版本:**

.. c:function:: void fp_relu_grad_p(float* src0, float* src1, float* dst, int length)
.. c:function:: void hp_relu_grad_p(float16* src0, float16* src1, float16* dst, int length)
.. c:function:: void fp_relu6_grad_p(float* src0, float* src1, float* dst, int length)
.. c:function:: void hp_relu6_grad_p(float16* src0, float16* src1, float16* dst, int length)
.. c:function:: void fp_lrelu_grad_p(float* src0, float* src1, float* dst, int length, float alpha)
.. c:function:: void hp_lrelu_grad_p(float16* src0, float16* src1, float16* dst, int length, float16 alpha)
.. c:function:: void fp_sigmoid_grad_p(float* src0, float* src1, float* dst, int length)
.. c:function:: void hp_sigmoid_grad_p(float16* src0, float16* src1, float16* dst, int length)
.. c:function:: void fp_tanh_grad_p(float* src0, float* src1, float* dst, int length)
.. c:function:: void hp_tanh_grad_p(float16* src0, float16* src1, float16* dst, int length)
.. c:function:: void fp_hsigmoid_grad_p(float* src0, float* src1, float* dst, int length)
.. c:function:: void hp_hsigmoid_grad_p(float16* src0, float16* src1, float16* dst, int length)
.. c:function:: void fp_hswish_grad_p(float* src0, float* src1, float* dst, int length)
.. c:function:: void hp_hswish_grad_p(float16* src0, float16* src1, float16* dst, int length)
.. c:function:: void fp_gelu_grad_p(float* src0, float* src1, float* dst, int length)
.. c:function:: void hp_gelu_grad_p(float16* src0, float16* src1, float16* dst, int length)
.. c:function:: void fp_elu_grad_p(float* src0, float* src1, float* dst, int length, float alpha)
.. c:function:: void hp_elu_grad_p(float16* src0, float16* src1, float16* dst, int length, float16 alpha)
.. c:function:: void fp_softplus_grad_p(float* src0, float* src1, float* dst, int length)
.. c:function:: void hp_softplus_grad_p(float16* src0, float16* src1, float16* dst, int length)
.. c:function:: void fp_hardshrink_grad_p(float* src0, float* src1, float* dst, int length, float lambd)
.. c:function:: void hp_hardshrink_grad_p(float16* src0, float16* src1, float16* dst, int length, float16 lambd)
.. c:function:: void fp_softshrink_grad_p(float* src0, float* src1, float* dst, int length, float lambd)
.. c:function:: void hp_softshrink_grad_p(float16* src0, float16* src1, float16* dst, int length, float16 lambd)
.. c:function:: void fp_celu_grad_p(float* src0, float* src1, float* dst, int length, float alpha)
.. c:function:: void hp_celu_grad_p(float16* src0, float16* src1, float16* dst, int length, float16 alpha)
.. c:function:: void fp_hardtanh_grad_p(float* src0, float* src1, float* dst, int length, float min_val, float max_val)
.. c:function:: void hp_hardtanh_grad_p(float16* src0, float16* src1, float16* dst, int length, float min_val, float max_val)

    **C调用示例：**

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

        //MT7004 示例
        #include <stdio.h>

        int main(int argc, char* argv[]) {
            float *src0 = (float *)0x10000000;   // 私有存储空间地址
            float *src1 = (float *)0x10001000;
            float *dst  = (float *)0x10002000;
            int length = 1024;
            float alpha = 0.01f;
            fp_lrelu_grad_p(src0, src1, dst, length, alpha);
            return 0;
        }