nmatrix 0.0.6 → 0.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
 - data/.gitignore +2 -0
 - data/Gemfile +5 -0
 - data/History.txt +97 -0
 - data/Manifest.txt +34 -7
 - data/README.rdoc +13 -13
 - data/Rakefile +36 -26
 - data/ext/nmatrix/data/data.cpp +15 -2
 - data/ext/nmatrix/data/data.h +4 -0
 - data/ext/nmatrix/data/ruby_object.h +5 -14
 - data/ext/nmatrix/extconf.rb +3 -2
 - data/ext/nmatrix/{util/math.cpp → math.cpp} +296 -6
 - data/ext/nmatrix/math/asum.h +143 -0
 - data/ext/nmatrix/math/geev.h +82 -0
 - data/ext/nmatrix/math/gemm.h +267 -0
 - data/ext/nmatrix/math/gemv.h +208 -0
 - data/ext/nmatrix/math/ger.h +96 -0
 - data/ext/nmatrix/math/gesdd.h +80 -0
 - data/ext/nmatrix/math/gesvd.h +78 -0
 - data/ext/nmatrix/math/getf2.h +86 -0
 - data/ext/nmatrix/math/getrf.h +240 -0
 - data/ext/nmatrix/math/getri.h +107 -0
 - data/ext/nmatrix/math/getrs.h +125 -0
 - data/ext/nmatrix/math/idamax.h +86 -0
 - data/ext/nmatrix/{util → math}/lapack.h +60 -356
 - data/ext/nmatrix/math/laswp.h +165 -0
 - data/ext/nmatrix/math/long_dtype.h +52 -0
 - data/ext/nmatrix/math/math.h +1154 -0
 - data/ext/nmatrix/math/nrm2.h +181 -0
 - data/ext/nmatrix/math/potrs.h +125 -0
 - data/ext/nmatrix/math/rot.h +141 -0
 - data/ext/nmatrix/math/rotg.h +115 -0
 - data/ext/nmatrix/math/scal.h +73 -0
 - data/ext/nmatrix/math/swap.h +73 -0
 - data/ext/nmatrix/math/trsm.h +383 -0
 - data/ext/nmatrix/nmatrix.cpp +176 -152
 - data/ext/nmatrix/nmatrix.h +1 -2
 - data/ext/nmatrix/ruby_constants.cpp +9 -4
 - data/ext/nmatrix/ruby_constants.h +1 -0
 - data/ext/nmatrix/storage/dense.cpp +57 -41
 - data/ext/nmatrix/storage/list.cpp +52 -50
 - data/ext/nmatrix/storage/storage.cpp +59 -43
 - data/ext/nmatrix/storage/yale.cpp +352 -333
 - data/ext/nmatrix/storage/yale.h +4 -0
 - data/lib/nmatrix.rb +2 -2
 - data/lib/nmatrix/blas.rb +4 -4
 - data/lib/nmatrix/enumerate.rb +241 -0
 - data/lib/nmatrix/lapack.rb +54 -1
 - data/lib/nmatrix/math.rb +462 -0
 - data/lib/nmatrix/nmatrix.rb +210 -486
 - data/lib/nmatrix/nvector.rb +0 -62
 - data/lib/nmatrix/rspec.rb +75 -0
 - data/lib/nmatrix/shortcuts.rb +136 -108
 - data/lib/nmatrix/version.rb +1 -1
 - data/spec/blas_spec.rb +20 -12
 - data/spec/elementwise_spec.rb +22 -13
 - data/spec/io_spec.rb +1 -0
 - data/spec/lapack_spec.rb +197 -0
 - data/spec/nmatrix_spec.rb +39 -38
 - data/spec/nvector_spec.rb +3 -9
 - data/spec/rspec_monkeys.rb +29 -0
 - data/spec/rspec_spec.rb +34 -0
 - data/spec/shortcuts_spec.rb +14 -16
 - data/spec/slice_spec.rb +242 -186
 - data/spec/spec_helper.rb +19 -0
 - metadata +33 -5
 - data/ext/nmatrix/util/math.h +0 -2612
 
    
        data/ext/nmatrix/nmatrix.h
    CHANGED
    
    | 
         @@ -303,8 +303,7 @@ NM_DEF_STRUCT_POST(NMATRIX);  // }; 
     | 
|
| 
       303 
303 
     | 
    
         
             
              #define NM_STORAGE_DENSE(val)       ((struct NM_DENSE_STORAGE*)(NM_STORAGE(val)))
         
     | 
| 
       304 
304 
     | 
    
         
             
            #endif
         
     | 
| 
       305 
305 
     | 
    
         | 
| 
       306 
     | 
    
         
            -
            #define  
     | 
| 
       307 
     | 
    
         
            -
            #define NM_LIST_SRC(val)        (NM_STORAGE_LIST(val)->src)
         
     | 
| 
      
 306 
     | 
    
         
            +
            #define NM_SRC(val)             (NM_STORAGE(val)->src)
         
     | 
| 
       308 
307 
     | 
    
         
             
            #define NM_DIM(val)             (NM_STORAGE(val)->dim)
         
     | 
| 
       309 
308 
     | 
    
         
             
            #define NM_DTYPE(val)           (NM_STORAGE(val)->dtype)
         
     | 
| 
       310 
309 
     | 
    
         
             
            #define NM_ITYPE(val)           (NM_STORAGE_YALE(val)->itype)
         
     | 
| 
         @@ -9,8 +9,8 @@ 
     | 
|
| 
       9 
9 
     | 
    
         
             
            //
         
     | 
| 
       10 
10 
     | 
    
         
             
            // == Copyright Information
         
     | 
| 
       11 
11 
     | 
    
         
             
            //
         
     | 
| 
       12 
     | 
    
         
            -
            // SciRuby is Copyright (c) 2010 -  
     | 
| 
       13 
     | 
    
         
            -
            // NMatrix is Copyright (c)  
     | 
| 
      
 12 
     | 
    
         
            +
            // SciRuby is Copyright (c) 2010 - 2012, Ruby Science Foundation
         
     | 
| 
      
 13 
     | 
    
         
            +
            // NMatrix is Copyright (c) 2012, Ruby Science Foundation
         
     | 
| 
       14 
14 
     | 
    
         
             
            //
         
     | 
| 
       15 
15 
     | 
    
         
             
            // Please see LICENSE.txt for additional copyright notices.
         
     | 
| 
       16 
16 
     | 
    
         
             
            //
         
     | 
| 
         @@ -57,11 +57,12 @@ ID	nm_rb_real, 
     | 
|
| 
       57 
57 
     | 
    
         | 
| 
       58 
58 
     | 
    
         
             
            		nm_rb_row,
         
     | 
| 
       59 
59 
     | 
    
         
             
            		nm_rb_column,
         
     | 
| 
       60 
     | 
    
         
            -
             
     | 
| 
       61 
60 
     | 
    
         
             
            		nm_rb_add,
         
     | 
| 
       62 
61 
     | 
    
         
             
            		nm_rb_sub,
         
     | 
| 
       63 
62 
     | 
    
         
             
            		nm_rb_mul,
         
     | 
| 
       64 
63 
     | 
    
         
             
            		nm_rb_div,
         
     | 
| 
      
 64 
     | 
    
         
            +
                nm_rb_both,
         
     | 
| 
      
 65 
     | 
    
         
            +
                nm_rb_none,
         
     | 
| 
       65 
66 
     | 
    
         | 
| 
       66 
