diff yetilab/matrix/matrix.yeti @ 259:fae62dca8048

Make concat also return sparse when all its inputs are sparse
author Chris Cannam
date Wed, 22 May 2013 09:22:10 +0100
parents f3b7b5d20f88
children de770971a628
line wrap: on
line diff
--- a/yetilab/matrix/matrix.yeti	Wed May 22 08:56:51 2013 +0100
+++ b/yetilab/matrix/matrix.yeti	Wed May 22 09:22:10 2013 +0100
@@ -9,8 +9,6 @@
 // result regardless of storage order.  (The transpose function just
 // switches the row/column order without moving the elements.)
 
-//!!! check that we are not unnecessarily copying in the transform functions
-
 vec = load yetilab.vector.vector;
 bf = load yetilab.vector.blockfuncs;
 
@@ -536,6 +534,27 @@
                map do i: getter i m done [0..n-1]
                done mm)));
 
+sparseConcat direction first mm =
+   (dimension d f = if direction == d then sum (map f mm) else f first fi;
+    rows = dimension (Vertical ()) height;
+    columns = dimension (Horizontal ()) width;
+    entries ioff joff ui uj mm =
+        case mm of 
+        m::rest:
+           (map do { i, j, v }: { i = i + ioff, j = j + joff, v }
+                done (enumerate m)) ++
+           (entries
+               (ioff + ui * height m)
+               (joff + uj * width m)
+                ui uj rest);
+         _: []
+        esac;
+    makeSparse
+        if isRowMajor? first then (RowMajor ()) else (ColumnMajor ()) fi
+        { rows, columns }
+        if direction == Vertical () then entries 0 0 1 0 mm
+        else entries 0 0 0 1 mm fi);
+
 checkDimensionsFor direction first mm =
    (counter = if direction == Horizontal () then (.rows) else (.columns) fi;
     n = counter (size first);
@@ -545,26 +564,31 @@
 
 concat direction mm = //!!! doc: storage order is taken from first matrix in sequence
     //!!! would this be better as separate concatHorizontal/concatVertical functions?
-    case mm of
-    first::rest: 
+    case length mm of
+    0: zeroSizeMatrix ();
+    1: head mm;
+    _:
+        first = head mm;
         checkDimensionsFor direction first mm;
-        row = isRowMajor? first;
-        // horizontal, row-major: against grain with rows
-        // horizontal, col-major: with grain with cols
-        // vertical, row-major: with grain with rows
-        // vertical, col-major: against grain with cols
-        case direction of
-        Horizontal ():
-            if row then concatAgainstGrain DenseRows getRow (.rows) mm;
-            else concatWithGrain DenseCols getColumn (.columns) mm;
-            fi;
-        Vertical ():
-            if row then concatWithGrain DenseRows getRow (.rows) mm;
-            else concatAgainstGrain DenseCols getColumn (.columns) mm;
-            fi;
-        esac;
-    [single]: single;
-    _: zeroSizeMatrix ();
+        if all isSparse? mm then
+            sparseConcat direction first mm
+        else
+            row = isRowMajor? first;
+            // horizontal, row-major: against grain with rows
+            // horizontal, col-major: with grain with cols
+            // vertical, row-major: with grain with rows
+            // vertical, col-major: against grain with cols
+            case direction of
+            Horizontal ():
+                if row then concatAgainstGrain DenseRows getRow (.rows) mm;
+                else concatWithGrain DenseCols getColumn (.columns) mm;
+                fi;
+            Vertical ():
+                if row then concatWithGrain DenseRows getRow (.rows) mm;
+                else concatAgainstGrain DenseCols getColumn (.columns) mm;
+                fi;
+            esac;
+        fi;
     esac;
 
 //!!! inconsistent with std.slice which has start..end not start+count (see also vec.slice/rangeOf)