xtensor-stack / xtensor

C++ tensors with broadcasting and lazy computing
BSD 3-Clause "New" or "Revised" License
3.38k stars 400 forks source link

No matching member function for call to 'simd_apply' #2105

Open mathiasgredal opened 4 years ago

mathiasgredal commented 4 years ago

I was trying to convert code from python to c++, when I ran into an issue, that I think might be a bug.

Python code:

import numpy as np

a = np.array([1, 2, 3, 4, 5])
b = np.array([1, 1, -1, 1, -1])

a[b<=0] = 0

print(a) # [1 2 0 4 0]

C++ code:

#include <iostream>
#define XTENSOR_USE_XSIMD
#include <xtensor/xarray.hpp>
#include <xtensor/xio.hpp>

int main() {
    xt::xarray<double> a { 1, 2, 3, 4, 5 };
    xt::xarray<double> b { 1, 1, -1, 1, -1 };

    xt::xarray<double> res = !(b <= 0) * a;

    std::cout << res << std::endl;
}

However when compiling the c++ code, I get the following errors:

- ./libs/xtensor/include/xtensor/xfunction.hpp:811: error: no matching member function for call to 'simd_apply'
         return m_f.simd_apply((std::get<I>(m_e)
                ~~~~^~~~~~~~~~
./libs/xtensor/include/xtensor/xfunction.hpp:1027: error: no matching member function for call to 'simd_apply'
        return (p_f->m_f.simd_apply)(std::get<I>(m_st). template step_simd<T>()...);
               ~~~~~~~~~~^~~~~~~~~~~

Here is the full compiler output: https://pastebin.com/TZZCfL6Z

My setup is:


One way to fix this error is to disable simd:

#include <iostream>
//#define XTENSOR_USE_XSIMD
#include <xtensor/xarray.hpp>
#include <xtensor/xio.hpp>

int main()
{
    xt::xarray<double> a { 1, 2, 3, 4, 5 };
    xt::xarray<double> b { 1, 1, -1, 1, -1 };

    xt::xarray<double> res = !(b <= 0) * a;

    std::cout << res << std::endl;
}

or to split the operation:

#include <iostream>
#define XTENSOR_USE_XSIMD
#include <xtensor/xarray.hpp>
#include <xtensor/xio.hpp>

int main()
{
    xt::xarray<double> a { 1, 2, 3, 4, 5 };
    xt::xarray<double> b { 1, 1, -1, 1, -1 };

    xt::xarray<double> res0 = !(b <= 0);

    xt::xarray<double> res1 = res0 * a;

    std::cout << res1 << std::endl;
}
JohanMabille commented 4 years ago

Thanks for reporting, this is indeed a bug.

Another possibility to avoid splitting the operation (and which avoids mixing boolean value and arithmetic operations) is to use the where function:

xt::xarray<double> res = xt::where(!(b <= 0), a, 0.);