67 
     | 
    
         
             
            		nm_rb_negate,
         
     | 
| 
       67 
68 
     | 
    
         | 
| 
         @@ -84,6 +85,7 @@ VALUE cNMatrix, 
     | 
|
| 
       84 
85 
     | 
    
         
             
            			cNMatrix_LAPACK,
         
     | 
| 
       85 
86 
     | 
    
         | 
| 
       86 
87 
     | 
    
         
             
            			nm_eDataTypeError,
         
     | 
| 
      
 88 
     | 
    
         
            +
                  nm_eConvergenceError,
         
     | 
| 
       87 
89 
     | 
    
         
             
            			nm_eStorageTypeError;
         
     | 
| 
       88 
90 
     | 
    
         | 
| 
       89 
91 
     | 
    
         
             
            /*
         
     | 
| 
         @@ -127,9 +129,12 @@ void nm_init_ruby_constants(void) { 
     | 
|
| 
       127 
129 
     | 
    
         
             
            	nm_rb_lower             = rb_intern("lower");
         
     | 
| 
       128 
130 
     | 
    
         
             
            	nm_rb_unit              = rb_intern("unit");
         
     | 
| 
       129 
131 
     | 
    
         
             
            	nm_rb_nonunit           = rb_intern("nonunit");
         
     | 
| 
       130 
     | 
    
         
            -
             
     | 
| 
       131 
132 
     | 
    
         
             
            	nm_rb_hash              = rb_intern("hash");
         
     | 
| 
       132 
133 
     | 
    
         | 
| 
       133 
134 
     | 
    
         
             
            	nm_rb_column            = rb_intern("column");
         
     | 
| 
       134 
135 
     | 
    
         
             
            	nm_rb_row               = rb_intern("row");
         
     | 
| 
      
 136 
     | 
    
         
            +
             
     | 
| 
      
 137 
     | 
    
         
            +
              //Added by Ryan
         
     | 
| 
      
 138 
     | 
    
         
            +
              nm_rb_both              = rb_intern("both");
         
     | 
| 
      
 139 
     | 
    
         
            +
              nm_rb_none              = rb_intern("none");
         
     | 
| 
       135 
140 
     | 
    
         
             
            }
         
     | 
| 
         @@ -35,9 +35,11 @@ 
     | 
|
| 
       35 
35 
     | 
    
         
             
             * Project Includes
         
     | 
| 
       36 
36 
     | 
    
         
             
             */
         
     | 
| 
       37 
37 
     | 
    
         
             
            // #include "types.h"
         
     | 
| 
       38 
     | 
    
         
            -
            #include "util/math.h"
         
     | 
| 
       39 
     | 
    
         
            -
             
     | 
| 
       40 
38 
     | 
    
         
             
            #include "data/data.h"
         
     | 
| 
      
 39 
     | 
    
         
            +
            #include "math/long_dtype.h"
         
     | 
| 
      
 40 
     | 
    
         
            +
            #include "math/gemm.h"
         
     | 
| 
      
 41 
     | 
    
         
            +
            #include "math/gemv.h"
         
     | 
| 
      
 42 
     | 
    
         
            +
            #include "math/math.h"
         
     | 
| 
       41 
43 
     | 
    
         
             
            #include "common.h"
         
     | 
| 
       42 
44 
     | 
    
         
             
            #include "dense.h"
         
     | 
| 
       43 
45 
     | 
    
         | 
| 
         @@ -73,6 +75,30 @@ namespace nm { namespace dense_storage { 
     | 
|
| 
       73 
75 
     | 
    
         
             
              template <typename DType>
         
     | 
| 
       74 
76 
     | 
    
         
             
              bool is_symmetric(const DENSE_STORAGE* mat, int lda);
         
     | 
| 
       75 
77 
     | 
    
         | 
| 
      
 78 
     | 
    
         
            +
             
     | 
| 
      
 79 
     | 
    
         
            +
              /*
         
     | 
| 
      
 80 
     | 
    
         
            +
               * Recursive slicing for N-dimensional matrix.
         
     | 
| 
      
 81 
     | 
    
         
            +
               */
         
     | 
| 
      
 82 
     | 
    
         
            +
              template <typename LDType, typename RDType>
         
     | 
| 
      
 83 
     | 
    
         
            +
              static void slice_copy(DENSE_STORAGE *dest, const DENSE_STORAGE *src, size_t* lengths, size_t pdest, size_t psrc, size_t n) {
         
     | 
| 
      
 84 
     | 
    
         
            +
                if (src->dim - n > 1) {
         
     | 
| 
      
 85 
     | 
    
         
            +
                  for (size_t i = 0; i < lengths[n]; ++i) {
         
     | 
| 
      
 86 
     | 
    
         
            +
                    slice_copy<LDType,RDType>(dest, src, lengths,
         
     | 
| 
      
 87 
     | 
    
         
            +
                               pdest + dest->stride[n]*i,
         
     | 
| 
      
 88 
     | 
    
         
            +
                               psrc + src->stride[n]*i,
         
     | 
| 
      
 89 
     | 
    
         
            +
                               n + 1);
         
     | 
| 
      
 90 
     | 
    
         
            +
                  }
         
     | 
| 
      
 91 
     | 
    
         
            +
                } else {
         
     | 
| 
      
 92 
     | 
    
         
            +
                  for (size_t p = 0; p < dest->shape[n]; ++p) {
         
     | 
| 
      
 93 
     | 
    
         
            +
                    reinterpret_cast<LDType*>(dest->elements)[p+pdest] = reinterpret_cast<RDType*>(src->elements)[p+psrc];
         
     | 
| 
      
 94 
     | 
    
         
            +
                  }
         
     | 
| 
      
 95 
     | 
    
         
            +
                  /*memcpy((char*)dest->elements + pdest*DTYPE_SIZES[dest->dtype],
         
     | 
| 
      
 96 
     | 
    
         
            +
                      (char*)src->elements + psrc*DTYPE_SIZES[src->dtype],
         
     | 
| 
      
 97 
     | 
    
         
            +
                      dest->shape[n]*DTYPE_SIZES[dest->dtype]); */
         
     | 
| 
      
 98 
     | 
    
         
            +
                }
         
     | 
| 
      
 99 
     | 
    
         
            +
             
     | 
| 
      
 100 
     | 
    
         
            +
              }
         
     | 
| 
      
 101 
     | 
    
         
            +
             
     | 
| 
       76 
102 
     | 
    
         
             
            }} // end of namespace nm::dense_storage
         
     | 
| 
       77 
103 
     | 
    
         | 
| 
       78 
104 
     | 
    
         | 
| 
         @@ -163,12 +189,12 @@ void nm_dense_storage_delete(STORAGE* s) { 
     | 
|
| 
       163 
189 
     | 
    
         
             
              if (s) {
         
     | 
| 
       164 
190 
     | 
    
         
             
                DENSE_STORAGE* storage = (DENSE_STORAGE*)s;
         
     | 
| 
       165 
191 
     | 
    
         
             
                if(storage->count-- == 1) {
         
     | 
| 
       166 
     | 
    
         
            -
                   
     | 
| 
       167 
     | 
    
         
            -
                   
     | 
| 
       168 
     | 
    
         
            -
                   
     | 
| 
      
 192 
     | 
    
         
            +
                  xfree(storage->shape);
         
     | 
| 
      
 193 
     | 
    
         
            +
                  xfree(storage->offset);
         
     | 
| 
      
 194 
     | 
    
         
            +
                  xfree(storage->stride);
         
     | 
| 
       169 
195 
     | 
    
         
             
                  if (storage->elements != NULL) // happens with dummy objects
         
     | 
| 
       170 
     | 
    
         
            -
                     
     | 
| 
       171 
     | 
    
         
            -
                   
     | 
| 
      
 196 
     | 
    
         
            +
                    xfree(storage->elements);
         
     | 
| 
      
 197 
     | 
    
         
            +
                  xfree(storage);
         
     | 
| 
       172 
198 
     | 
    
         
             
                }
         
     | 
| 
       173 
199 
     | 
    
         
             
              }
         
     | 
| 
       174 
200 
     | 
    
         
             
            }
         
     | 
