scid icon indicating copy to clipboard operation
scid copied to clipboard

Matrix slices have copy semantics, while row/column slices have view semantics

Open cristicbz opened this issue 13 years ago • 3 comments

This is a side effect of the fact row() and column() return views:

import std.exception, scid.matvec;

void main() {
    auto mat   = Matrix!double([ [1.,2.], [3., 4.] ]);  
    auto row   = mat[ 0 ][ 0 .. 2 ];
    auto col   = mat[ 0 .. 2 ][ 0 ];
    auto slice = mat[ 0 .. 1 ][ 0 .. 1 ];

    // Copy semantics of matrix slices:
    slice[ 0, 0 ] = 10.0;
    enforce( mat[ 0, 0 ] = 1. );

    // View semantics of row and column slices:
    row[ 0 ] = 100.;
    enforce( mat[ 0, 0 ] == 100. && col[ 0 ] == 100. );

    col[ 0 ] = 200.;
    enforce( mat[ 0, 0 ] == 200. && row[ 0 ] == 200. );
}

I'm thinking we should add a .dup property on view storage types that returns a copy of the area they are a view of, this will help with more issues actually and it might simplify the storage concepts: rather than having both a view() and a slice() method, storages could simply provide a view() method and slicing could be done (in BasicVector and BasicMatrix, not by the user) by calling view( ... ).dup .

cristicbz avatar Aug 20 '11 13:08 cristicbz

So .dup would just copy the BasicMatrix/BasicVector and increment the reference count? Or would it eagerly duplicate the underlying storage?

dsimcha avatar Aug 21 '11 02:08 dsimcha

Hmmm, well my idea was for it to simply create a copy of the storage that would share the same container (i.e. no eager copying), but you've actually pointed out an important point. In the case of strided vector views - for example the row of a column-major matrix, that has space between consecutive elements - .dup would have to perform an eager copy. There is no way to represent a strided array as a non-view vector right now. Other than performing this duplication on strided views, there's three solutions I see:

  1. Allow vectors to wrap strided blocks of memory. This would add quite a bit of complexity, but it is doable.
  2. Have any kind of matrix slicing return another matrix. That would return 1 x n and m x 1 matrices for row/column slices. This is a bit annoying as people might end up using a lot of row/column matrices which I expect to run quite a bit more slowly than the vectors. Not to mention the loss of static checking of operations between vectors and matrices.

cristicbz avatar Aug 21 '11 16:08 cristicbz

Option (2) is ugly and makes abstractions leaky. I'd suggest for the short term that we use eager copying and that we consider implementing (1) as a long-term todo. Eager copying might not be the worst thing in the world anyhow, because it packs the elements into consecutive memory addresses, resulting in better cache efficiency.

dsimcha avatar Aug 21 '11 17:08 dsimcha