cotila icon indicating copy to clipboard operation
cotila copied to clipboard

Create compatibility between vectors and matrices

Open LucasChollet opened this issue 4 years ago • 10 comments

Vectors are now children of matrices, so they share the same set of properties. This hierarchy change allows the deletions of some duplicate code that was shared among the two classes.

Some algorithms have been rewritten to accept both vectors and matrices.

However, there is a regression, you now need to be explicit about both dimensions of the matrix when using iota().

LucasChollet avatar Oct 10 '21 20:10 LucasChollet

Thanks for the PR! Sorry I took so long to get to this, I've been pretty busy lately. I like the direction this is going. @drubinstein had an idea though, why not go one step further with template <typename T, std::size_t... Dimension> struct Tensor? What do you think?

calebzulawski avatar Oct 25 '21 01:10 calebzulawski

Thank you for this answer ! It could be neat, but is it possible to do it without dynamic allocation ?

LucasChollet avatar Oct 25 '21 13:10 LucasChollet

With the parameter pack the dimensions are still constants, so I think so.

calebzulawski avatar Oct 25 '21 14:10 calebzulawski

I may be missing something, but I was wondering about the creation of the array. The number of bracket pairs is determined by the number of parameters in the pack, and I don't know how to write it.

LucasChollet avatar Oct 25 '21 14:10 LucasChollet

Yeah, I'll have to think about that one more. I'm pretty sure it's possible, but not obvious to me either at the moment. I think it's probably possible with a recursive template.

calebzulawski avatar Oct 25 '21 14:10 calebzulawski

This works:

#include <cstdint>

template <typename T, std::size_t... Dimension>
struct data_impl;

template <typename T, std::size_t... Dimension>
using data_impl_t = typename data_impl<T, Dimension...>::type;

template <typename T>
struct data_impl<T> {
    using type = T;
};

template <typename T, std::size_t First, std::size_t... Dimension>
struct data_impl<T, First, Dimension...> {
    using type = data_impl_t<T, Dimension...>[First];
};

constexpr data_impl_t<int, 2, 3, 1> d {{{0}, {1}, {2}}, {{3}, {4}, {5}}}; // same as int[2][3][1]

calebzulawski avatar Oct 25 '21 22:10 calebzulawski

Woww ! It's truly impressive !

As another way to tackle this problem, isn't it possible to flatten the array ?

With your example, the element 4 (in position (1, 2, 0)) in d will just be array[2 * 1 + 3 * 2 + 0 * 1]

If this solution work, wouldn't it be simpler ?

LucasChollet avatar Oct 25 '21 23:10 LucasChollet

That is possible, but the problem is that makes initialization frustrating--you need to also initialize it in one giant array. Using a multidimensional array is more ergonomic, I think.

calebzulawski avatar Oct 26 '21 01:10 calebzulawski

Definitely agreeing for a simple initialization. First I thought to add a constructor to allow it, but I just realize that we will need your trick to write the constructor 😅 I will try to work on this later this week

LucasChollet avatar Oct 26 '21 11:10 LucasChollet

I'm pretty sure most of the current operations can be ported over pretty easily if the new Tensor class supports:

  • generate
  • elementwise
  • combine row and column of matrix to be a slice.

Was talking with @calebzulawski and we're thinking about keeping the scala, vector, 2D matrix specializations for now but rewrite them with Tensor as the backing datastructure.

drubinstein avatar Oct 26 '21 19:10 drubinstein