* @brief Return the horizontal sum of a vector. */
| 814 | * @brief Return the horizontal sum of a vector. |
| 815 | */ |
| 816 | ASTCENC_SIMD_INLINE float hadd_s(vfloat a) |
| 817 | { |
| 818 | #if defined(ASTCENC_NO_INVARIANCE) |
| 819 | vfloat_t z = __riscv_vfmv_v_f_f32m1(0, vfloat::vl()); |
| 820 | return __riscv_vfmv_f(__riscv_vfredusum(a.m, z, vfloat::vl())); |
| 821 | #else |
| 822 | // TODO: Zvzip variant, once it's ratified |
| 823 | size_t vl = __riscv_vsetvlmax_e64m1(); |
| 824 | vuint64m1_t r = __riscv_vreinterpret_u64m1(__riscv_vreinterpret_u32m1(a.m)); |
| 825 | vuint64m1_t r0 = __riscv_vreinterpret_u64m1(__riscv_vlmul_ext_u32m1(__riscv_vnsrl(r, 0, vl))); |
| 826 | vuint64m1_t r1 = __riscv_vreinterpret_u64m1(__riscv_vlmul_ext_u32m1(__riscv_vnsrl(r, 32, vl))); |
| 827 | vfloat32m1_t z = __riscv_vfmv_v_f_f32m1(0, 1); |
| 828 | vl /= 2; |
| 829 | vfloat32mf2_t r00 = __riscv_vreinterpret_f32mf2(__riscv_vnsrl(r0, 0, vl)); |
| 830 | vfloat32mf2_t r01 = __riscv_vreinterpret_f32mf2(__riscv_vnsrl(r0, 32, vl)); |
| 831 | vfloat32mf2_t r10 = __riscv_vreinterpret_f32mf2(__riscv_vnsrl(r1, 0, vl)); |
| 832 | vfloat32mf2_t r11 = __riscv_vreinterpret_f32mf2(__riscv_vnsrl(r1, 32, vl)); |
| 833 | vfloat32mf2_t sum = __riscv_vfadd(__riscv_vfadd(r00, r10, vl), __riscv_vfadd(r01, r11, vl), vl); |
| 834 | return __riscv_vfmv_f(__riscv_vfredosum(sum, z, vl)); |
| 835 | #endif |
| 836 | } |
| 837 | |
| 838 | /** |
| 839 | * @brief Return lanes from @c b if @c cond is set, else @c a. |