Date: Fri, 18 Dec 2020 14:07:38 +0100

Hi,

Thank you all for your answers and interest in reading the proposal. As you

all seemed to agree on, the idea of a possible std::bittensor (or more

generally multidimensional containers) seems something that is not coming

in to the standard soon. There are as you said various approaches regarding

the use of multidimensional containers, and none seems to be standardized.

I will hope that something along these lines will eventually find it's way

into the standard, but for the time being libraries is what we got.

Regards,

Pablo Ruiz.

El vie, 18 dic 2020 a las 0:01, Jean-Baptiste Vallon Hoarau via

Std-Proposals (<std-proposals_at_[hidden]>) escribió:

> Hello,

>

> As Arthur said, i don't really see the need for this in the standard

> library.

> More generally : there is not as of yet a defacto standard for

> multidimensional containers, which is why i don't think we're going to get

> mdspan anytime soon. Case in point : a very popular md container library in

> the scientific C++ community is the xtensor library, and in it dimensions

> are handled in a very different way (one type for static shape, one type

> for static rank, one type fully dynamic, everything is flatly iterable)

> than the mdspan proposal.

> AFAIK nothing has been written on the pros and cons of both approaches.

>

> -Jean-Baptiste

>

> Le mar. 15 déc. 2020 à 01:06, Tony V E via Std-Proposals <

> std-proposals_at_[hidden]> a écrit :

>

>> Example code using bittensor might both explain the API and show

>> motivation for its existence.

>>

>>

>> Sent from my BlackBerry portable Babbage Device

>> *From: *Pablo Ruiz via Std-Proposals

>> *Sent: *Monday, December 14, 2020 2:23 PM

>> *To: *std-proposals_at_[hidden]

>> *Reply To: *std-proposals_at_[hidden]

>> *Cc: *Pablo Ruiz

>> *Subject: *[std-proposals] Arbitrary dimensional bittensor extending

>> bitset.

>>

>> Hi everyone,

>>

>> These past days I have been playing with some bit manipulation by using

>> the c++20 std and extending from it.

>> What I have found is the nice templated class std::bitset<N> and the

>> utility functions in the numerics library (added in c++20), if there is

>> anything more in the standard let me know.

>> What I would want to propose is for an extension, you could say a

>> generalization, of this std::bitset class to arbitrary dimensions. Namely

>> what I have called a bittensor. The idea would be to use the already

>> existing std::bitset for storing the data and defining over it an easy to

>> use interface for dealing with n-dimensional binary tensors, instead of

>> relying in manual bit fiddling (that one should also be able to use) one

>> could transform this tensors in a higher-level way, with the same

>> performance and size (this would be the ideal).

>>

>> Here I put a very simple sketch of what I think it should look like:

>>

>>

>> ___________________________________________________________________________

>>

>> template<std::size_t... N_i>

>> struct bittensor

>> {

>> std::bitset< (... * N_i) > _data;

>> constexpr static std::size_t _dims[] = {N_i ... };

>> constexpr bittensor () noexcept {};

>> constexpr bittensor (const std::bitset< (... * N_i) >& _val) noexcept

>> : _data(_val) {};

>> constexpr bittensor (const bittensor< N_i ... >& bt) noexcept :

>> _data(bt._data) {};

>> template<typename T>

>> constexpr bittensor (const T& _val) noexcept

>> {_data = std::bitset< (... * N_i) > (_val);}

>> //TODO -> specify types of constructor as in bitset or just

>> // remain with this general templated constructor that

>> // seems to work as expected.

>>

>> //Now come the operators defined on the class bittensor.

>> //Mainly this is a wrapper that just sends the job

>> //to the 1d version bitset that we are using as _data.

>> constexpr inline bittensor& operator&= (const bittensor& rhs)

>> noexcept { _data &= rhs._data; return *this;};

>> constexpr inline bittensor& operator|= (const bittensor& rhs)

>> noexcept { _data |= rhs._data; return *this;};

>> constexpr inline bittensor& operator^= (const bittensor& rhs)

>> noexcept { _data ^= rhs._data; return *this;};

>> constexpr inline bittensor& operator<<= (std::size_t pos) noexcept {

>> _data <<= pos; return *this;};

>> constexpr inline bittensor& operator>>= (std::size_t pos) noexcept {

>> _data >>= pos; return *this;};

>> constexpr inline bittensor operator~() const noexcept { return

>> bittensor< N_i ... > (~_data);};

>> constexpr inline bittensor operator<< (std::size_t pos) const

>> noexcept { return bittensor< N_i ... > (_data << pos);};

>> constexpr inline bittensor operator>> (std::size_t pos) const

>> noexcept { return bittensor< N_i ... > (_data >> pos);};

>> constexpr inline bool operator== (const bittensor& rhs) const

>> noexcept { return _data == rhs._data;};

>> constexpr inline bool operator!= (const bittensor& rhs) const

>> noexcept { return _data != rhs._data;};

>>

>> //Bit access, mainly the ones given by the bitset class

>> constexpr inline bool operator[] (std::size_t pos) const noexcept {

>> return _data[pos];};

>> constexpr inline std::size_t count () const noexcept { return

>> _data.count();};

>> constexpr inline std::size_t size () const noexcept { return

>> _data.size();};

>> constexpr inline bool test (std::size_t pos) const { return

>> _data.test(pos);};

>> constexpr inline bool any () const noexcept { return _data.any();};

>> constexpr inline bool none () const noexcept { return _data.none();};

>> constexpr inline bool all () const noexcept { return _data.all();};

>>

>> //Bit operations, mainly the ones given by the bitset class

>> constexpr inline bittensor& set () noexcept { _data.set(); return

>> *this;};

>> constexpr inline bittensor& set (std::size_t pos, bool val = true) {

>> _data.set(pos, val); return *this;};

>> constexpr inline bittensor& reset () noexcept { _data.reset(); return

>> *this;};

>> constexpr inline bittensor& reset (std::size_t pos) {

>> _data.reset(pos); return *this;};

>> constexpr inline bittensor& flip () noexcept { _data.flip(); return

>> *this;};

>> constexpr inline bittensor& flip (std::size_t pos) { _data.flip(pos);

>> return *this;};

>>

>> //Type conversions, mainly the ones given by the bitset class

>> constexpr inline unsigned long to_ulong () const { return

>> _data.to_ulong;};

>> constexpr inline unsigned long long to_ullong () const { return

>> _data.to_ullong;};

>> };

