xtensor-stack / xtensor

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

Coherent API between xtensor and xtensor-python #1258

Closed semin-park closed 5 years ago

semin-park commented 5 years ago

Currently,xt::pytensor<int, 2> py({2,2}); creates an empty tensor with shape (2,2).

However, xt::xtensor<int, 2> cxx({2,2}); throws an error because here, xtensor is trying to initialize cxx with the values of {2,2}. If you wanted to achieve the above, you should do xt::xtensor<int, 2> cxx = xt::empty<int>({2,2}).

In code,

int main() {

    Py_Initialize();
    xt::import_numpy();

    xt::pytensor<int, 2> py({2,2});                   // This is the same as 
    xt::xtensor<int, 2> cxx = xt::empty<int>({2,2}); // this.

    cout << py << endl;
    cout << cxx << endl;

    Py_Finalize();

    return 0;
}

returns (as an example)

{{          0,  -805306368},
 { -961214798,  1073743864}}
{{         0, -805306368},
 {         0, -805306368}}

It'd be nice if these APIs were coherent!

wolfv commented 5 years ago

Hi,

thanks for spotting this issue. That should indeed no be the case! A pyarray / pytensor should also have a initializer_list constructor that fills the array with the values. We also have a special, named constructor pyarray<double>::from_shape({x, y}); that does the same as creation with empty (actually, it's more performant because you'd use the correct type right away).

wolfv commented 5 years ago

Ok, I think I see why this works. We only have a nested_initializer_list constructor for the right dimensions for pytensor. So when you pass a 1D initializer list it will implicitly convert the initializer list to a shape_type and use that overload.

semin-park commented 5 years ago

Aha! Didn't know ::from_shape({x,y}) existed! Good to know :)

Since this issue is about coherent APIs, could I suggest one more thing??

xt::argwhere returns vectors of arrays of type unsigned long for xtensor, but long for pytensor. It'd be nice if both of them used just one or the other.

SylvainCorlay commented 5 years ago

xt::argwhere returns vectors of arrays of type unsigned long for xtensor, but long for pytensor. It'd be nice if both of them used just one or the other.

The reason for the the difference xt::argwhere returns containers of the integral type used to access elements of a given array.

semin-park commented 5 years ago

Aha, I see. That's a little unfortunate..

JohanMabille commented 5 years ago

On current master, xt::xtensor<int, 2> cxx({2,2}); creates an empty tensor with shape (2, 2) (tested on GCC 7 and VS 2015). Do you still have the issue?