| 
         @@ -181,9 +207,9 @@ void nm_dense_storage_delete_ref(STORAGE* s) { 
     | 
|
| 
       181 
207 
     | 
    
         
             
              if (s) {
         
     | 
| 
       182 
208 
     | 
    
         
             
                DENSE_STORAGE* storage = (DENSE_STORAGE*)s;
         
     | 
| 
       183 
209 
     | 
    
         
             
                nm_dense_storage_delete( reinterpret_cast<STORAGE*>(storage->src) );
         
     | 
| 
       184 
     | 
    
         
            -
                 
     | 
| 
       185 
     | 
    
         
            -
                 
     | 
| 
       186 
     | 
    
         
            -
                 
     | 
| 
      
 210 
     | 
    
         
            +
                xfree(storage->shape);
         
     | 
| 
      
 211 
     | 
    
         
            +
                xfree(storage->offset);
         
     | 
| 
      
 212 
     | 
    
         
            +
                xfree(storage);
         
     | 
| 
       187 
213 
     | 
    
         
             
              }
         
     | 
| 
       188 
214 
     | 
    
         
             
            }
         
     | 
| 
       189 
215 
     | 
    
         | 
| 
         @@ -367,6 +393,16 @@ VALUE nm_dense_each(VALUE nmatrix) { 
     | 
|
| 
       367 
393 
     | 
    
         
             
            }
         
     | 
| 
       368 
394 
     | 
    
         | 
| 
       369 
395 
     | 
    
         | 
| 
      
 396 
     | 
    
         
            +
            /*
         
     | 
| 
      
 397 
     | 
    
         
            +
             * Non-templated version of nm::dense_storage::slice_copy
         
     | 
| 
      
 398 
     | 
    
         
            +
             */
         
     | 
| 
      
 399 
     | 
    
         
            +
            static void slice_copy(DENSE_STORAGE *dest, const DENSE_STORAGE *src, size_t* lengths, size_t pdest, size_t psrc, size_t n) {
         
     | 
| 
      
 400 
     | 
    
         
            +
              NAMED_LR_DTYPE_TEMPLATE_TABLE(slice_copy_table, nm::dense_storage::slice_copy, void, DENSE_STORAGE*, const DENSE_STORAGE*, size_t*, size_t, size_t, size_t)
         
     | 
| 
      
 401 
     | 
    
         
            +
             
     | 
| 
      
 402 
     | 
    
         
            +
              slice_copy_table[dest->dtype][src->dtype](dest, src, lengths, pdest, psrc, n);
         
     | 
| 
      
 403 
     | 
    
         
            +
            }
         
     | 
| 
      
 404 
     | 
    
         
            +
             
     | 
| 
      
 405 
     | 
    
         
            +
             
     | 
| 
       370 
406 
     | 
    
         
             
            /*
         
     | 
| 
       371 
407 
     | 
    
         
             
             * Get a slice or one element, using copying.
         
     | 
| 
       372 
408 
     | 
    
         
             
             *
         
     | 
| 
         @@ -374,17 +410,16 @@ VALUE nm_dense_each(VALUE nmatrix) { 
     | 
|
| 
       374 
410 
     | 
    
         
             
             */
         
     | 
| 
       375 
