xref: /aosp_15_r20/external/XNNPACK/src/f32-velu/scalar-rr2-p6.c.in (revision 4bdc94577ba0e567308109d787f7fec7b531ce36)
1// Copyright 2020 Google LLC
2//
3// This source code is licensed under the BSD-style license found in the
4// LICENSE file in the root directory of this source tree.
5
6$assert BATCH_TILE >= 1
7#include <assert.h>
8#include <math.h>
9
10#include <xnnpack/common.h>
11#include <xnnpack/math.h>
12#include <xnnpack/vunary.h>
13
14
15void xnn_f32_velu_ukernel__${"wasm" if WASM else "scalar"}_rr2_p6_x${BATCH_TILE}(
16    size_t n,
17    const float* x,
18    float* y,
19    const union xnn_f32_elu_params params[restrict XNN_MIN_ELEMENTS(1)])
20{
21  assert(n % sizeof(float) == 0);
22
23  const float vprescale = params->scalar_rr2_p6.prescale;
24  const float valpha = params->scalar_rr2_p6.alpha;
25  const float vbeta = params->scalar_rr2_p6.beta;
26  const float vmagic_bias = params->scalar_rr2_p6.magic_bias;
27  const float vlog2e = params->scalar_rr2_p6.log2e;
28  const float vsat_cutoff = params->scalar_rr2_p6.sat_cutoff;
29  const float vminus_ln2_hi = params->scalar_rr2_p6.minus_ln2_hi;
30  const float vminus_ln2_lo = params->scalar_rr2_p6.minus_ln2_lo;
31  const float vc6 = params->scalar_rr2_p6.c6;
32  const float vc5 = params->scalar_rr2_p6.c5;
33  const float vc4 = params->scalar_rr2_p6.c4;
34  const float vc3 = params->scalar_rr2_p6.c3;
35  const float vc2 = params->scalar_rr2_p6.c2;
36  const float vone = params->scalar_rr2_p6.one;
37
38  $if BATCH_TILE > 1:
39    for (; n >= ${BATCH_TILE} * sizeof(float); n -= ${BATCH_TILE} * sizeof(float)) {
40      $for N in range(BATCH_TILE):
41        float vx${N} = x[${N}];
42      x += ${BATCH_TILE};
43
44      $for N in range(BATCH_TILE):
45        $if WASM:
46          const float vz${N} = __builtin_wasm_min_f32(__builtin_wasm_max_f32(vx${N} * vprescale, vsat_cutoff), 0.0f);
47        $else:
48          const float vz${N} = vx${N} * vprescale;
49
50      $for N in range(BATCH_TILE):
51        float vn${N} = vz${N} * vlog2e + vmagic_bias;
52
53      $for N in range(BATCH_TILE):
54        float vs${N} = uint32_as_float(float_as_uint32(vn${N}) << 23);
55        vn${N} -= vmagic_bias;
56
57      $for N in range(BATCH_TILE):
58        float vt${N} = vn${N} * vminus_ln2_hi + vz${N};
59
60      $for N in range(BATCH_TILE):
61        vt${N} = vn${N} * vminus_ln2_lo + vt${N};
62
63      $if not WASM:
64        $for N in range(BATCH_TILE):
65          if XNN_UNPREDICTABLE(vz${N} <= vsat_cutoff) {
66            vs${N} = 0.0f;
67            vt${N} = 0.0f;
68          }
69
70      $for N in range(BATCH_TILE):
71        float vp${N} = vc6 * vt${N} + vc5;
72
73      $for N in range(BATCH_TILE):
74        vp${N} = vp${N} * vt${N} + vc4;
75
76      $for N in range(BATCH_TILE):
77        vp${N} = vp${N} * vt${N} + vc3;
78
79      $for N in range(BATCH_TILE):
80        vp${N} = vp${N} * vt${N} + vc2;
81
82      $for N in range(BATCH_TILE):
83        vp${N} *= vt${N};
84
85      $for N in range(BATCH_TILE):
86        vt${N} *= vs${N};
87        vs${N} -= vone;
88
89      $for N in range(BATCH_TILE):
90        vp${N} = vp${N} * vt${N} + vt${N};
91
92      $for N in range(BATCH_TILE):
93        const float ve${N} = (vp${N} + vs${N}) * valpha;
94        $if WASM:
95          float vy${N} = __builtin_wasm_max_f32(vx${N} * vbeta, 0.0f);
96        $else:
97          float vy${N} = vx${N} * vbeta;
98
99      $if WASM:
100        $for N in range(BATCH_TILE):
101          vy${N} += __builtin_wasm_min_f32(ve${N}, 0.0f);
102      $else:
103        $for N in range(BATCH_TILE):
104          if XNN_UNPREDICTABLE(vx${N} < 0.0f) {
105            vy${N} = ve${N};
106          }
107
108      $for N in range(BATCH_TILE):
109        y[${N}] = vy${N};
110      y += ${BATCH_TILE};
111    }
112  $if BATCH_TILE == 1:
113    do {
114      float vx = *x++;
115
116      $if WASM:
117        const float vz = __builtin_wasm_min_f32(__builtin_wasm_max_f32(vx * vprescale, vsat_cutoff), 0.0f);
118      $else:
119        const float vz = vx * vprescale;
120
121      float vn = vz * vlog2e + vmagic_bias;
122      float vs = uint32_as_float(float_as_uint32(vn) << 23);
123      vn -= vmagic_bias;
124
125      float vt = vn * vminus_ln2_hi + vz;
126      vt = vn * vminus_ln2_lo + vt;
127
128      $if not WASM:
129        if XNN_UNPREDICTABLE(vz <= vsat_cutoff) {
130          vs = 0.0f;
131          vt = 0.0f;
132        }
133
134      float vp = vc6 * vt + vc5;
135      vp = vp * vt + vc4;
136      vp = vp * vt + vc3;
137      vp = vp * vt + vc2;
138      vp *= vt;
139
140      vt *= vs;
141      vs -= vone;
142      vp = vp * vt + vt;
143      const float ve = (vp + vs) * valpha;
144
145      $if WASM:
146        float vy = __builtin_wasm_max_f32(vx * vbeta, 0.0f);
147        vy += __builtin_wasm_min_f32(ve, 0.0f);
148      $else:
149        float vy = vx * vbeta;
150        if XNN_UNPREDICTABLE(vx < 0.0f) {
151          vy = ve;
152        }
153
154      *y++ = vy;
155
156      n -= sizeof(float);
157    } while (n != 0);
158  $elif BATCH_TILE == 2:
159    if XNN_UNLIKELY(n != 0) {
160      float vx = *x;
161
162      $if WASM:
163        const float vz = __builtin_wasm_min_f32(__builtin_wasm_max_f32(vx * vprescale, vsat_cutoff), 0.0f);
164      $else:
165        const float vz = vx * vprescale;
166
167      float vn = vz * vlog2e + vmagic_bias;
168      float vs = uint32_as_float(float_as_uint32(vn) << 23);
169      vn -= vmagic_bias;
170
171      float vt = vn * vminus_ln2_hi + vz;
172      vt = vn * vminus_ln2_lo + vt;
173
174      $if not WASM:
175        if XNN_UNPREDICTABLE(vz <= vsat_cutoff) {
176          vs = 0.0f;
177          vt = 0.0f;
178        }
179
180      float vp = vc6 * vt + vc5;
181      vp = vp * vt + vc4;
182      vp = vp * vt + vc3;
183      vp = vp * vt + vc2;
184      vp *= vt;
185
186      vt *= vs;
187      vs -= vone;
188      vp = vp * vt + vt;
189      const float ve = (vp + vs) * valpha;
190
191      $if WASM:
192        float vy = __builtin_wasm_max_f32(vx * vbeta, 0.0f);
193        vy += __builtin_wasm_min_f32(ve, 0.0f);
194      $else:
195        float vy = vx * vbeta;
196        if XNN_UNPREDICTABLE(vx < 0.0f) {
197          vy = ve;
198        }
199
200      *y = vy;
201    }
202  $else:
203    if XNN_UNLIKELY(n != 0) {
204      do {
205        float vx = *x++;
206
207        $if WASM:
208          const float vz = __builtin_wasm_min_f32(__builtin_wasm_max_f32(vx * vprescale, vsat_cutoff), 0.0f);
209        $else:
210          const float vz = vx * vprescale;
211
212        float vn = vz * vlog2e + vmagic_bias;
213        float vs = uint32_as_float(float_as_uint32(vn) << 23);
214        vn -= vmagic_bias;
215
216        float vt = vn * vminus_ln2_hi + vz;
217        vt = vn * vminus_ln2_lo + vt;
218
219        $if not WASM:
220          if XNN_UNPREDICTABLE(vz <= vsat_cutoff) {
221            vs = 0.0f;
222            vt = 0.0f;
223          }
224
225        float vp = vc6 * vt + vc5;
226        vp = vp * vt + vc4;
227        vp = vp * vt + vc3;
228        vp = vp * vt + vc2;
229        vp *= vt;
230
231        vt *= vs;
232        vs -= vone;
233        vp = vp * vt + vt;
234        const float ve = (vp + vs) * valpha;
235
236        $if WASM:
237          float vy = __builtin_wasm_max_f32(vx * vbeta, 0.0f);
238          vy += __builtin_wasm_min_f32(ve, 0.0f);
239        $else:
240          float vy = vx * vbeta;
241          if XNN_UNPREDICTABLE(vx < 0.0f) {
242            vy = ve;
243          }
244
245        *y++ = vy;
246
247        n -= sizeof(float);
248      } while (n != 0);
249    }
250}
251