>> //non-member functions

>> template<std::size_t... N_i>

>> bittensor< N_i ... > operator& (const bittensor< N_i ... >& lhs, const

>> bittensor< N_i ... >& rhs) noexcept { return bittensor< N_i ... >

>> (lhs._data & rhs._data);}

>> template<std::size_t... N_i >

>> bittensor< N_i ... > operator| (const bittensor< N_i ... >& lhs, const

>> bittensor< N_i ... >& rhs) noexcept { return bittensor< N_i ... >

>> (lhs._data | rhs._data);}

>> template<std::size_t... N_i >

>> bittensor< N_i ... > operator^ (const bittensor< N_i ... >& lhs, const

>> bittensor< N_i ... >& rhs) noexcept { return bittensor< N_i ... >

>> (lhs._data ^ rhs._data);}

>> //And now come the iostream inserters and extractors for printing _data

>> (for the moment) to a certain stream

>> template<class charT, class traits, std::size_t... N_i>

>> std::basic_istream<charT, traits>& operator>> (std::basic_istream<charT,

>> traits>& is, bittensor< N_i ... >& rhs) { is >> rhs._data; return is;}

>> template<class charT, class traits, std::size_t... N_i>

>> std::basic_ostream<charT, traits>& operator<< (std::basic_ostream<charT,

>> traits>& os, const bittensor< N_i ... >& rhs) { os << rhs._data; return os;}

>>

>> //Add hashing support (based on the one given by bitset)

>> namespace std

>> {

>> template<std::size_t... N_i>

>> struct hash<bittensor< N_i ... >>

>> {

>> hash () noexcept {};

>> size_t operator() (const bittensor< N_i ... >& bt) const noexcept

>> { return hash< std::bitset< (... * N_i) > > ()(bt._data);}

>> };

>> template<>

>> struct hash<bittensor<0>>

>> {

>> hash () noexcept {};

>> size_t operator() (const bittensor<0>& bt) const noexcept {return

>> static_cast<size_t> (bt[0]);}

>> };

>> }

>>

>>

>>

>> ___________________________________________________________________________

>>

>> This is far from something really useful but I thought it may help to

>> introduce more explicitly the idea I have in mind. I hope there are not

>> much mistakes in the code (which compiles well in g++-10 as a .h file) and

>> to receive your thoughts about this extension of the std::bitset. I think

>> that it c++ wants to incorporate more math libraries into its standard (as

>> it seems to be doing) incorporating something like this is a must (look at

>> the numpy arrays for the python case for instance). And something that we

>> may further extend by templating on the 1d data structure (here

>> std::bitset) to an arbitrary vector-space-like structure, but this seems to

>> be a really harder project.

>>

>>

>> Regards,

>>

>>

>> Pablo Ruiz.

>>

>>

>>

>>

>>

>>

>>

>>

>> --

>> Std-Proposals mailing list

>> Std-Proposals_at_[hidden]

>> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals

>>

> --

> Std-Proposals mailing list

> Std-Proposals_at_[hidden]

> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals

>

Thank you all for your answers and interest in reading the proposal. As you

all seemed to agree on, the idea of a possible std::bittensor (or more

generally multidimensional containers) seems something that is not coming

in to the standard soon. There are as you said various approaches regarding

the use of multidimensional containers, and none seems to be standardized.

I will hope that something along these lines will eventually find it's way

into the standard, but for the time being libraries is what we got.

Regards,

Pablo Ruiz.

El vie, 18 dic 2020 a las 0:01, Jean-Baptiste Vallon Hoarau via

Std-Proposals (<std-proposals_at_[hidden]>) escribió:

> Hello,

>

> As Arthur said, i don't really see the need for this in the standard

> library.

> More generally : there is not as of yet a defacto standard for

> multidimensional containers, which is why i don't think we're going to get

> mdspan anytime soon. Case in point : a very popular md container library in

> the scientific C++ community is the xtensor library, and in it dimensions

> are handled in a very different way (one type for static shape, one type

> for static rank, one type fully dynamic, everything is flatly iterable)

> than the mdspan proposal.

> AFAIK nothing has been written on the pros and cons of both approaches.

>

> -Jean-Baptiste

>

> Le mar. 15 déc. 2020 à 01:06, Tony V E via Std-Proposals <

> std-proposals_at_[hidden]> a écrit :

>

>> Example code using bittensor might both explain the API and show

>> motivation for its existence.

>>

>>

>> Sent from my BlackBerry portable Babbage Device

>> *From: *Pablo Ruiz via Std-Proposals

>> *Sent: *Monday, December 14, 2020 2:23 PM

>> *To: *std-proposals_at_[hidden]

>> *Reply To: *std-proposals_at_[hidden]

>> *Cc: *Pablo Ruiz

>> *Subject: *[std-proposals] Arbitrary dimensional bittensor extending

>> bitset.

>>

>> Hi everyone,

>>

>> These past days I have been playing with some bit manipulation by using

>> the c++20 std and extending from it.

>> What I have found is the nice templated class std::bitset<N> and the

>> utility functions in the numerics library (added in c++20), if there is

>> anything more in the standard let me know.

>> What I would want to propose is for an extension, you could say a

>> generalization, of this std::bitset class to arbitrary dimensions. Namely

>> what I have called a bittensor. The idea would be to use the already

>> existing std::bitset for storing the data and defining over it an easy to

>> use interface for dealing with n-dimensional binary tensors, instead of

>> relying in manual bit fiddling (that one should also be able to use) one

>> could transform this tensors in a higher-level way, with the same

>> performance and size (this would be the ideal).

>>

>> Here I put a very simple sketch of what I think it should look like:

>>

>>

>> ___________________________________________________________________________

>>

>> template<std::size_t... N_i>

>> struct bittensor

>> {

>> std::bitset< (... * N_i) > _data;

>> constexpr static std::size_t _dims[] = {N_i ... };

>> constexpr bittensor () noexcept {};

>> constexpr bittensor (const std::bitset< (... * N_i) >& _val) noexcept

>> : _data(_val) {};

>> constexpr bittensor (const bittensor< N_i ... >& bt) noexcept :

>> _data(bt._data) {};

>> template<typename T>

>> constexpr bittensor (const T& _val) noexcept

>> {_data = std::bitset< (... * N_i) > (_val);}

>> //TODO -> specify types of constructor as in bitset or just

>> // remain with this general templated constructor that

>> // seems to work as expected.

>>

>> //Now come the operators defined on the class bittensor.

>> //Mainly this is a wrapper that just sends the job

>> //to the 1d version bitset that we are using as _data.

>> constexpr inline bittensor& operator&= (const bittensor& rhs)

>> noexcept { _data &= rhs._data; return *this;};

>> constexpr inline bittensor& operator|= (const bittensor& rhs)

>> noexcept { _data |= rhs._data; return *this;};

>> constexpr inline bittensor& operator^= (const bittensor& rhs)

>> noexcept { _data ^= rhs._data; return *this;};

>> constexpr inline bittensor& operator<<= (std::size_t pos) noexcept {

>> _data <<= pos; return *this;};

>> constexpr inline bittensor& operator>>= (std::size_t pos) noexcept {

>> _data >>= pos; return *this;};

>> constexpr inline bittensor operator~() const noexcept { return

>> bittensor< N_i ... > (~_data);};

>> constexpr inline bittensor operator<< (std::size_t pos) const

>> noexcept { return bittensor< N_i ... > (_data << pos);};

>> constexpr inline bittensor operator>> (std::size_t pos) const

>> noexcept { return bittensor< N_i ... > (_data >> pos);};

>> constexpr inline bool operator== (const bittensor& rhs) const

>> noexcept { return _data == rhs._data;};

>> constexpr inline bool operator!= (const bittensor& rhs) const

>> noexcept { return _data != rhs._data;};

>>

>> //Bit access, mainly the ones given by the bitset class

>> constexpr inline bool operator[] (std::size_t pos) const noexcept {

>> return _data[pos];};

>> constexpr inline std::size_t count () const noexcept { return

>> _data.count();};

>> constexpr inline std::size_t size () const noexcept { return

>> _data.size();};

>> constexpr inline bool test (std::size_t pos) const { return

>> _data.test(pos);};

>> constexpr inline bool any () const noexcept { return _data.any();};

>> constexpr inline bool none () const noexcept { return _data.none();};

>> constexpr inline bool all () const noexcept { return _data.all();};

>>

>> //Bit operations, mainly the ones given by the bitset class

>> constexpr inline bittensor& set () noexcept { _data.set(); return

>> *this;};

>> constexpr inline bittensor& set (std::size_t pos, bool val = true) {

>> _data.set(pos, val); return *this;};

>> constexpr inline bittensor& reset () noexcept { _data.reset(); return

>> *this;};

>> constexpr inline bittensor& reset (std::size_t pos) {

>> _data.reset(pos); return *this;};

>> constexpr inline bittensor& flip () noexcept { _data.flip(); return

>> *this;};

>> constexpr inline bittensor& flip (std::size_t pos) { _data.flip(pos);

>> return *this;};

>>

>> //Type conversions, mainly the ones given by the bitset class

>> constexpr inline unsigned long to_ulong () const { return

>> _data.to_ulong;};

>> constexpr inline unsigned long long to_ullong () const { return

>> _data.to_ullong;};

>> };

