| 167 | |
| 168 | // NEON-optimized absmax computation for a block of float32, bf16, or fp16. |
| 169 | template <typename T> static inline float neon_absmax(const T* data, long long n) { |
| 170 | float32x4_t vmax = vdupq_n_f32(0.0f); |
| 171 | long long i = 0; |
| 172 | for (; i + 16 <= n; i += 16) { |
| 173 | float32x4_t v0, v1, v2, v3; |
| 174 | if constexpr (std::is_same<T, float>::value) { |
| 175 | const float* p = reinterpret_cast<const float*>(data + i); |
| 176 | v0 = vld1q_f32(p); |
| 177 | v1 = vld1q_f32(p + 4); |
| 178 | v2 = vld1q_f32(p + 8); |
| 179 | v3 = vld1q_f32(p + 12); |
| 180 | } else if constexpr (std::is_same<T, bf16_t>::value) { |
| 181 | v0 = neon_bf16x4_to_f32(data + i); |
| 182 | v1 = neon_bf16x4_to_f32(data + i + 4); |
| 183 | v2 = neon_bf16x4_to_f32(data + i + 8); |
| 184 | v3 = neon_bf16x4_to_f32(data + i + 12); |
| 185 | } else { |
| 186 | v0 = neon_fp16x4_to_f32(data + i); |
| 187 | v1 = neon_fp16x4_to_f32(data + i + 4); |
| 188 | v2 = neon_fp16x4_to_f32(data + i + 8); |
| 189 | v3 = neon_fp16x4_to_f32(data + i + 12); |
| 190 | } |
| 191 | vmax = vmaxq_f32( |
| 192 | vmax, vmaxq_f32(vmaxq_f32(vabsq_f32(v0), vabsq_f32(v1)), vmaxq_f32(vabsq_f32(v2), vabsq_f32(v3))) |
| 193 | ); |
| 194 | } |
| 195 | for (; i + 4 <= n; i += 4) { |
| 196 | float32x4_t v; |
| 197 | if constexpr (std::is_same<T, float>::value) |
| 198 | v = vld1q_f32(reinterpret_cast<const float*>(data + i)); |
| 199 | else if constexpr (std::is_same<T, bf16_t>::value) |
| 200 | v = neon_bf16x4_to_f32(data + i); |
| 201 | else |
| 202 | v = neon_fp16x4_to_f32(data + i); |
| 203 | vmax = vmaxq_f32(vmax, vabsq_f32(v)); |
| 204 | } |
| 205 | float result = vmaxvq_f32(vmax); |
| 206 | for (; i < n; ++i) { |
| 207 | float val; |
| 208 | if constexpr (std::is_same<T, float>::value) |
| 209 | val = data[i]; |
| 210 | else if constexpr (std::is_same<T, bf16_t>::value) |
| 211 | val = bf16_to_float(data[i].v); |
| 212 | else |
| 213 | val = fp16_to_float(data[i].v); |
| 214 | result = std::max(result, std::fabs(val)); |
| 215 | } |
| 216 | return result; |
| 217 | } |
| 218 | |
| 219 | // NEON-optimized norm_to_lut_index for 4 float values at a time |
| 220 | // Maps [-1, 1] → [0, 65535] |
nothing calls this directly
no test coverage detected