diff --git a/.ycm_extra_conf.py b/.ycm_extra_conf.py new file mode 100644 index 0000000000000000000000000000000000000000..1072f839f07d817cb87c602ca7d06468b8e294ec --- /dev/null +++ b/.ycm_extra_conf.py @@ -0,0 +1,4 @@ +def Settings( **kwargs ): + return { + 'flags': [ '-x', 'c++', '-march=armv8-a_sve', 'O3', '-Wall', '-Wextra', '-Werror'], + } diff --git a/Makefile b/Makefile index de5e44d51827122a33b27aca4f871d7ddfdec97f..38f15a2977353f495eb9c5fedf3cdced78771e93 100644 --- a/Makefile +++ b/Makefile @@ -12,6 +12,7 @@ HEADERS = simd.hpp \ matrix_type.hpp matrix_overloading.hpp \ arithmetics/generic/generic_vector_ops.hpp arithmetics/generic/generic.hpp arithmetics/generic/generic_matrix_ops.hpp \ arithmetics/sve/sve_vector_ops.hpp backend/sve/sve_backend.hpp arithmetics/sve/sve.hpp arithmetics/sve/sve_matrix_ops.hpp \ + backend/sve/sve_complex_double.hpp backend/sve/sve_complex_float.hpp backend/sve/sve_double.hpp backend/sve/sve_float.hpp \ loadstore/sve/sve_load.hpp all: ${TARGET} diff --git a/backend/sve/sve_complex_double.hpp b/backend/sve/sve_complex_double.hpp index 7292b48603348be1f55fc237aeb1222694d1f831..04a58e338b433a7efa86de4c2751838753c0b49c 100644 --- a/backend/sve/sve_complex_double.hpp +++ b/backend/sve/sve_complex_double.hpp @@ -94,6 +94,13 @@ struct svetype<complex<double>>{ return {re, im}; } + static inline vec and_z(svbool_t pg, vec op1, vec op2) + { + svuint64_t re = svand_z(pg, svreinterpret_u64(op1.v0), svreinterpret_u64(op2.v0)); + svuint64_t im = svand_z(pg, svreinterpret_u64(op1.v1), svreinterpret_u64(op2.v1)); + return {svreinterpret_f64(re), svreinterpret_f64(im)}; + } + static inline vec orr_z(svbool_t pg, vec op1, vec op2) { svuint64_t re = svorr_z(pg, svreinterpret_u64(op1.v0), svreinterpret_u64(op2.v0)); @@ -101,6 +108,20 @@ struct svetype<complex<double>>{ return {svreinterpret_f64(re), svreinterpret_f64(im)}; } + static inline vec eor_z(svbool_t pg, vec op1, vec op2) + { + svuint64_t re = sveor_z(pg, svreinterpret_u64(op1.v0), svreinterpret_u64(op2.v0)); + svuint64_t im = sveor_z(pg, svreinterpret_u64(op1.v1), svreinterpret_u64(op2.v1)); + return {svreinterpret_f64(re), svreinterpret_f64(im)}; + } + + static inline vec not_z(svbool_t pg, vec op1, vec op2) + { + svuint64_t re = svnot_z(pg, svreinterpret_u64(op1.v0), svreinterpret_u64(op2.v0)); + svuint64_t im = svnot_z(pg, svreinterpret_u64(op1.v1), svreinterpret_u64(op2.v1)); + return {svreinterpret_f64(re), svreinterpret_f64(im)}; + } + // vector vector operations static inline vec add_z(svbool_t pg, vec op1, vec op2) { diff --git a/backend/sve/sve_complex_float.hpp b/backend/sve/sve_complex_float.hpp index d14e3383631e4564e434ec81f70ff7570bca9656..aeef9b16ffbbbe22ec186b86b627c47e713bd262 100644 --- a/backend/sve/sve_complex_float.hpp +++ b/backend/sve/sve_complex_float.hpp @@ -94,6 +94,13 @@ struct svetype<complex<float>>{ return {re, im}; } + static inline vec and_z(svbool_t pg, vec op1, vec op2) + { + svuint32_t re = svand_z(pg, svreinterpret_u32(op1.v0), svreinterpret_u32(op2.v0)); + svuint32_t im = svand_z(pg, svreinterpret_u32(op1.v1), svreinterpret_u32(op2.v1)); + return {svreinterpret_f32(re), svreinterpret_f32(im)}; + } + static inline vec orr_z(svbool_t pg, vec op1, vec op2) { svuint32_t re = svorr_z(pg, svreinterpret_u32(op1.v0), svreinterpret_u32(op2.v0)); @@ -101,6 +108,20 @@ struct svetype<complex<float>>{ return {svreinterpret_f32(re), svreinterpret_f32(im)}; } + static inline vec eor_z(svbool_t pg, vec op1, vec op2) + { + svuint32_t re = sveor_z(pg, svreinterpret_u32(op1.v0), svreinterpret_u32(op2.v0)); + svuint32_t im = sveor_z(pg, svreinterpret_u32(op1.v1), svreinterpret_u32(op2.v1)); + return {svreinterpret_f32(re), svreinterpret_f32(im)}; + } + + static inline vec not_z(svbool_t pg, vec op1, vec op2) + { + svuint32_t re = svnot_z(pg, svreinterpret_u32(op1.v0), svreinterpret_u32(op2.v0)); + svuint32_t im = svnot_z(pg, svreinterpret_u32(op1.v1), svreinterpret_u32(op2.v1)); + return {svreinterpret_f32(re), svreinterpret_f32(im)}; + } + // vector vector operations static inline vec add_z(svbool_t pg, vec op1, vec op2) { diff --git a/backend/sve/sve_double.hpp b/backend/sve/sve_double.hpp index 20409247f74ba0fa9921f8b2cc79980eef3f81b0..a4f9b97f40bb6f7dcd9186f3860d2fab74e86b24 100644 --- a/backend/sve/sve_double.hpp +++ b/backend/sve/sve_double.hpp @@ -78,9 +78,18 @@ struct svetype<double>{ static inline vec conj_z(svbool_t pg, vec op1) { return op1; } + static inline vec and_z(svbool_t pg, vec op1, vec op2) + { return svreinterpret_f64(svand_z(pg, svreinterpret_u64(op1), svreinterpret_u64(op2))); } + static inline vec orr_z(svbool_t pg, vec op1, vec op2) { return svreinterpret_f64(svorr_z(pg, svreinterpret_u64(op1), svreinterpret_u64(op2))); } + static inline vec eor_z(svbool_t pg, vec op1, vec op2) + { return svreinterpret_f64(sveor_z(pg, svreinterpret_u64(op1), svreinterpret_u64(op2))); } + + static inline vec not_z(svbool_t pg, vec op1, vec op2) + { return svreinterpret_f64(svnot_z(pg, svreinterpret_u64(op1), svreinterpret_u64(op2))); } + // vector vector operations static inline vec add_z(svbool_t pg, vec op1, vec op2) { return svadd_f64_z(pg, op1, op2); } diff --git a/backend/sve/sve_float.hpp b/backend/sve/sve_float.hpp index 0694342d0afdadfdf08ff1e76d8f732a9b1af0be..525cd43ea840b4ea0ea13cc3c8201885a133eb45 100644 --- a/backend/sve/sve_float.hpp +++ b/backend/sve/sve_float.hpp @@ -79,9 +79,18 @@ struct svetype<float>{ static inline vec conj_z(svbool_t pg, vec op1) { return op1; } + static inline vec and_z(svbool_t pg, vec op1, vec op2) + { return svreinterpret_f32(svand_z(pg, svreinterpret_u32(op1), svreinterpret_u32(op2))); } + static inline vec orr_z(svbool_t pg, vec op1, vec op2) { return svreinterpret_f32(svorr_z(pg, svreinterpret_u32(op1), svreinterpret_u32(op2))); } + static inline vec eor_z(svbool_t pg, vec op1, vec op2) + { return svreinterpret_f32(sveor_z(pg, svreinterpret_u32(op1), svreinterpret_u32(op2))); } + + static inline vec not_z(svbool_t pg, vec op1, vec op2) + { return svreinterpret_f32(svnot_z(pg, svreinterpret_u32(op1), svreinterpret_u32(op2))); } + // vector vector operations static inline vec add_z(svbool_t pg, vec op1, vec op2) { return svadd_f32_z(pg, op1, op2); } diff --git a/backend/sve/sve_int.hpp b/backend/sve/sve_int.hpp index cf3a5fdfd80754702bc3f5d68fdb2cbad1c14e35..7d3e4a3c8f3c0bed21a3c932b74db96a1d6a08ed 100644 --- a/backend/sve/sve_int.hpp +++ b/backend/sve/sve_int.hpp @@ -76,9 +76,18 @@ struct svetype<int>{ static inline vec mulscal_z(svbool_t pg, vec op1, scal op2) { return svmul_n_s32_z(pg, op1, op2); } + static inline vec and_z(svbool_t pg, vec op1, vec op2) + { return svand_z(pg, op1, op2); } + static inline vec orr_z(svbool_t pg, vec op1, vec op2) { return svorr_z(pg, op1, op2); } + static inline vec eor_z(svbool_t pg, vec op1, vec op2) + { return sveor_z(pg, op1, op2); } + + static inline vec not_z(svbool_t pg, vec op1, vec op2) + { return svnot_z(pg, op1, op2); } + // vector vector operations static inline vec add_z(svbool_t pg, vec op1, vec op2) { return svadd_s32_z(pg, op1, op2); } diff --git a/bitwise/generic/gen_bit_ops.hpp b/bitwise/generic/gen_bit_ops.hpp index e6a0bddfcaa7f6f2218eb234199d908ebaa2e649..842e1e20707e20d691d3c30609563e221c17cf20 100644 --- a/bitwise/generic/gen_bit_ops.hpp +++ b/bitwise/generic/gen_bit_ops.hpp @@ -40,6 +40,25 @@ #define VECTOR_FOR(i, w, inc) \ for (unsigned int i = 0; i < w; i += inc) +// bitwise and two vectors +struct bitwise_and_vector_vector{ + template <typename T> + inline vector_t<T> operator()(const vector_t<T> &a, const vector_t<T> &b) + { + assert(a.size == b.size); + + vector_t<T> vres(a.size); + + std::cout << "[Generic vector (bitwise and) used]" << endl; + + VECTOR_FOR(i, vres.size, 1) + { + vres.elem[i] = a.elem[i] & b.elem[i]; + } + return vres; + } +}; + // bitwise or two vectors struct bitwise_or_vector_vector{ template <typename T> @@ -59,6 +78,63 @@ struct bitwise_or_vector_vector{ } }; +// bitwise xor two vectors +struct bitwise_xor_vector_vector{ + template <typename T> + inline vector_t<T> operator()(const vector_t<T> &a, const vector_t<T> &b) + { + assert(a.size == b.size); + + vector_t<T> vres(a.size); + + std::cout << "[Generic vector (bitwise xor) used]" << endl; + + VECTOR_FOR(i, vres.size, 1) + { + vres.elem[i] = a.elem[i] ^ b.elem[i]; + } + return vres; + } +}; + +// bitwise not two vectors +struct bitwise_not_vector_vector{ + template <typename T> + inline vector_t<T> operator()(const vector_t<T> &a, const vector_t<T> &b) + { + assert(a.size == b.size); + + vector_t<T> vres(a.size); + + std::cout << "[Generic vector (bitwise not) used]" << endl; + + VECTOR_FOR(i, vres.size, 1) + { + vres.elem[i] = a.elem[i] ~ b.elem[i]; + } + return vres; + } +}; + +// bitwise logical shift left two vectors +struct bitwise_logical_shift_left_vector_vector{ template <typename T> + inline vector_t<T> operator()(const vector_t<T> &a, const int &b) + { + assert(a.size == b.size); + + vector_t<T> vres(a.size); + + std::cout << "[Generic vector (bitwise not) used]" << endl; + + VECTOR_FOR(i, vres.size, 1) + { + vres.elem[i] = a.elem[i] << b; + } + return vres; + } +}; + + #endif // GEN_BIT_OPS_HPP diff --git a/bitwise/sve/sve_bit_ops.hpp b/bitwise/sve/sve_bit_ops.hpp index c108629830895ee4e6e407d250dc4e0fb0e305a6..6adad5b9508b33c6a331cf188d7537ad757afb7a 100644 --- a/bitwise/sve/sve_bit_ops.hpp +++ b/bitwise/sve/sve_bit_ops.hpp @@ -37,6 +37,36 @@ #include "sve_bitwise.hpp" +// bitwise_and two vectors +struct bitwise_and_vector_vector{ + template <typename T> + inline vector_t<T> operator()(const vector_t<T> &a, const vector_t<T> &b) + { + assert(a.size == b.size); + + int64_t i = 0; + vector_t<T> vres(a.size); + svbool_t ig = svetype<T>::svwhile(i, vres.size); + + std::cout << "[SVE vector (bitwise and) used]" << endl; + do + { + typename svetype<T>::vec x0 = svetype<T>::vload(ig, (const T *) &a.elem[i]); + typename svetype<T>::vec x1 = svetype<T>::vload(ig, (const T *) &b.elem[i]); + + typename svetype<T>::vec res = svetype<T>::and_z(ig, x0, x1); + + svetype<T>::vstore(ig, (T *) &vres.elem[i], res); + + i += svetype<T>::count(); + ig = svetype<T>::svwhile(i, vres.size); + } + while (svptest_any(svetype<T>::svtrue(), ig)); + + return vres; + } +}; + // bitwise_or two vectors struct bitwise_or_vector_vector{ template <typename T> @@ -48,7 +78,7 @@ struct bitwise_or_vector_vector{ vector_t<T> vres(a.size); svbool_t ig = svetype<T>::svwhile(i, vres.size); - std::cout << "[SVE vector (SUM) used]" << endl; + std::cout << "[SVE vector (bitwise or) used]" << endl; do { typename svetype<T>::vec x0 = svetype<T>::vload(ig, (const T *) &a.elem[i]); @@ -67,6 +97,96 @@ struct bitwise_or_vector_vector{ } }; +// bitwise_xor two vectors +struct bitwise_xor_vector_vector{ + template <typename T> + inline vector_t<T> operator()(const vector_t<T> &a, const vector_t<T> &b) + { + assert(a.size == b.size); + + int64_t i = 0; + vector_t<T> vres(a.size); + svbool_t ig = svetype<T>::svwhile(i, vres.size); + + std::cout << "[SVE vector (bitwise xor) used]" << endl; + do + { + typename svetype<T>::vec x0 = svetype<T>::vload(ig, (const T *) &a.elem[i]); + typename svetype<T>::vec x1 = svetype<T>::vload(ig, (const T *) &b.elem[i]); + + typename svetype<T>::vec res = svetype<T>::eor_z(ig, x0, x1); + + svetype<T>::vstore(ig, (T *) &vres.elem[i], res); + + i += svetype<T>::count(); + ig = svetype<T>::svwhile(i, vres.size); + } + while (svptest_any(svetype<T>::svtrue(), ig)); + + return vres; + } +}; + +// bitwise_not two vectors +struct bitwise_not_vector_vector{ + template <typename T> + inline vector_t<T> operator()(const vector_t<T> &a, const vector_t<T> &b) + { + assert(a.size == b.size); + + int64_t i = 0; + vector_t<T> vres(a.size); + svbool_t ig = svetype<T>::svwhile(i, vres.size); + + std::cout << "[SVE vector (bitwise not) used]" << endl; + do + { + typename svetype<T>::vec x0 = svetype<T>::vload(ig, (const T *) &a.elem[i]); + typename svetype<T>::vec x1 = svetype<T>::vload(ig, (const T *) &b.elem[i]); + + typename svetype<T>::vec res = svetype<T>::not_z(ig, x0, x1); + + svetype<T>::vstore(ig, (T *) &vres.elem[i], res); + + i += svetype<T>::count(); + ig = svetype<T>::svwhile(i, vres.size); + } + while (svptest_any(svetype<T>::svtrue(), ig)); + + return vres; + } +}; + +// bitwise_not two vectors +struct bitwise_not_vector_vector{ + template <typename T> + inline vector_t<T> operator()(const vector_t<T> &a, const vector_t<T> &b) + { + assert(a.size == b.size); + + int64_t i = 0; + vector_t<T> vres(a.size); + svbool_t ig = svetype<T>::svwhile(i, vres.size); + + std::cout << "[SVE vector (bitwise not) used]" << endl; + do + { + typename svetype<T>::vec x0 = svetype<T>::vload(ig, (const T *) &a.elem[i]); + typename svetype<T>::vec x1 = svetype<T>::vload(ig, (const T *) &b.elem[i]); + + typename svetype<T>::vec res = svetype<T>::not_z(ig, x0, x1); + + svetype<T>::vstore(ig, (T *) &vres.elem[i], res); + + i += svetype<T>::count(); + ig = svetype<T>::svwhile(i, vres.size); + } + while (svptest_any(svetype<T>::svtrue(), ig)); + + return vres; + } +}; + #endif #endif // SVE_BIT_OPS_HPP diff --git a/simd.hpp b/simd.hpp index fb0dba3ded9460b5469de80b21dede441ad428ba..3bbee824e87e227b202a83062d252c8dee8f6e50 100644 --- a/simd.hpp +++ b/simd.hpp @@ -72,6 +72,4 @@ using namespace std; #include "vector_overloading.hpp" #include "matrix_overloading.hpp" - - #endif // SIMD_HPP diff --git a/vector_test.x b/vector_test.x new file mode 100755 index 0000000000000000000000000000000000000000..6a93d8592d73df0bc002bce37f23492ae8660a42 Binary files /dev/null and b/vector_test.x differ