diff --git a/CMakeLists.txt b/CMakeLists.txt index f78d2f97..862e641a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -40,6 +40,7 @@ include(sources.cmake) add_definitions(-D_ENABLE_EXTENDED_ALIGNED_STORAGE) option(ENABLE_TESTS "Enable tests and examples. This changes many compiler flags" OFF) +option(ENABLE_DFT "Enable DFT and related algorithms" ON) set(KFR_DFT_SRC ${CMAKE_CURRENT_SOURCE_DIR}/include/kfr/dft/impl/dft-src.cpp @@ -99,8 +100,10 @@ add_library(kfr INTERFACE) target_sources(kfr INTERFACE ${KFR_SRC}) target_include_directories(kfr INTERFACE include) -add_library(kfr_dft ${KFR_DFT_SRC}) -target_link_libraries(kfr_dft kfr) +if (ENABLE_DFT) + add_library(kfr_dft ${KFR_DFT_SRC}) + target_link_libraries(kfr_dft kfr) +endif() add_library(kfr_io ${KFR_IO_SRC}) target_link_libraries(kfr_io kfr) diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 3428a37d..f923f531 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -28,7 +28,12 @@ add_executable(window window.cpp) target_link_libraries(window kfr) add_executable(fir fir.cpp) -target_link_libraries(fir kfr kfr_dft) + +target_link_libraries(fir kfr) +if (ENABLE_DFT) + target_link_libraries(fir kfr_dft) + target_compile_definitions(fir PRIVATE -DHAVE_DFT) +endif () add_executable(sample_rate_conversion sample_rate_conversion.cpp) target_link_libraries(sample_rate_conversion kfr kfr_io) @@ -36,5 +41,7 @@ target_link_libraries(sample_rate_conversion kfr kfr_io) add_executable(sample_rate_converter sample_rate_converter.cpp) target_link_libraries(sample_rate_converter kfr kfr_io) -add_executable(dft dft.cpp) -target_link_libraries(dft kfr kfr_dft) +if (ENABLE_DFT) + add_executable(dft dft.cpp) + target_link_libraries(dft kfr kfr_dft) +endif () diff --git a/examples/fir.cpp b/examples/fir.cpp index c619ca51..169a7cf3 100644 --- a/examples/fir.cpp +++ b/examples/fir.cpp @@ -5,7 +5,9 @@ */ #include +#ifdef HAVE_DFT #include +#endif #include #include @@ -128,6 +130,7 @@ int main() plot_save("filtered_noise2", filtered_noise2, "title='Filtered noise 2', div_by_N=True"); #endif +#ifdef HAVE_DFT // -------------------------------------------------------------------------------------- // ---------------------- Convolution filter (optimized using DFT) ---------------------- // -------------------------------------------------------------------------------------- @@ -142,6 +145,7 @@ int main() #if PYTHON_IS_INSTALLED // Plot results, same as filtered_noise2 plot_save("filtered_noise3", filtered_noise3, "title='Filtered noise 3', div_by_N=True"); +#endif #endif return 0; diff --git a/include/kfr/base/memory.hpp b/include/kfr/base/memory.hpp index 3b7b1aa7..fd7e6c58 100644 --- a/include/kfr/base/memory.hpp +++ b/include/kfr/base/memory.hpp @@ -27,6 +27,7 @@ #include "read_write.hpp" #include "types.hpp" +#include #include #include diff --git a/include/kfr/base/pointer.hpp b/include/kfr/base/pointer.hpp index 6412ce24..e795ee0c 100644 --- a/include/kfr/base/pointer.hpp +++ b/include/kfr/base/pointer.hpp @@ -42,7 +42,7 @@ namespace internal template KFR_SINTRIN bool invoke_substitute(Expression& expr, expression_pointer&& new_pointer, - csize_t = csize_t{}); + csize_t = {}); } template diff --git a/include/kfr/base/simd_clang.hpp b/include/kfr/base/simd_clang.hpp index ab90009d..e4fe6492 100644 --- a/include/kfr/base/simd_clang.hpp +++ b/include/kfr/base/simd_clang.hpp @@ -29,6 +29,8 @@ #include "platform.hpp" #include "types.hpp" +#if CMT_COMPILER_CLANG + CMT_PRAGMA_MSVC(warning(push)) CMT_PRAGMA_MSVC(warning(disable : 4324)) @@ -344,3 +346,5 @@ constexpr inline vec()> concat(const vec&... vs) n } // namespace kfr CMT_PRAGMA_MSVC(warning(pop)) + +#endif diff --git a/include/kfr/base/univector.hpp b/include/kfr/base/univector.hpp index a02e8e92..592b31c3 100644 --- a/include/kfr/base/univector.hpp +++ b/include/kfr/base/univector.hpp @@ -374,6 +374,10 @@ struct univector : std::vector>, : std::vector>(other.begin(), other.end()) { } + template + constexpr univector(const std::vector&) = delete; + template + constexpr univector(std::vector&&) = delete; constexpr static bool size_known = false; constexpr static bool is_array = false; constexpr static bool is_array_ref = false; diff --git a/include/kfr/base/vec.hpp b/include/kfr/base/vec.hpp index 2fbf15e0..ea14349e 100644 --- a/include/kfr/base/vec.hpp +++ b/include/kfr/base/vec.hpp @@ -128,14 +128,14 @@ constexpr inline size_t scale_get_index(size_t counter, size_t groupsize, size_t } template -constexpr inline size_t scale_get_index() +constexpr inline size_t scale_get_index(csizes_t) { return scale_get_index(counter, groupsize, csizes_t().get(csize_t())); } template constexpr inline auto scale_impl(csizes_t ind, csizes_t cnt) noexcept - -> csizes_t()...> + -> csizes_t(ind)...> { return {}; } diff --git a/include/kfr/cometa.hpp b/include/kfr/cometa.hpp index f19db48c..7e4f3ef3 100644 --- a/include/kfr/cometa.hpp +++ b/include/kfr/cometa.hpp @@ -253,14 +253,15 @@ namespace ops { struct empty { + constexpr empty() noexcept {} }; } // namespace ops template struct cval_t : ops::empty { - constexpr static T value = val; - constexpr cval_t() noexcept = default; + constexpr static T value = val; + constexpr cval_t() noexcept {} constexpr cval_t(const cval_t&) noexcept = default; constexpr cval_t(cval_t&&) noexcept = default; typedef T value_type; @@ -359,6 +360,9 @@ struct get_nth<0, T, first, rest...> constexpr static T value = first; }; +template +struct get_nth_e; + template struct get_nth_type; @@ -406,7 +410,7 @@ struct cvals_t : ops::empty return &arr[0]; } template - constexpr cvals_t::value...> operator[]( + constexpr cvals_t::value...> operator[]( cvals_t) const { return {}; @@ -427,6 +431,15 @@ struct cvals_t : ops::empty constexpr static size_t size() { return 0; } }; +namespace details +{ +template +struct get_nth_e> +{ + constexpr static T value = get_nth::value; +}; +} // namespace details + template using cbools_t = cvals_t; @@ -1658,8 +1671,6 @@ constexpr bool is_sequence(csizes_t) return details::test_sequence(csizes_t()).value; } -#ifdef CMT_COMPILER_GNU - template constexpr cval_t cval{}; @@ -1727,7 +1738,6 @@ template constexpr cvalseq_t cuintseq{}; template constexpr indicesfor_t indicesfor{}; -#endif // Workaround for GCC 4.8 template diff --git a/include/kfr/cometa/array.hpp b/include/kfr/cometa/array.hpp index 2fc5c955..ef3d3ee4 100644 --- a/include/kfr/cometa/array.hpp +++ b/include/kfr/cometa/array.hpp @@ -51,8 +51,8 @@ struct array_ref constexpr array_ref(std::array& arr) noexcept : m_data(arr.data()), m_size(N) { } - template - constexpr array_ref(const std::vector& vec) noexcept : m_data(vec.data()), m_size(vec.size()) + template + constexpr array_ref(const std::vector& vec) noexcept : m_data(vec.data()), m_size(vec.size()) { } diff --git a/include/kfr/data/sincos.hpp b/include/kfr/data/sincos.hpp index f4115ca2..25984046 100644 --- a/include/kfr/data/sincos.hpp +++ b/include/kfr/data/sincos.hpp @@ -33,11 +33,7 @@ namespace data { template -constexpr T c_sin_table[65]; - -// data generated by mpfr -template <> -constexpr f32 c_sin_table[65] = { +constexpr T c_sin_table[65] = { /* sin(2*pi* 0/ 256) */ f32(0.0), /* sin(2*pi* 1/ 256) */ f32(0.02454122852291228803173452945928292506547), /* sin(2*pi* 2/ 256) */ f32(0.04906767432741801425495497694268265831475), diff --git a/include/kfr/dft/impl/dft-impl.hpp b/include/kfr/dft/impl/dft-impl.hpp index 08039d5a..bb9be49a 100644 --- a/include/kfr/dft/impl/dft-impl.hpp +++ b/include/kfr/dft/impl/dft-impl.hpp @@ -504,22 +504,25 @@ static void dft_stage_fixed_initialize(dft_stage* stage, size_t width) } } -template +template struct dft_stage_fixed_impl : dft_stage { dft_stage_fixed_impl(size_t radix_, size_t iterations, size_t blocks) { this->name = type_name(); - this->radix = radix; + this->radix = fixed_radix; this->blocks = blocks; this->repeats = iterations; this->recursion = false; // true; - this->data_size = - align_up((this->repeats * (radix - 1)) * sizeof(complex), platform<>::native_cache_alignment); + this->data_size = align_up((this->repeats * (fixed_radix - 1)) * sizeof(complex), + platform<>::native_cache_alignment); } - constexpr static size_t width = - radix >= 7 ? fft_vector_width / 2 : radix >= 4 ? fft_vector_width : fft_vector_width * 2; + constexpr static size_t rradix = fixed_radix; + + constexpr static size_t width = fixed_radix >= 7 + ? fft_vector_width / 2 + : fixed_radix >= 4 ? fft_vector_width : fft_vector_width * 2; virtual void do_initialize(size_t size) override final { dft_stage_fixed_initialize(this, width); } DFT_STAGE_FN @@ -529,40 +532,41 @@ struct dft_stage_fixed_impl : dft_stage const size_t Nord = this->repeats; const complex* twiddle = ptr_cast>(this->data); - const size_t N = Nord * this->radix; + const size_t N = Nord * fixed_radix; CMT_LOOP_NOUNROLL for (size_t b = 0; b < this->blocks; b++) { - butterflies(Nord, csize, csize, cbool, out, in, twiddle, Nord); + butterflies(Nord, csize, csize, cbool, out, in, twiddle, Nord); in += N; out += N; } } }; -template +template struct dft_stage_fixed_final_impl : dft_stage { dft_stage_fixed_final_impl(size_t radix_, size_t iterations, size_t blocks) { this->name = type_name(); - this->radix = radix; + this->radix = fixed_radix; this->blocks = blocks; this->repeats = iterations; this->recursion = false; this->can_inplace = false; } - constexpr static size_t width = - radix >= 7 ? fft_vector_width / 2 : radix >= 4 ? fft_vector_width : fft_vector_width * 2; + constexpr static size_t width = fixed_radix >= 7 + ? fft_vector_width / 2 + : fixed_radix >= 4 ? fft_vector_width : fft_vector_width * 2; DFT_STAGE_FN template KFR_INTRIN void do_execute(complex* out, const complex* in, u8*) { const size_t b = this->blocks; - const size_t size = b * radix; + const size_t size = b * fixed_radix; - butterflies(b, csize, csize, cbool, out, in, b); + butterflies(b, csize, csize, cbool, out, in, b); } }; diff --git a/include/kfr/dft/impl/dft-templates.hpp b/include/kfr/dft/impl/dft-templates.hpp index f8d4f959..59a8ef7a 100644 --- a/include/kfr/dft/impl/dft-templates.hpp +++ b/include/kfr/dft/impl/dft-templates.hpp @@ -24,6 +24,7 @@ See https://www.kfrlib.com for details. */ +#ifdef FLOAT #include "../fft.hpp" namespace kfr @@ -42,3 +43,5 @@ template void dft_plan_real::from_fmt(kfr::complex* out, const kfr template void dft_plan_real::to_fmt(kfr::complex* out, kfr::dft_pack_format fmt) const; } // namespace kfr + +#endif diff --git a/include/kfr/dft/impl/ft.hpp b/include/kfr/dft/impl/ft.hpp index fd649ec6..b04026b1 100644 --- a/include/kfr/dft/impl/ft.hpp +++ b/include/kfr/dft/impl/ft.hpp @@ -1677,15 +1677,15 @@ KFR_INTRIN void spec_generic_butterfly_w(csize_t, cbool_t, compl template > KFR_INTRIN void generic_butterfly(size_t radix, cbool_t, complex* out, const complex* in, - complex* temp, const complex* twiddle, Tstride ostride = Tstride{}) + complex* temp, const complex* twiddle, Tstride ostride = {}) { - constexpr size_t width = platform::vector_width; - cswitch(csizes_t<11, 13>(), radix, [&](auto radix_) CMT_INLINE_LAMBDA { + constexpr size_t width = platform::vector_width; spec_generic_butterfly_w(radix_, cbool_t(), out, in, twiddle, ostride); }, [&]() CMT_INLINE_LAMBDA { + constexpr size_t width = platform::vector_width; generic_butterfly_w(radix, cbool_t(), out, in, twiddle, ostride); }); } diff --git a/include/kfr/ext/double_double.hpp b/include/kfr/ext/double_double.hpp index 4870f294..4ccc2d12 100644 --- a/include/kfr/ext/double_double.hpp +++ b/include/kfr/ext/double_double.hpp @@ -38,10 +38,17 @@ struct double_double const double cc = ((((x.hi - u.hi) - u.lo) + x.lo) - c * y.lo) / y.hi; return { c, cc }; } - constexpr bool isinf() const noexcept { return std::isinf(hi); } - constexpr bool isnan() const noexcept { return std::isnan(hi) || std::isnan(lo); } - constexpr double ulp(float value) const noexcept +#if defined _MSC_VER && !defined __clang__ +#define DOUBLEDOUBLE_CONSTEXPR +#else +#define DOUBLEDOUBLE_CONSTEXPR constexpr +#endif + + DOUBLEDOUBLE_CONSTEXPR bool isinf() const noexcept { return std::isinf(hi); } + DOUBLEDOUBLE_CONSTEXPR bool isnan() const noexcept { return std::isnan(hi) || std::isnan(lo); } + + DOUBLEDOUBLE_CONSTEXPR double ulp(float value) const noexcept { if (std::isnan(value) && isnan()) return 0.0; @@ -51,7 +58,7 @@ struct double_double return 1.0; return (double_double(value) - *this) / double_double(std::nexttoward(value, 0.0)); } - constexpr double ulp(double value) const noexcept + DOUBLEDOUBLE_CONSTEXPR double ulp(double value) const noexcept { if (std::isnan(value) && isnan()) return 0.0; diff --git a/include/kfr/io/audiofile.hpp b/include/kfr/io/audiofile.hpp index 7c5e0482..46a34ffc 100644 --- a/include/kfr/io/audiofile.hpp +++ b/include/kfr/io/audiofile.hpp @@ -64,6 +64,9 @@ struct audio_format struct audio_format_and_length : audio_format { using audio_format::audio_format; +#ifdef CMT_COMPILER_MSVC + audio_format_and_length() noexcept {} +#endif audio_format_and_length(const audio_format& fmt) : audio_format(fmt) {} imax length = 0; // in samples diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index c3836bc4..06912885 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -41,10 +41,15 @@ set(ALL_TESTS_CPP all_tests.cpp base_test.cpp complex_test.cpp - dft_test.cpp dsp_test.cpp expression_test.cpp - intrinsic_test.cpp io_test.cpp resampler_test.cpp) + intrinsic_test.cpp + io_test.cpp + resampler_test.cpp) + +if (ENABLE_DFT) + list(APPEND ALL_TESTS_CPP dft_test.cpp) +endif () if (MPFR_FOUND AND GMP_FOUND) list(APPEND ALL_TESTS_CPP transcendental_test.cpp) @@ -54,8 +59,10 @@ endif () add_executable(all_tests ${ALL_TESTS_CPP}) target_compile_definitions(all_tests PRIVATE KFR_NO_MAIN) -target_link_libraries(all_tests kfr kfr_dft) -target_link_libraries(all_tests kfr kfr_dft kfr_io) +if (ENABLE_DFT) + target_link_libraries(all_tests kfr kfr_dft) +endif () +target_link_libraries(all_tests kfr kfr_io) if (MPFR_FOUND AND GMP_FOUND) add_definitions(-DHAVE_MPFR) @@ -65,7 +72,10 @@ endif () function(add_x86_test NAME FLAGS) separate_arguments(FLAGS) - add_executable(all_tests_${NAME} ${ALL_TESTS_CPP} ${KFR_DFT_SRC} ${KFR_IO_SRC}) + add_executable(all_tests_${NAME} ${ALL_TESTS_CPP} ${KFR_IO_SRC}) + if (ENABLE_DFT) + target_sources(all_tests_${NAME} PRIVATE ${KFR_DFT_SRC}) + endif () target_compile_options(all_tests_${NAME} PRIVATE ${FLAGS}) target_compile_definitions(all_tests_${NAME} PRIVATE KFR_NO_MAIN) target_link_libraries(all_tests_${NAME} kfr)