kfrlib / kfr

Fast, modern C++ DSP framework, FFT, Sample Rate Conversion, FIR/IIR/Biquad Filters (SSE, AVX, AVX-512, ARM NEON)
https://www.kfrlib.com
GNU General Public License v2.0
1.66k stars 253 forks source link

is_infinite issue with Clang #181

Closed xkzl closed 1 year ago

xkzl commented 1 year ago

Hello @dancazarin ,

I try to embed KFR library in a program and I am facing some issues with the new definition for "is_infinity", here: https://github.com/kfrlib/kfr/blob/4e2e8253b304381ed95ea70cd2d73742be40bb67/include/kfr/base/expression.hpp#L197

It seems to be related to this issue: https://stackoverflow.com/questions/44995196/static-member-access-in-constant-expressions

Any possible fix or alternative idea ?

dancazarin commented 1 year ago

Hello Marco,

I don't think it's the issue discussed on stackoverflow. The stackoverflow snippet shows that function argument s can't be used to call static function in constexpr context. It makes sense because s is a runtime value there. But the type S can be used in the same code for both GCC and Clang. This issue indeed occured during development of KFR and it's the cause of strange val_of(decltype(t)()) construct that you may have seen in the KFR sources.

Here, in KFR, E is some type passed to template argument of is_infinite variable. I think is_infinite may work or don't work only in connection to what is passed to it. It is used in KFR with no problems if E is a class that have static constexpr function named get_shape. Do you call is_infinite in your code or does this issue happen deep in the KFR sources? What class is passed to is_infinite? Inspect this class so you are sure that get_shape is declared like this:

constexpr static shape<dims> get_shape() { return /* some constant or infinite_size */; }
dancazarin commented 1 year ago

Closed due to inactivity. Feel free to reopen if the problem still exists.

xkzl commented 11 months ago

Hello @dancazarin

Just got some dedicated time to try to tackle this issue I was facing. I just updated to KFR 5.1 and here are the precise error messages (just a sample):

kfr/5.1.0/include/kfr/base/expression.hpp:197:23: error: constexpr variable 'is_infinite<kfr::expression_concatenate<kfr::univector<kfr::complex<double>, 18446744073709551615> &, kfr::expression_function<kfr::fn::cconj, kfr::univector<kfr::complex<double>, 18446744073709551615> &>, 0>>' must be initialized by a constant expression
constexpr inline bool is_infinite = expression_traits<E>::get_shape().has_infinity();

kfr/5.1.0/include/kfr/base/univector.hpp:410:24: note: in instantiation of variable template specialization 'kfr::is_infinite<kfr::expression_concatenate<kfr::univector<kfr::complex<double>, 18446744073709551615> &, kfr::expression_function<kfr::fn::cconj, kfr::univector<kfr::complex<double>, 18446744073709551615> &>, 0>>' requested here
        static_assert(!is_infinite<Input>, "Dynamically sized vector requires finite input expression");
                       ^

I think this is basically not related to my code, but something must be wrong in my configuration.. I guess. I am just trying to link a dummy library skeleton with a cmake including KFR library.

dancazarin commented 11 months ago

As always, a minimal reproducible example can drastically speed up the search for the issue cause.

xkzl commented 11 months ago

Hello @dancazarin

While preparing the minimal example, I have found the origin of the issue. It came from my custom elliptic filter implementation. And it is now fixed. Sorry for bothering, thanks for helping !

xkzl commented 11 months ago

The conflict came from the use of kfr::univector<T> instead of zpk<T> in my implementation of elliptic filter. Definitely looking forward to use KFR6 !

univector<complex<T>> z = concatenate(z1, cconj(z2));
univector<complex<T>> p = concatenate(p1, cconj(p2));
T k = (product(-p) / product(-z)).real();

replaced by

zpk<T> result;
    result.z = concatenate(z1, cconj(z2));
    result.p = concatenate(p1, cconj(p2));
    result.k = (product(-result.p) / product(-result.z)).real();