411 
     | 
    
         
             
            void* nm_dense_storage_get(STORAGE* storage, SLICE* slice) {
         
     | 
| 
       376 
412 
     | 
    
         
             
              DENSE_STORAGE* s = (DENSE_STORAGE*)storage;
         
     | 
| 
       377 
     | 
    
         
            -
              DENSE_STORAGE* ns;
         
     | 
| 
       378 
413 
     | 
    
         | 
| 
       379 
414 
     | 
    
         
             
              if (slice->single)
         
     | 
| 
       380 
415 
     | 
    
         
             
                return (char*)(s->elements) + nm_dense_storage_pos(s, slice->coords) * DTYPE_SIZES[s->dtype];
         
     | 
| 
       381 
     | 
    
         
            -
              else { 
     | 
| 
      
 416 
     | 
    
         
            +
              else {
         
     | 
| 
       382 
417 
     | 
    
         
             
                size_t *shape      = ALLOC_N(size_t, s->dim);
         
     | 
| 
       383 
418 
     | 
    
         
             
                for (size_t i = 0; i < s->dim; ++i) {
         
     | 
| 
       384 
419 
     | 
    
         
             
                  shape[i]  = slice->lengths[i];
         
     | 
| 
       385 
420 
     | 
    
         
             
                }
         
     | 
| 
       386 
421 
     | 
    
         | 
| 
       387 
     | 
    
         
            -
                ns = nm_dense_storage_create(s->dtype, shape, s->dim, NULL, 0);
         
     | 
| 
      
 422 
     | 
    
         
            +
                DENSE_STORAGE* ns = nm_dense_storage_create(s->dtype, shape, s->dim, NULL, 0);
         
     | 
| 
       388 
423 
     | 
    
         | 
| 
       389 
424 
     | 
    
         
             
                slice_copy(ns,
         
     | 
| 
       390 
425 
     | 
    
         
             
                    reinterpret_cast<const DENSE_STORAGE*>(s->src),
         
     | 
| 
         @@ -392,6 +427,7 @@ void* nm_dense_storage_get(STORAGE* storage, SLICE* slice) { 
     | 
|
| 
       392 
427 
     | 
    
         
             
                    0,
         
     | 
| 
       393 
428 
     | 
    
         
             
                    nm_dense_storage_pos(s, slice->coords),
         
     | 
| 
       394 
429 
     | 
    
         
             
                    0);
         
     | 
| 
      
 430 
     | 
    
         
            +
             
     | 
| 
       395 
431 
     | 
    
         
             
                return ns;
         
     | 
| 
       396 
432 
     | 
    
         
             
              }
         
     | 
| 
       397 
433 
     | 
    
         
             
            }
         
     | 
| 
         @@ -552,24 +588,6 @@ static size_t* stride(size_t* shape, size_t dim) { 
     | 
|
| 
       552 
588 
     | 
    
         
             
              return stride;
         
     | 
| 
       553 
589 
     | 
    
         
             
            }
         
     | 
| 
       554 
590 
     | 
    
         | 
| 
       555 
     | 
    
         
            -
            /*
         
     | 
| 
       556 
     | 
    
         
            -
             * Recursive slicing for N-dimensional matrix.
         
     | 
| 
       557 
     | 
    
         
            -
             */
         
     | 
| 
       558 
     | 
    
         
            -
            static void slice_copy(DENSE_STORAGE *dest, const DENSE_STORAGE *src, size_t* lengths, size_t pdest, size_t psrc, size_t n) {
         
     | 
| 
       559 
     | 
    
         
            -
              if (src->dim - n > 1) {
         
     | 
| 
       560 
     | 
    
         
            -
                for (size_t i = 0; i < lengths[n]; ++i) {
         
     | 
| 
       561 
     | 
    
         
            -
                  slice_copy(dest, src, lengths,
         
     | 
| 
       562 
     | 
    
         
            -
                                                pdest + dest->stride[n]*i,
         
     | 
| 
       563 
     | 
    
         
            -
                                                psrc + src->stride[n]*i,
         
     | 
| 
       564 
     | 
    
         
            -
                                                n + 1);
         
     | 
| 
       565 
     | 
    
         
            -
                }
         
     | 
| 
       566 
     | 
    
         
            -
              } else {
         
     | 
| 
       567 
     | 
    
         
            -
                memcpy((char*)dest->elements + pdest*DTYPE_SIZES[dest->dtype],
         
     | 
| 
       568 
     | 
    
         
            -
                    (char*)src->elements + psrc*DTYPE_SIZES[src->dtype],
         
     | 
| 
       569 
     | 
    
         
            -
                    dest->shape[n]*DTYPE_SIZES[dest->dtype]);
         
     | 
| 
       570 
     | 
    
         
            -
              }
         
     | 
| 
       571 
     | 
    
         
            -
             
     | 
| 
       572 
     | 
    
         
            -
            }
         
     | 
| 
       573 
591 
     | 
    
         | 
| 
       574 
592 
     | 
    
         
             
            /////////////////////////
         
     | 
| 
       575 
593 
     | 
    
         
             
            // Copying and Casting //
         
     | 
| 
         @@ -694,22 +712,20 @@ DENSE_STORAGE* cast_copy(const DENSE_STORAGE* rhs, dtype_t new_dtype) { 
     | 
|
| 
       694 
712 
     | 
    
         | 
| 
       695 
713 
     | 
    
         
             
              DENSE_STORAGE* lhs			= nm_dense_storage_create(new_dtype, shape, rhs->dim, NULL, 0);
         
     | 
| 
       696 
714 
     | 
    
         | 
| 
       697 
     | 
    
         
            -
              RDType*	rhs_els         = reinterpret_cast<RDType*>(rhs->elements);
         
     | 
| 
       698 
     | 
    
         
            -
              LDType* lhs_els	        = reinterpret_cast<LDType*>(lhs->elements);
         
     | 
| 
       699 
     | 
    
         
            -
             
     | 
| 
       700 
715 
     | 
    
         
             
            	// Ensure that allocation worked before copying.
         
     | 
| 
       701 
716 
     | 
    
         
             
              if (lhs && count) {
         
     | 
| 
       702 
717 
     | 
    
         
             
                if (rhs->src != rhs) { // Make a copy of a ref to a matrix.
         
     | 
| 
      
 718 
     | 
    
         
            +
                  size_t* offset      = ALLOCA_N(size_t, rhs->dim);
         
     | 
| 
      
 719 
     | 
    
         
            +
                  memset(offset, 0, sizeof(size_t) * rhs->dim);
         
     | 
| 
       703 
720 
     | 
    
         | 
| 
       704 
     | 
    
         
            -
                   
     | 
| 
       705 
     | 
    
         
            -
             
     | 
| 
       706 
     | 
    
         
            -
             
     | 
| 
       707 
     | 
    
         
            -
                  while (count-- > 0)   {
         
     | 
| 
       708 
     | 
    
         
            -
                    lhs_els[count] = tmp_els[count];
         
     | 
| 
       709 
     | 
    
         
            -
                  }
         
     | 
| 
       710 
     | 
    
         
            -
                  nm_dense_storage_delete(tmp);
         
     | 
| 
      
 721 
     | 
    
         
            +
                  slice_copy(lhs, reinterpret_cast<const DENSE_STORAGE*>(rhs->src),
         
     | 
| 
      
 722 
     | 
    
         
            +
                             rhs->shape, 0,
         
     | 
| 
      
 723 
     | 
    
         
            +
                             nm_dense_storage_pos(rhs, offset), 0);
         
     | 
| 
       711 
724 
     | 
    
         | 
| 
       712 
725 
     | 
    
         
             
                } else {              // Make a regular copy.
         
     | 
| 
      
 726 
     | 
    
         
            +
                  RDType*	rhs_els         = reinterpret_cast<RDType*>(rhs->elements);
         
     | 
| 
      
 727 
     | 
    
         
            +
                  LDType* lhs_els	        = reinterpret_cast<LDType*>(lhs->elements);
         
     | 
| 
      
 728 
     | 
    
         
            +
             
     | 
| 
       713 
729 
     | 
    
         
             
                	while (count-- > 0)     		lhs_els[count] = rhs_els[count];
         
     | 
| 
       714 
730 
     | 
    
         
             
                }
         
     | 
| 
       715 
731 
     | 
    
         
             
              }
         
     | 
| 
         @@ -33,6 +33,7 @@ 
     | 
|
| 
       33 
33 
     | 
    
         
             
            #include <ruby.h>
         
     | 
| 
       34 
34 
     | 
    
         
             
            #include <algorithm> // std::min
         
     | 
| 
       35 
35 
     | 
    
         
             
            #include <iostream>
         
     | 
| 
      
 36 
     | 
    
         
            +
            #include <vector>
         
     | 
| 
       36 
37 
     | 
    
         | 
| 
       37 
38 
     | 
    
         
             
            /*
         
     | 
| 
       38 
39 
     | 
    
         
             
             * Project Includes
         
     | 
| 
         @@ -45,7 +46,7 @@ 
     | 
|
| 
       45 
46 
     | 
    
         
             
            #include "common.h"
         
     | 
| 
       46 
47 
     | 
    
         
             
            #include "list.h"
         
     | 
| 
       47 
48 
     | 
    
         | 
| 
       48 
     | 
    
         
            -
            #include " 
     | 
| 
      
 49 
     | 
    
         
            +
            #include "math/math.h"
         
     | 
| 
       49 
50 
     | 
    
         
             
            #include "util/sl_list.h"
         
     | 
| 
       50 
51 
     | 
    
         | 
| 
       51 
52 
     | 
    
         
             
            /*
         
     | 
| 
         @@ -83,7 +84,7 @@ public: 
     | 
|
| 
       83 
84 
     | 
    
         | 
| 
       84 
85 
     | 
    
         
             
              size_t dim() const { return ref->dim; }
         
     | 
| 
       85 
86 
     | 
    
         | 
| 
       86 
     | 
    
         
            -
              size_t  
     | 
| 
      
 87 
     | 
    
         
            +
              size_t ref_shape(size_t rec) const {
         
     | 
| 
       87 
88 
     | 
    
         
             
                return shape_[ref->dim - rec - 1];
         
     | 
| 
       88 
89 
     | 
    
         
             
              }
         
     | 
| 
       89 
90 
     | 
    
         | 
| 
         @@ -143,7 +144,7 @@ static void map_empty_stored_r(RecurseData& result, RecurseData& s, LIST* x, con 
     | 
|
| 
       143 
144 
     | 
    
         | 
| 
       144 
145 
     | 
    
         
             
              // For reference matrices, make sure we start in the correct place.
         
     | 
| 
       145 
146 
     | 
    
         
             
              size_t offset   = result.offset(rec);
         
     | 
| 
       146 
     | 
    
         
            -
              size_t x_shape  = result. 
     | 
| 
      
 147 
     | 
    
         
            +
              size_t x_shape  = result.ref_shape(rec);
         
     | 
| 
       147 
148 
     | 
    
         | 
| 
       148 
149 
     | 
    
         
             
              while (curr && curr->key < offset) {  curr = curr->next;  }
         
     | 
| 
       149 
150 
     | 
    
         
             
              if (curr && curr->key - offset >= x_shape) curr = NULL;
         
     | 
| 
         @@ -188,8 +189,8 @@ static void map_merged_stored_r(RecurseData& result, RecurseData& left, RecurseD 
     | 
|
| 
       188 
189 
     | 
    
         
             
              while (lcurr && lcurr->key < left.offset(rec))  {  lcurr = lcurr->next;  }
         
     | 
| 
       189 
190 
     | 
    
         
             
              while (rcurr && rcurr->key < right.offset(rec)) {  rcurr = rcurr->next;  }
         
     | 
| 
       190 
191 
     | 
    
         | 
| 
       191 
     | 
    
         
            -
              if (rcurr && rcurr->key - right.offset(rec) >= result. 
     | 
| 
       192 
     | 
    
         
            -
              if (lcurr && lcurr->key - left.offset(rec) >= result. 
     | 
| 
      
 192 
     | 
    
         
            +
              if (rcurr && rcurr->key - right.offset(rec) >= result.ref_shape(rec)) rcurr = NULL;
         
     | 
| 
      
 193 
     | 
    
         
            +
              if (lcurr && lcurr->key - left.offset(rec) >= result.ref_shape(rec))  lcurr = NULL;
         
     | 
| 
       193 
194 
     | 
    
         | 
| 
       194 
195 
     | 
    
         
             
              if (rec) {
         
     | 
| 
       195 
196 
     | 
    
         
             
                while (lcurr || rcurr) {
         
     | 
| 
         @@ -214,8 +215,8 @@ static void map_merged_stored_r(RecurseData& result, RecurseData& left, RecurseD 
     | 
|
| 
       214 
215 
     | 
    
         
             
                  if (!val->first) nm::list::del(val, 0); // empty list -- don't insert
         
     | 
| 
       215 
216 
     | 
    
         
             
                  else xcurr = nm::list::insert_helper(x, xcurr, key, val);
         
     | 
| 
       216 
217 
     | 
    
         | 
| 
       217 
     | 
    
         
            -
                  if (rcurr && rcurr->key - right.offset(rec) >= result. 
     | 
| 
       218 
     | 
    
         
            -
                  if (lcurr && lcurr->key - left.offset(rec) >= result. 
     | 
| 
      
 218 
     | 
    
         
            +
                  if (rcurr && rcurr->key - right.offset(rec) >= result.ref_shape(rec)) rcurr = NULL;
         
     | 
| 
      
 219 
     | 
    
         
            +
                  if (lcurr && lcurr->key - left.offset(rec) >= result.ref_shape(rec)) lcurr = NULL;
         
     | 
| 
       219 
220 
     | 
    
         
             
                }
         
     | 
| 
       220 
221 
     | 
    
         
             
              } else {
         
     | 
| 
       221 
222 
     | 
    
         
             
                while (lcurr || rcurr) {
         
     | 
| 
         @@ -239,8 +240,8 @@ static void map_merged_stored_r(RecurseData& result, RecurseData& left, RecurseD 
     | 
|
| 
       239 
240 
     | 
    
         
             
                  if (rb_funcall(val, rb_intern("!="), 1, result.init_obj()) == Qtrue)
         
     | 
| 
       240 
241 
     | 
    
         
             
                    xcurr = nm::list::insert_helper(x, xcurr, key, val);
         
     | 
| 
       241 
242 
     | 
    
         | 
| 
       242 
     | 
    
         
            -
                  if (rcurr && rcurr->key - right.offset(rec) >= result. 
     | 
| 
       243 
     | 
    
         
            -
                  if (lcurr && lcurr->key - left.offset(rec) >= result. 
     | 
| 
      
 243 
     | 
    
         
            +
                  if (rcurr && rcurr->key - right.offset(rec) >= result.ref_shape(rec)) rcurr = NULL;
         
     | 
| 
      
 244 
     | 
    
         
            +
                  if (lcurr && lcurr->key - left.offset(rec) >= result.ref_shape(rec)) lcurr = NULL;
         
     | 
| 
       244 
245 
     | 
    
         
             
                }
         
     | 
| 
       245 
246 
     | 
    
         
             
              }
         
     | 
| 
       246 
247 
     | 
    
         
             
            }
         
     | 
| 
         @@ -293,10 +294,10 @@ void nm_list_storage_delete(STORAGE* s) { 
     | 
|
| 
       293 
294 
     | 
    
         
             
                if (storage->count-- == 1) {
         
     | 
| 
       294 
295 
     | 
    
         
             
                  list::del( storage->rows, storage->dim - 1 );
         
     | 
| 
       295 
296 
     | 
    
         | 
| 
       296 
     | 
    
         
            -
                   
     | 
| 
       297 
     | 
    
         
            -
                   
     | 
| 
       298 
     | 
    
         
            -
                   
     | 
| 
       299 
     | 
    
         
            -
                   
     | 
| 
      
 297 
     | 
    
         
            +
                  xfree(storage->shape);
         
     | 
| 
      
 298 
     | 
    
         
            +
                  xfree(storage->offset);
         
     | 
| 
      
 299 
     | 
    
         
            +
                  xfree(storage->default_val);
         
     | 
| 
      
 300 
     | 
    
         
            +
                  xfree(s);
         
     | 
| 
       300 
301 
     | 
    
         
             
                }
         
     | 
| 
       301 
302 
     | 
    
         
             
              }
         
     | 
| 
       302 
303 
     | 
    
         
             
            }
         
     | 
| 
         @@ -309,9 +310,9 @@ void nm_list_storage_delete_ref(STORAGE* s) { 
     | 
|
| 
       309 
310 
     | 
    
         
             
                LIST_STORAGE* storage = (LIST_STORAGE*)s;
         
     | 
| 
       310 
311 
     | 
    
         | 
| 
       311 
312 
     | 
    
         
             
                nm_list_storage_delete( reinterpret_cast<STORAGE*>(storage->src ) );
         
     | 
| 
       312 
     | 
    
         
            -
                 
     | 
| 
       313 
     | 
    
         
            -
                 
     | 
| 
       314 
     | 
    
         
            -
                 
     | 
| 
      
 313 
     | 
    
         
            +
                xfree(storage->shape);
         
     | 
| 
      
 314 
     | 
    
         
            +
                xfree(storage->offset);
         
     | 
| 
      
 315 
     | 
    
         
            +
                xfree(s);
         
     | 
| 
       315 
316 
     | 
    
         
             
              }
         
     | 
| 
       316 
317 
     | 
    
         
             
            }
         
     | 
| 
       317 
318 
     | 
    
         | 
| 
         @@ -334,7 +335,7 @@ void nm_list_storage_mark(void* storage_base) { 
     | 
|
| 
       334 
335 
     | 
    
         
             
            /*
         
     | 
| 
       335 
336 
     | 
    
         
             
             * Documentation goes here.
         
     | 
| 
       336 
337 
     | 
    
         
             
             */
         
     | 
| 
       337 
     | 
    
         
            -
            NODE* list_storage_get_single_node(LIST_STORAGE* s, SLICE* slice)
         
     | 
| 
      
 338 
     | 
    
         
            +
            static NODE* list_storage_get_single_node(LIST_STORAGE* s, SLICE* slice)
         
     | 
| 
       338 
339 
     | 
    
         
             
            {
         
     | 
| 
       339 
340 
     | 
    
         
             
              size_t r;
         
     | 
| 
       340 
341 
     | 
    
         
             
              LIST*  l = s->rows;
         
     | 
| 
         @@ -358,7 +359,7 @@ static void each_empty_with_indices_r(nm::list_storage::RecurseData& s, size_t r 
     | 
|
| 
       358 
359 
     | 
    
         
             
              VALUE empty  = s.dtype() == nm::RUBYOBJ ? *reinterpret_cast<VALUE*>(s.init()) : s.init_obj();
         
     | 
| 
       359 
360 
     | 
    
         | 
| 
       360 
361 
     | 
    
         
             
              if (rec) {
         
     | 
| 
       361 
     | 
    
         
            -
                for (long index = 0; index < s. 
     | 
| 
      
 362 
     | 
    
         
            +
                for (long index = 0; index < s.ref_shape(rec); ++index) {
         
     | 
| 
       362 
363 
     | 
    
         
             
                  // Don't do an unshift/shift here -- we'll let that be handled in the lowest-level iteration (recursions == 0)
         
     | 
| 
       363 
364 
     | 
    
         
             
                  rb_ary_push(stack, LONG2NUM(index));
         
     | 
| 
       364 
365 
     | 
    
         
             
                  each_empty_with_indices_r(s, rec-1, stack);
         
     | 
| 
         @@ -366,7 +367,7 @@ static void each_empty_with_indices_r(nm::list_storage::RecurseData& s, size_t r 
     | 
|
| 
       366 
367 
     | 
    
         
             
                }
         
     | 
| 
       367 
368 
     | 
    
         
             
              } else {
         
     | 
| 
       368 
369 
     | 
    
         
             
                rb_ary_unshift(stack, empty);
         
     | 
| 
       369 
     | 
    
         
            -
                for (long index = 0; index < s. 
     | 
| 
      
 370 
     | 
    
         
            +
                for (long index = 0; index < s.ref_shape(rec); ++index) {
         
     | 
| 
       370 
371 
     | 
    
         
             
                  rb_ary_push(stack, LONG2NUM(index));
         
     | 
| 
       371 
372 
     | 
    
         
             
                  rb_yield_splat(stack);
         
     | 
| 
       372 
373 
     | 
    
         
             
                  rb_ary_pop(stack);
         
     | 
| 
         @@ -382,18 +383,18 @@ static void each_with_indices_r(nm::list_storage::RecurseData& s, const LIST* l, 
     | 
|
| 
       382 
383 
     | 
    
         
             
              NODE*  curr  = l->first;
         
     | 
| 
       383 
384 
     | 
    
         | 
| 
       384 
385 
     | 
    
         
             
              size_t offset = s.offset(rec);
         
     | 
| 
       385 
     | 
    
         
            -
              size_t shape  = s. 
     | 
| 
      
 386 
     | 
    
         
            +
              size_t shape  = s.ref_shape(rec);
         
     | 
| 
       386 
387 
     | 
    
         | 
| 
       387 
388 
     | 
    
         
             
              while (curr && curr->key < offset) curr = curr->next;
         
     | 
| 
       388 
     | 
    
         
            -
              if (curr && curr->key >= shape) curr = NULL;
         
     | 
| 
      
 389 
     | 
    
         
            +
              if (curr && curr->key - offset >= shape) curr = NULL;
         
     | 
| 
       389 
390 
     | 
    
         | 
| 
       390 
391 
     | 
    
         | 
| 
       391 
392 
     | 
    
         
             
              if (rec) {
         
     | 
| 
       392 
     | 
    
         
            -
                for (long index = 0; index < shape; ++index) {
         
     | 
| 
      
 393 
     | 
    
         
            +
                for (long index = 0; index < shape; ++index) { // index in reference
         
     | 
| 
       393 
394 
     | 
    
         
             
                  rb_ary_push(stack, LONG2NUM(index));
         
     | 
| 
       394 
395 
     | 
    
         
             
                  if (!curr || index < curr->key - offset) {
         
     | 
| 
       395 
396 
     | 
    
         
             
                    each_empty_with_indices_r(s, rec-1, stack);
         
     | 
| 
       396 
     | 
    
         
            -
                  } else {
         
     | 
| 
      
 397 
     | 
    
         
            +
                  } else { // index == curr->key - offset
         
     | 
| 
       397 
398 
     | 
    
         
             
                    each_with_indices_r(s, reinterpret_cast<const LIST*>(curr->val), rec-1, stack);
         
     | 
| 
       398 
399 
     | 
    
         
             
                    curr = curr->next;
         
     | 
| 
       399 
400 
     | 
    
         
             
                  }
         
     | 
| 
         @@ -407,7 +408,7 @@ static void each_with_indices_r(nm::list_storage::RecurseData& s, const LIST* l, 
     | 
|
| 
       407 
408 
     | 
    
         
             
                  if (!curr || index < curr->key - offset) {
         
     | 
| 
       408 
409 
     | 
    
         
             
                    rb_ary_unshift(stack, s.dtype() == nm::RUBYOBJ ? *reinterpret_cast<VALUE*>(s.init()) : s.init_obj());
         
     | 
| 
       409 
410 
     | 
    
         | 
| 
       410 
     | 
    
         
            -
                  } else { // index == curr->key
         
     | 
| 
      
 411 
     | 
    
         
            +
                  } else { // index == curr->key - offset
         
     | 
| 
       411 
412 
     | 
    
         
             
                    rb_ary_unshift(stack, s.dtype() == nm::RUBYOBJ ? *reinterpret_cast<VALUE*>(curr->val) : rubyobj_from_cval(curr->val, s.dtype()).rval);
         
     | 
| 
       412 
413 
     | 
    
         | 
| 
       413 
414 
     | 
    
         
             
                    curr = curr->next;
         
     | 
| 
         @@ -429,7 +430,7 @@ static void each_stored_with_indices_r(nm::list_storage::RecurseData& s, const L 
     | 
|
| 
       429 
430 
     | 
    
         
             
              NODE* curr = l->first;
         
     | 
| 
       430 
431 
     | 
    
         | 
| 
       431 
432 
     | 
    
         
             
              size_t offset = s.offset(rec);
         
     | 
| 
       432 
     | 
    
         
            -
              size_t shape  = s. 
     | 
| 
      
 433 
     | 
    
         
            +
              size_t shape  = s.ref_shape(rec);
         
     | 
| 
       433 
434 
     | 
    
         | 
| 
       434 
435 
     | 
    
         
             
              while (curr && curr->key < offset) { curr = curr->next; }
         
     | 
| 
       435 
436 
     | 
    
         
             
              if (curr && curr->key - offset >= shape) curr = NULL;
         
     | 
| 
         @@ -460,7 +461,7 @@ static void each_stored_with_indices_r(nm::list_storage::RecurseData& s, const L 
     | 
|
| 
       460 
461 
     | 
    
         
             
                  rb_ary_pop(stack);
         
     | 
| 
       461 
462 
     | 
    
         | 
| 
       462 
463 
     | 
    
         
             
                  curr = curr->next;
         
     | 
| 
       463 
     | 
    
         
            -
                  if (curr && curr->key >= shape) curr = NULL;
         
     | 
| 
      
 464 
     | 
    
         
            +
                  if (curr && curr->key - offset >= shape) curr = NULL;
         
     | 
| 
       464 
465 
     | 
    
         
             
                }
         
     | 
| 
       465 
466 
     | 
    
         
             
              }
         
     | 
| 
       466 
467 
     | 
    
         
             
            }
         
     | 
| 
         @@ -500,7 +501,6 @@ VALUE nm_list_map_merged_stored(VALUE left, VALUE right, VALUE init) { 
     | 
|
| 
       500 
501 
     | 
    
         
             
              nm::list_storage::RecurseData sdata(s);
         
     | 
| 
       501 
502 
     | 
    
         | 
| 
       502 
503 
     | 
    
         
             
              void* scalar_init = NULL;
         
     | 
| 
       503 
     | 
    
         
            -
              size_t* shape;
         
     | 
| 
       504 
504 
     | 
    
         | 
| 
       505 
505 
     | 
    
         
             
              // right might be a scalar, in which case this is a scalar operation.
         
     | 
| 
       506 
506 
     | 
    
         
             
              if (TYPE(right) != T_DATA || (RDATA(right)->dfree != (RUBY_DATA_FUNC)nm_delete && RDATA(right)->dfree != (RUBY_DATA_FUNC)nm_delete_ref)) {
         
     | 
| 
         @@ -541,8 +541,11 @@ VALUE nm_list_map_merged_stored(VALUE left, VALUE right, VALUE init) { 
     | 
|
| 
       541 
541 
     | 
    
         
             
            }
         
     | 
| 
       542 
542 
     | 
    
         | 
| 
       543 
543 
     | 
    
         | 
| 
       544 
     | 
    
         
            -
             
     | 
| 
      
 544 
     | 
    
         
            +
            /*
         
     | 
| 
      
 545 
     | 
    
         
            +
             * Copy a slice of a list matrix into a regular list matrix.
         
     | 
| 
      
 546 
     | 
    
         
            +
             */
         
     | 
| 
       545 
547 
     | 
    
         
             
            static LIST* slice_copy(const LIST_STORAGE *src, LIST *src_rows, size_t *coords, size_t *lengths, size_t n) {
         
     | 
| 
      
 548 
     | 
    
         
            +
             
     | 
| 
       546 
549 
     | 
    
         
             
              NODE *src_node;
         
     | 
| 
       547 
550 
     | 
    
         
             
              LIST *dst_rows = NULL;
         
     | 
| 
       548 
551 
     | 
    
         
             
              void *val = NULL;
         
     | 
| 
         @@ -586,10 +589,9 @@ void* nm_list_storage_get(STORAGE* storage, SLICE* slice) { 
     | 
|
| 
       586 
589 
     | 
    
         
             
              NODE* n;
         
     | 
| 
       587 
590 
     | 
    
         | 
| 
       588 
591 
     | 
    
         
             
              if (slice->single) {
         
     | 
| 
       589 
     | 
    
         
            -
                n = list_storage_get_single_node(s, slice); 
     | 
| 
      
 592 
     | 
    
         
            +
                n = list_storage_get_single_node(s, slice);
         
     | 
| 
       590 
593 
     | 
    
         
             
                return (n ? n->val : s->default_val);
         
     | 
| 
       591 
     | 
    
         
            -
              } 
         
     | 
| 
       592 
     | 
    
         
            -
              else {
         
     | 
| 
      
 594 
     | 
    
         
            +
              } else {
         
     | 
| 
       593 
595 
     | 
    
         
             
                void *init_val = ALLOC_N(char, DTYPE_SIZES[s->dtype]);
         
     | 
| 
       594 
596 
     | 
    
         
             
                memcpy(init_val, s->default_val, DTYPE_SIZES[s->dtype]);
         
     | 
| 
       595 
597 
     | 
    
         | 
| 
         @@ -597,7 +599,7 @@ void* nm_list_storage_get(STORAGE* storage, SLICE* slice) { 
     | 
|
| 
       597 
599 
     | 
    
         
             
                memcpy(shape, slice->lengths, sizeof(size_t) * s->dim);
         
     | 
| 
       598 
600 
     | 
    
         | 
| 
       599 
601 
     | 
    
         
             
                ns = nm_list_storage_create(s->dtype, shape, s->dim, init_val);
         
     | 
| 
       600 
     | 
    
         
            -
             
     | 
| 
      
 602 
     | 
    
         
            +
             
     | 
| 
       601 
603 
     | 
    
         
             
                ns->rows = slice_copy(s, s->rows, slice->coords, slice->lengths, 0);
         
     | 
| 
       602 
604 
     | 
    
         
             
                return ns;
         
     | 
| 
       603 
605 
     | 
    
         
             
              }
         
     | 
| 
         @@ -618,23 +620,23 @@ void* nm_list_storage_ref(STORAGE* storage, SLICE* slice) { 
     | 
|
| 
       618 
620 
     | 
    
         
             
                return (n ? n->val : s->default_val);
         
     | 
| 
       619 
621 
     | 
    
         
             
              } 
         
     | 
| 
       620 
622 
     | 
    
         
             
              else {
         
     | 
| 
       621 
     | 
    
         
            -
                ns 
     | 
| 
      
 623 
     | 
    
         
            +
                ns              = ALLOC( LIST_STORAGE );
         
     | 
| 
       622 
624 
     | 
    
         | 
| 
       623 
     | 
    
         
            -
                ns->dim 
     | 
| 
       624 
     | 
    
         
            -
                ns->dtype 
     | 
| 
       625 
     | 
    
         
            -
                ns->offset 
     | 
| 
       626 
     | 
    
         
            -
                ns->shape 
     | 
| 
      
 625 
     | 
    
         
            +
                ns->dim         = s->dim;
         
     | 
| 
      
 626 
     | 
    
         
            +
                ns->dtype       = s->dtype;
         
     | 
| 
      
 627 
     | 
    
         
            +
                ns->offset      = ALLOC_N(size_t, ns->dim);
         
     | 
| 
      
 628 
     | 
    
         
            +
                ns->shape       = ALLOC_N(size_t, ns->dim);
         
     | 
| 
       627 
629 
     | 
    
         | 
| 
       628 
630 
     | 
    
         
             
                for (size_t i = 0; i < ns->dim; ++i) {
         
     | 
| 
       629 
631 
     | 
    
         
             
                  ns->offset[i] = slice->coords[i] + s->offset[i];
         
     | 
| 
       630 
632 
     | 
    
         
             
                  ns->shape[i]  = slice->lengths[i];
         
     | 
| 
       631 
633 
     | 
    
         
             
                }
         
     | 
| 
       632 
634 
     | 
    
         | 
| 
       633 
     | 
    
         
            -
                ns->rows 
     | 
| 
      
 635 
     | 
    
         
            +
                ns->rows        = s->rows;
         
     | 
| 
       634 
636 
     | 
    
         
             
                ns->default_val = s->default_val;
         
     | 
| 
       635 
637 
     | 
    
         | 
| 
       636 
638 
     | 
    
         
             
                s->src->count++;
         
     | 
| 
       637 
     | 
    
         
            -
                ns->src 
     | 
| 
      
 639 
     | 
    
         
            +
                ns->src         = s->src;
         
     | 
| 
       638 
640 
     | 
    
         | 
| 
       639 
641 
     | 
    
         
             
                return ns;
         
     | 
| 
       640 
642 
     | 
    
         
             
              }
         
     | 
| 
         @@ -874,21 +876,21 @@ static bool eqeq_empty_r(RecurseData& s, const LIST* l, size_t rec, const TDType 
     | 
|
| 
       874 
876 
     | 
    
         | 
| 
       875 
877 
     | 
    
         
             
              // For reference matrices, make sure we start in the correct place.
         
     | 
| 
       876 
878 
     | 
    
         
             
              while (curr && curr->key < s.offset(rec)) {  curr = curr->next;  }
         
     | 
| 
       877 
     | 
    
         
            -
              if (curr && curr->key - s.offset(rec) >= s. 
     | 
| 
      
 879 
     | 
    
         
            +
              if (curr && curr->key - s.offset(rec) >= s.ref_shape(rec)) curr = NULL;
         
     | 
| 
       878 
880 
     | 
    
         | 
| 
       879 
881 
     | 
    
         
             
              if (rec) {
         
     | 
| 
       880 
882 
     | 
    
         
             
                while (curr) {
         
     | 
| 
       881 
883 
     | 
    
         
             
                  if (!eqeq_empty_r<SDType,TDType>(s, reinterpret_cast<const LIST*>(curr->val), rec-1, t_init)) return false;
         
     | 
| 
       882 
884 
     | 
    
         
             
                  curr = curr->next;
         
     | 
| 
       883 
885 
     | 
    
         | 
| 
       884 
     | 
    
         
            -
                  if (curr && curr->key - s.offset(rec) >= s. 
     | 
| 
      
 886 
     | 
    
         
            +
                  if (curr && curr->key - s.offset(rec) >= s.ref_shape(rec)) curr = NULL;
         
     | 
| 
       885 
887 
     | 
    
         
             
                }
         
     | 
| 
       886 
888 
     | 
    
         
             
              } else {
         
     | 
| 
       887 
889 
     | 
    
         
             
                while (curr) {
         
     | 
| 
       888 
890 
     | 
    
         
             
                  if (*reinterpret_cast<SDType*>(curr->val) != *t_init) return false;
         
     | 
| 
       889 
891 
     | 
    
         
             
                  curr = curr->next;
         
     | 
| 
       890 
892 
     | 
    
         | 
| 
       891 
     | 
    
         
            -
                  if (curr && curr->key - s.offset(rec) >= s. 
     | 
| 
      
 893 
     | 
    
         
            +
                  if (curr && curr->key - s.offset(rec) >= s.ref_shape(rec)) curr = NULL;
         
     | 
| 
       892 
894 
     | 
    
         
             
                }
         
     | 
| 
       893 
895 
     | 
    
         
             
              }
         
     | 
| 
       894 
896 
     | 
    
         
             
              return true;
         
     | 
| 
         @@ -909,8 +911,8 @@ static bool eqeq_r(RecurseData& left, RecurseData& right, const LIST* l, const L 
     | 
|
| 
       909 
911 
     | 
    
         
             
              // For reference matrices, make sure we start in the correct place.
         
     | 
| 
       910 
912 
     | 
    
         
             
              while (lcurr && lcurr->key < left.offset(rec)) {  lcurr = lcurr->next;  }
         
     | 
| 
       911 
913 
     | 
    
         
             
              while (rcurr && rcurr->key < right.offset(rec)) {  rcurr = rcurr->next;  }
         
     | 
| 
       912 
     | 
    
         
            -
              if (rcurr && rcurr->key - right.offset(rec) >= left. 
     | 
| 
       913 
     | 
    
         
            -
              if (lcurr && lcurr->key - left.offset(rec) >= left. 
     | 
| 
      
 914 
     | 
    
         
            +
              if (rcurr && rcurr->key - right.offset(rec) >= left.ref_shape(rec)) rcurr = NULL;
         
     | 
| 
      
 915 
     | 
    
         
            +
              if (lcurr && lcurr->key - left.offset(rec) >= left.ref_shape(rec)) lcurr = NULL;
         
     | 
| 
       914 
916 
     | 
    
         | 
| 
       915 
917 
     | 
    
         
             
              bool compared = false;
         
     | 
| 
       916 
918 
     | 
    
         | 
| 
         @@ -929,15 +931,15 @@ static bool eqeq_r(RecurseData& left, RecurseData& right, const LIST* l, const L 
     | 
|
| 
       929 
931 
     | 
    
         
             
                    lcurr   = lcurr->next;
         
     | 
| 
       930 
932 
     | 
    
         
             
                    rcurr   = rcurr->next;
         
     | 
| 
       931 
933 
     | 
    
         
             
                  }
         
     | 
| 
       932 
     | 
    
         
            -
                  if (rcurr && rcurr->key - right.offset(rec) >=  
     | 
| 
       933 
     | 
    
         
            -
                  if (lcurr && lcurr->key - left.offset(rec) 
     | 
| 
      
 934 
     | 
    
         
            +
                  if (rcurr && rcurr->key - right.offset(rec) >= right.ref_shape(rec)) rcurr = NULL;
         
     | 
| 
      
 935 
     | 
    
         
            +
                  if (lcurr && lcurr->key - left.offset(rec)  >= left.ref_shape(rec)) lcurr = NULL;
         
     | 
| 
       934 
936 
     | 
    
         
             
                  compared = true;
         
     | 
| 
       935 
937 
     | 
    
         
             
                }
         
     | 
| 
       936 
938 
     | 
    
         
             
              } else {
         
     | 
| 
       937 
939 
     | 
    
         
             
                while (lcurr || rcurr) {
         
     | 
| 
       938 
940 
     | 
    
         | 
| 
       939 
     | 
    
         
            -
                  if (rcurr && rcurr->key - right.offset(rec) >= left. 
     | 
| 
       940 
     | 
    
         
            -
                  if (lcurr && lcurr->key - left.offset(rec) >= left. 
     | 
| 
      
 941 
     | 
    
         
            +
                  if (rcurr && rcurr->key - right.offset(rec) >= left.ref_shape(rec)) rcurr = NULL;
         
     | 
| 
      
 942 
     | 
    
         
            +
                  if (lcurr && lcurr->key - left.offset(rec) >= left.ref_shape(rec)) lcurr = NULL;
         
     | 
| 
       941 
943 
     | 
    
         | 
| 
       942 
944 
     | 
    
         
             
                  if (!rcurr || (lcurr && (lcurr->key - left.offset(rec) < rcurr->key - right.offset(rec)))) {
         
     | 
| 
       943 
945 
     | 
    
         
             
                    if (*reinterpret_cast<LDType*>(lcurr->val) != *reinterpret_cast<const RDType*>(right.init())) return false;
         
     | 
| 
         @@ -950,8 +952,8 @@ static bool eqeq_r(RecurseData& left, RecurseData& right, const LIST* l, const L 
     | 
|
| 
       950 
952 
     | 
    
         
             
                    lcurr         = lcurr->next;
         
     | 
| 
       951 
953 
     | 
    
         
             
                    rcurr         = rcurr->next;
         
     | 
| 
       952 
954 
     | 
    
         
             
                  }
         
     | 
| 
       953 
     | 
    
         
            -
                  if (rcurr && rcurr->key - right.offset(rec) >=  
     | 
| 
       954 
     | 
    
         
            -
                  if (lcurr && lcurr->key - left.offset(rec) 
     | 
| 
      
 955 
     | 
    
         
            +
                  if (rcurr && rcurr->key - right.offset(rec) >= right.ref_shape(rec)) rcurr = NULL;
         
     | 
| 
      
 956 
     | 
    
         
            +
                  if (lcurr && lcurr->key - left.offset(rec)  >= left.ref_shape(rec)) lcurr = NULL;
         
     | 
| 
       955 
957 
     | 
    
         
             
                  compared = true;
         
     | 
| 
       956 
958 
     | 
    
         
             
                }
         
     | 
| 
       957 
959 
     | 
    
         
             
              }
         
     |