>> //non-member functions

>> template<std::size_t... N_i>

>> bittensor< N_i ... > operator& (const bittensor< N_i ... >& lhs, const

>> bittensor< N_i ... >& rhs) noexcept { return bittensor< N_i ... >

>> (lhs._data & rhs._data);}

>> template<std::size_t... N_i >

>> bittensor< N_i ... > operator| (const bittensor< N_i ... >& lhs, const

>> bittensor< N_i ... >& rhs) noexcept { return bittensor< N_i ... >

>> (lhs._data | rhs._data);}

>> template<std::size_t... N_i >

>> bittensor< N_i ... > operator^ (const bittensor< N_i ... >& lhs, const

>> bittensor< N_i ... >& rhs) noexcept { return bittensor< N_i ... >

>> (lhs._data ^ rhs._data);}

>> //And now come the iostream inserters and extractors for printing _data

>> (for the moment) to a certain stream

>> template<class charT, class traits, std::size_t... N_i>

>> std::basic_istream<charT, traits>& operator>> (std::basic_istream<charT,

>> traits>& is, bittensor< N_i ... >& rhs) { is >> rhs._data; return is;}

>> template<class charT, class traits, std::size_t... N_i>

>> std::basic_ostream<charT, traits>& operator<< (std::basic_ostream<charT,

>> traits>& os, const bittensor< N_i ... >& rhs) { os << rhs._data; return os;}

>>

>> //Add hashing support (based on the one given by bitset)

>> namespace std

>> {

>> template<std::size_t... N_i>

>> struct hash<bittensor< N_i ... >>

>> {

>> hash () noexcept {};

>> size_t operator() (const bittensor< N_i ... >& bt) const noexcept

>> { return hash< std::bitset< (... * N_i) > > ()(bt._data);}

>> };

>> template<>

>> struct hash<bittensor<0>>

>> {

>> hash () noexcept {};

>> size_t operator() (const bittensor<0>& bt) const noexcept {return

>> static_cast<size_t> (bt[0]);}

>> };

>> }

>>

>>

>>

>> ___________________________________________________________________________

>>

>> This is far from something really useful but I thought it may help to

>> introduce more explicitly the idea I have in mind. I hope there are not

>> much mistakes in the code (which compiles well in g++-10 as a .h file) and

>> to receive your thoughts about this extension of the std::bitset. I think

>> that it c++ wants to incorporate more math libraries into its standard (as

>> it seems to be doing) incorporating something like this is a must (look at

>> the numpy arrays for the python case for instance). And something that we

>> may further extend by templating on the 1d data structure (here

>> std::bitset) to an arbitrary vector-space-like structure, but this seems to

>> be a really harder project.

>>

>>

>> Regards,

>>

>>

>> Pablo Ruiz.

>>

>>

>>

>>

>>

>>

>>

>>

>> --

>> Std-Proposals mailing list

>> Std-Proposals_at_[hidden]

>> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals

>>

> --

> Std-Proposals mailing list

> Std-Proposals_at_[hidden]

> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals

>

Received on 2020-12-18 06:07:44