gonum / matrix

Matrix packages for the Go language [DEPRECATED]
446 stars 51 forks source link

reshape matrix function #384

Closed davmaz closed 8 years ago

davmaz commented 8 years ago

Currently, unless I'm mistaken, gonum/matrix does not support the "reshape" function. Here is the matlab/octave description:

deftypefn {Function File} {} reshape (@var{a}, @var{m}, @var{n})
 **Return a matrix with @var{m} rows and @var{n} columns whose elements are
 taken from the matrix @var{a}.  To decide how to order the elements,
 Octave pretends that the elements of a matrix are stored in column-major
 order (like Fortran arrays are stored).**

 For example,
 reshape ([1, 2, 3, 4], 2, 2)
      result{}  1  3
                2  4
 If the variable @code{do_fortran_indexing} is nonzero, the
 code{reshape} function is equivalent to

 retval = zeros (m, n);
 retval (:) = a;

I can give more details or examples if required.

sbinet commented 8 years ago

(I took the liberty to slightly reformat the original issue)

from the original golang-dev discussion, it seems the API would look like:

(*Dense).Reshape(a mat64.Matrix, r, c int)
kortschak commented 8 years ago

I'm leery of this - I don't like that MATLAB does it, but it does it (largely) because other defects in the language that are absent from Go. Can you describe a use case?

jonlawlor commented 8 years ago

In my experience it is typically used in matlab when you have two variables (often of non-numeric types, often of different types) and you want their array indexes to match. Very rarely I've been able to use it to transform a repeated operation on subsets of a vector into a single operation across all rows or all columns, much like a relational group by. In one particularly gnarly case I ended up using a 3 dimensional matrix for this purpose - probably the only time I had a real use for one.

The absence of 3d+ matrices and the fact that you can already reference matrix elements as a vector eliminates most of the use cases in my mind. People might have a habit of using reshape in particular applications though.

kortschak commented 8 years ago

That was pretty much my view. I really don't think we should be fostering habits born of other languages. If a reshape truly needed, it's not hard to write (untested):

func reshape(m mat64.Matrix, r, c int) *mat.Dense {
    mr, mc := m.Dims()
    if mr*mc != r*c {
        panic(matrix.ErrShape)
    }
    var r mat64.Dense
    r.Clone(m)
    raw := r.RawMatrix()
    raw.Rows = r
    raw.Cols = c
    raw.Stride = c
    r.SetRawMatrix(raw)
    return &r
}
btracey commented 8 years ago

My main uses of reshape were to turn linear arrays into matrices, and to do tricky things because for loops were slow. The latter isn't really necessary, and the former we support through NewDense.

@davmaz what cases do you have?

davmaz commented 8 years ago

Yes, like you, I would use it to turn vectors (or linear arrays) into a matrix. I think Dan's suggestion will do what I need. Thanks!


From: Brendan Tracey [notifications@github.com] Sent: Wednesday, May 18, 2016 08:53 To: gonum/matrix Cc: davem@ltsnet.net; Mention Subject: Re: [gonum/matrix] reshape matrix function (#384)

My main uses of reshape were to turn linear arrays into matrices, and to do tricky things because for loops were slow. The latter isn't really necessary, and the former we support through NewDense.

@davmazhttps://github.com/davmaz what cases do you have?

� You are receiving this because you were mentioned. Reply to this email directly or view it on GitHubhttps://github.com/gonum/matrix/issues/384#issuecomment-220016777

btracey commented 8 years ago

Note that if you have linear, row-major data as a slice, NewDense acts as a reshape as well.

data := []float64{0,1,2,3,4,5}
m := mat64.NewDense(2, 3, data)
// m is
// [0 1 2]
// [3 4 5]
kortschak commented 8 years ago

Yes, this is the reason I don't like the idea of including a reshape function. It is actually a number of different things that are almost artificially lumped together in other languages. The snippet I posted previously for example is the general case, but allocates because it does not know if the matrix is a Dense and if it is whether the stride matches the column dimension; knowing that a matrix is a Dense and the stride matches the columns, the operation is a zero-allocation one.

Knowing what the background is for the operation improves the efficiency and covering all the cases increases (while not onerously, more than is justified) the complexity of a function that would live in mat64.

@davmaz I'd just use NewDense ad @btracey suggests (note that we do more complicated work in some initialisations for tests because the tests were written a long time ago and because we are ensuring very tight constraints on the inputs for testing purposes - flatten being the example).

davmaz commented 8 years ago

Thanks for the pointers. You all do awesome work with the matrix libraries and for the future of go!


From: Brendan Tracey [notifications@github.com] Sent: Wednesday, May 18, 2016 10:44 To: gonum/matrix Cc: davem@ltsnet.net; State change Subject: Re: [gonum/matrix] reshape matrix function (#384)

Note that if you have linear, row-major data as a slice, NewDense acts as a reshape as well.

data := []float64{0,1,2,3,4,5} m := mat64.NewDense(2, 3, data) // m is // [0 1 2] // [3 4 5]

� You are receiving this because you modified the open/close state. Reply to this email directly or view it on GitHubhttps://github.com/gonum/matrix/issues/384#issuecomment-220048773