changeset 275:2c3faf6a2820

Implementation and (currently) failing tests for duplicate
author Chris Cannam
date Sat, 25 May 2013 18:18:10 +0100
parents df0836b48494
children 39b5f3fed12d
files yetilab/matrix.yeti yetilab/matrix/test/test_matrix.yeti yetilab/stream/filter.yeti yetilab/stream/test/test_filter.yeti
diffstat 4 files changed, 184 insertions(+), 29 deletions(-) [+]
line wrap: on
line diff
--- a/yetilab/matrix.yeti	Thu May 23 21:36:20 2013 +0100
+++ b/yetilab/matrix.yeti	Sat May 25 18:18:10 2013 +0100
@@ -9,6 +9,11 @@
 // result regardless of storage order.  (The transpose function just
 // switches the row/column order without moving the elements.)
 
+// The matrix representation does not take into account different
+// forms of zero-width or zero-height matrix. That is, all matrices of
+// zero width or height are equal to each other and to the zero-size
+// matrix -- they can't be distinguished.
+
 vec = load yetilab.vector;
 bf = load yetilab.vector.blockfuncs;
 
@@ -168,6 +173,8 @@
 
 zeroSizeMatrix () = zeroMatrix { rows = 0, columns = 0 };
 
+isZeroSize? m = (width m == 0 or height m == 0);
+
 generate f { rows, columns } =
     if rows < 1 or columns < 1 then zeroSizeMatrix ()
     else
@@ -333,7 +340,9 @@
     esac);
 
 equal' comparator vecComparator m1 m2 =
-    if size m1 != size m2 then 
+    if isZeroSize? m1 and isZeroSize? m2 then
+        true
+    elif size m1 != size m2 then 
         false
     elif isRowMajor? m1 != isRowMajor? m2 then
         equal' comparator vecComparator (flipped m1) m2;
@@ -437,7 +446,7 @@
         newMatrix (typeOf m) (map bf.abs (asColumns m));
     fi;
 
-filter f m =
+filter' f m =
     if isSparse? m then
         makeSparse (typeOf m) (size m)
            (map do { i, j, v }: { i, j, v = if f v then v else 0 fi } done
@@ -600,7 +609,7 @@
         failWith "Matrix dimensions incompatible for concat (found \(map do m: counter (size m) done mm) not all of which are \(n))";
     fi);
 
-concat direction mm = //!!! doc: storage order is taken from first matrix in sequence
+concat' direction mm = //!!! doc: storage order is taken from first matrix in sequence
     case length mm of
     0: zeroSizeMatrix ();
     1: head mm;
@@ -628,6 +637,10 @@
         fi;
     esac;
 
+//!!! doc this filter -- zero-size elts are ignored
+concat direction mm =
+    concat' direction (filter do mat: not (isZeroSize? mat) done mm);
+
 //!!! doc note: argument order chosen for consistency with std module slice
 rowSlice m start end = //!!! doc: storage order same as input
     if isRowMajor? m then
@@ -694,6 +707,7 @@
     zeroMatrix,
     identityMatrix,
     zeroSizeMatrix,
+    isZeroSize?,
     equal,
     equalUnder,
     transposed,
@@ -709,7 +723,7 @@
     sum = sum',
     difference,
     abs = abs',
-    filter,
+    filter = filter',
     product,
     concat,
     rowSlice,
@@ -740,6 +754,7 @@
     zeroMatrix is { .rows is number, .columns is number } -> matrix, 
     identityMatrix is { .rows is number, .columns is number } -> matrix, 
     zeroSizeMatrix is () -> matrix,
+    isZeroSize? is matrix -> boolean,
     equal is matrix -> matrix -> boolean,
     equalUnder is (number -> number -> boolean) -> matrix -> matrix -> boolean,
     transposed is matrix -> matrix,
--- a/yetilab/matrix/test/test_matrix.yeti	Thu May 23 21:36:20 2013 +0100
+++ b/yetilab/matrix/test/test_matrix.yeti	Sat May 25 18:18:10 2013 +0100
@@ -360,7 +360,19 @@
 "zeroSizeMatrix-\(name)": \(
     compareMatrices
        (mat.zeroSizeMatrix ())
-       (newMatrix (ColumnMajor ()) [])
+       (newMatrix (ColumnMajor ()) []) and
+        compareMatrices
+           (mat.zeroSizeMatrix ())
+           (newMatrix (ColumnMajor ()) [[]]) and
+        compareMatrices
+           (newMatrix (ColumnMajor ()) [[]])
+           (newMatrix (RowMajor ()) [[]]) and
+        compareMatrices
+           (mat.zeroSizeMatrix ())
+           (mat.newSparseMatrix (ColumnMajor ()) { rows = 0, columns = 1 } []) and
+        compareMatrices
+           (mat.zeroSizeMatrix ())
+           (mat.newSparseMatrix (ColumnMajor ()) { rows = 1, columns = 0 } [])
 ),
 
 "asRows-\(name)": \(
--- a/yetilab/stream/filter.yeti	Thu May 23 21:36:20 2013 +0100
+++ b/yetilab/stream/filter.yeti	Sat May 25 18:18:10 2013 +0100
@@ -202,6 +202,64 @@
         }
     fi;
 
+duplicated copies s = 
+//!!! doc fact that original s cannot be used independently of this afterward
+// (so maybe name is misleading?)
+    if copies < 2 then map \s [1..copies];
+    else
+        pos = [:];
+        lowtide () = head (sort (map (at pos) (keys pos)));
+        var hightide = 0;
+        var cache = mat.zeroSizeMatrix ();
+        syncd = synchronized pos;
+        advance i n =
+           (formerLow = lowtide ();
+            pos[i] := pos[i] + n;
+            encroachment = lowtide () - formerLow;
+            if encroachment > 0 then
+                cache := mat.columnSlice cache encroachment
+                   (mat.width cache - encroachment);
+            fi);
+        map do instance:
+            pos[instance] := 0;
+            {
+                get position () = syncd \(pos[instance]),
+                get channels () = syncd \(s.channels),
+                get sampleRate () = syncd \(s.sampleRate),
+                get available () = syncd
+                  \(case s.available of
+                    Known av: Known (av + (hightide - pos[instance]));
+                    other: other;
+                    esac),
+                get finished? () = syncd
+                  \(if not s.finished? then false
+                    else pos[instance] >= hightide
+                    fi),
+                read count = syncd
+                  \(ready = hightide - pos[instance];
+                    if s.finished? and ready <= 0 
+                    then mat.zeroSizeMatrix ()
+                    else
+                        if count > ready then
+                            more = s.read (count - ready);
+                            cache := mat.concat (Horizontal ())
+                               [cache, more];
+                        fi;
+                        chunk = mat.columnSlice cache
+                           (pos[instance] - (lowtide ())) count;
+                        advance instance (mat.width chunk);
+                        chunk;
+                    fi),
+                close () = syncd
+                  \(delete pos instance;
+                    if empty? pos then
+                        s.close ()
+                    fi),
+            }
+            done [1..copies];
+    fi;
+                        
+
 {
     withDuration is number -> stream -> stream,
     delayedBy is number -> stream -> stream,
@@ -209,7 +267,6 @@
     mixed is list<stream> -> stream,
     multiplexed is list<stream> -> stream,
     repeated is stream -> stream,
+    duplicated is number -> stream -> list<stream>,
 }
 
-
-
--- a/yetilab/stream/test/test_filter.yeti	Thu May 23 21:36:20 2013 +0100
+++ b/yetilab/stream/test/test_filter.yeti	Sat May 25 18:18:10 2013 +0100
@@ -9,7 +9,7 @@
 { compare, compareUsing } = load yetilab.test.test;
 
 makeTests name withUnknown =
-   (withDuration n str =
+   (maybeDuration n str =
         // Truncate a stream, but if withUnknown is true, return it
         // with availability Unknown -- so as to test that other
         // filter functions behave correctly even if availability is
@@ -68,7 +68,7 @@
     // we're actually testing filt.withDuration here rather than just
     // generating a stream for use in another test. The inner call
     // does use the wrapper.
-    str = filt.withDuration 5 (withDuration 3 (syn.generated 2 id));
+    str = filt.withDuration 5 (maybeDuration 3 (syn.generated 2 id));
     compare str.position 0 and
         compare str.channels 1 and
         compare str.sampleRate 2 and
@@ -86,7 +86,7 @@
 ),
 
 "delayedBy-0-3-\(name)": \(
-    str = filt.delayedBy 0 (withDuration 3 (syn.generated 2 id));
+    str = filt.delayedBy 0 (maybeDuration 3 (syn.generated 2 id));
     compare str.position 0 and
         compare str.channels 1 and
         compare str.sampleRate 2 and
@@ -114,7 +114,7 @@
 ),
 
 "delayedBy-2-3-\(name)": \(
-    str = filt.delayedBy 2 (withDuration 3 (syn.generated 2 id));
+    str = filt.delayedBy 2 (maybeDuration 3 (syn.generated 2 id));
     compare str.position 0 and
         compare str.channels 1 and
         compare str.sampleRate 2 and
@@ -132,7 +132,7 @@
 ),
 
 "delayedBy-m2-3-\(name)": \(
-    str = filt.delayedBy (-2) (withDuration 3 (syn.generated 2 id));
+    str = filt.delayedBy (-2) (maybeDuration 3 (syn.generated 2 id));
     compare str.position 0 and
         compare str.channels 1 and
         compare str.sampleRate 2 and
@@ -146,7 +146,7 @@
 ),
 
 "delayedBy-m4-3-\(name)": \(
-    str = filt.delayedBy (-4) (withDuration 3 (syn.generated 2 id));
+    str = filt.delayedBy (-4) (maybeDuration 3 (syn.generated 2 id));
     compare str.position 0 and
         compare str.channels 1 and
         compare str.sampleRate 2 and
@@ -157,7 +157,7 @@
 ),
 
 "delayedBy-2-3b-\(name)": \(
-    str = filt.delayedBy 2 (withDuration 3 (syn.generated 2 id));
+    str = filt.delayedBy 2 (maybeDuration 3 (syn.generated 2 id));
     compare str.position 0 and
         compare str.channels 1 and
         compare str.sampleRate 2 and
@@ -175,7 +175,7 @@
 ),
 
 "delayedBy-2-3c-\(name)": \(
-    str = filt.delayedBy 2 (withDuration 3 (syn.generated 2 id));
+    str = filt.delayedBy 2 (maybeDuration 3 (syn.generated 2 id));
     compare str.position 0 and
         compare str.channels 1 and
         compare str.sampleRate 2 and
@@ -221,7 +221,7 @@
 ),
 
 "mixedTo-1-2-\(name)": \(
-    str = filt.mixedTo 2 (withDuration 3 (syn.generated 2 id));
+    str = filt.mixedTo 2 (maybeDuration 3 (syn.generated 2 id));
     compare str.position 0 and
         compare str.channels 2 and
         compare str.sampleRate 2 and
@@ -237,8 +237,8 @@
 "mixedTo-2-1-\(name)": \(
     str = filt.mixedTo 1
        (filt.multiplexed
-          [withDuration 3 (syn.generated 2 id),
-           withDuration 3 (syn.generated 2 id)]);
+          [maybeDuration 3 (syn.generated 2 id),
+           maybeDuration 3 (syn.generated 2 id)]);
     compare str.position 0 and
         compare str.channels 1 and
         compare str.sampleRate 2 and
@@ -254,8 +254,8 @@
 "mixedTo-2-3-\(name)": \(
     str = filt.mixedTo 3
        (filt.multiplexed
-          [withDuration 3 (syn.generated 2 id),
-           withDuration 3 (syn.generated 2 (+1))]);
+          [maybeDuration 3 (syn.generated 2 id),
+           maybeDuration 3 (syn.generated 2 (+1))]);
     compare str.position 0 and
         compare str.channels 3 and
         compare str.sampleRate 2 and
@@ -269,7 +269,7 @@
 ),
 
 "mixedTo-1-3-\(name)": \(
-    str = filt.mixedTo 3 (withDuration 3 (syn.generated 2 id));
+    str = filt.mixedTo 3 (maybeDuration 3 (syn.generated 2 id));
     compare str.position 0 and
         compare str.channels 3 and
         compare str.sampleRate 2 and
@@ -296,7 +296,7 @@
 ),
 
 "mixed-inf-trunc-\(name)": \(
-    str = filt.mixed [syn.generated 2 (2*), withDuration 3 (syn.generated 2 (0-))];
+    str = filt.mixed [syn.generated 2 (2*), maybeDuration 3 (syn.generated 2 (0-))];
     compare str.position 0 and
         compare str.channels 1 and
         compare str.sampleRate 2 and
@@ -312,7 +312,7 @@
 "mixed-precalc-trunc-\(name)": \(
     str = filt.mixed
        [syn.precalculated 2 (vec.fromList [1,2]),
-        withDuration 3 (syn.generated 2 (0-))];
+        maybeDuration 3 (syn.generated 2 (0-))];
     compare str.position 0 and
         compare str.channels 1 and
         compare str.sampleRate 2 and
@@ -329,7 +329,7 @@
     str = filt.mixed
        [syn.precalculated 2 (vec.fromList [1,2]),
         filt.multiplexed [syn.precalculated 2 (vec.fromList [3,4]),
-                          withDuration 3 (syn.generated 2 (0-))]];
+                          maybeDuration 3 (syn.generated 2 (0-))]];
     compare str.position 0 and
         compare str.channels 2 and
         compare str.sampleRate 2 and
@@ -346,7 +346,7 @@
     str = filt.mixed
        [syn.precalculated 2 (vec.fromList [1,2]),
         syn.precalculated 2 (vec.fromList [3,4]),
-        withDuration 3 (syn.generated 2 (0-))];
+        maybeDuration 3 (syn.generated 2 (0-))];
     compare str.position 0 and
         compare str.channels 1 and
         compare str.sampleRate 2 and
@@ -374,7 +374,7 @@
 ),
 
 "multiplexed-inf-trunc-\(name)": \(
-    str = filt.multiplexed [syn.generated 2 id, withDuration 3 (syn.generated 2 (0-))];
+    str = filt.multiplexed [syn.generated 2 id, maybeDuration 3 (syn.generated 2 (0-))];
     compare str.position 0 and
         compare str.channels 2 and
         compare str.sampleRate 2 and
@@ -390,7 +390,7 @@
 "multiplexed-precalc-trunc-\(name)": \(
     str = filt.multiplexed
        [syn.precalculated 2 (vec.fromList [1,2]),
-        withDuration 3 (syn.generated 2 (0-))];
+        maybeDuration 3 (syn.generated 2 (0-))];
     compare str.position 0 and
         compare str.channels 2 and
         compare str.sampleRate 2 and
@@ -407,7 +407,7 @@
     str = filt.multiplexed
        [syn.precalculated 2 (vec.fromList [1,2]),
         filt.multiplexed [syn.precalculated 2 (vec.fromList [3,4]),
-                          withDuration 3 (syn.generated 2 (0-))]];
+                          maybeDuration 3 (syn.generated 2 (0-))]];
     compare str.position 0 and
         compare str.channels 3 and
         compare str.sampleRate 2 and
@@ -424,7 +424,7 @@
     str = filt.multiplexed
        [syn.precalculated 2 (vec.fromList [1,2]),
         syn.precalculated 2 (vec.fromList [3,4]),
-        withDuration 3 (syn.generated 2 (0-))];
+        maybeDuration 3 (syn.generated 2 (0-))];
     compare str.position 0 and
         compare str.channels 3 and
         compare str.sampleRate 2 and
@@ -460,6 +460,77 @@
         ( str.close (); true )
 ),
 
+"duplicated-1-\(name)": \(
+    original = maybeDuration 3 (syn.precalculated 2 (vec.fromList [1,2,3]));
+    sn = filt.duplicated 1 original;
+    str = (head sn);
+    compare (length sn) 1 and
+        compare str.position 0 and
+        compare str.channels 1 and
+        compare str.sampleRate 2 and
+        compare str.available (maybeKnown 3) and
+        compare str.finished? false and
+        compare (map vec.list (mat.asRows (str.read 1))) [[1]] and
+        compare str.position 1 and
+        compare str.available (maybeKnown 2) and
+        compare (map vec.list (mat.asRows (str.read 3))) [[2,3]] and
+        compare str.position 3 and
+        compare str.finished? true and
+        compare str.available (Known 0) and
+        ( str.close (); true )
+),
+
+"duplicated-2-\(name)": \(
+    original = maybeDuration 3 (syn.precalculated 2 (vec.fromList [1,2,3]));
+    sn = filt.duplicated 2 original;
+    s1 = (head sn);
+    s2 = (head (tail sn));
+
+    compare (length sn) 2 and
+
+        compare s1.position 0 and
+        compare s1.channels 1 and
+        compare s1.sampleRate 2 and
+        compare s1.available (maybeKnown 3) and
+        compare s1.finished? false and
+
+        compare s2.position 0 and
+        compare s2.channels 1 and
+        compare s2.sampleRate 2 and
+        compare s2.available (maybeKnown 3) and
+        compare s2.finished? false and
+
+        compare (map vec.list (mat.asRows (s1.read 1))) [[1]] and
+        compare s1.position 1 and
+        compare s1.available (maybeKnown 2) and
+        compare s2.position 0 and
+        compare s2.available (maybeKnown 3) and
+
+        compare (map vec.list (mat.asRows (s2.read 2))) [[1,2]] and
+        compare s1.position 1 and
+        compare s1.available (maybeKnown 2) and
+        compare s2.position 2 and
+        compare s2.available (maybeKnown 1) and
+
+        compare (map vec.list (mat.asRows (s1.read 3))) [[2,3]] and
+        compare s1.position 3 and
+        compare s1.finished? true and
+        compare s1.available (Known 0) and
+        compare s2.position 2 and
+        compare s2.finished? false and
+        compare s2.available (maybeKnown 1) and
+
+        compare (map vec.list (mat.asRows (s1.read 3))) [] and
+
+        compare (map vec.list (mat.asRows (s2.read 1))) [[3]] and
+        compare s1.position 3 and
+        compare s1.finished? true and
+        compare s2.position 3 and
+        compare s2.finished? true and
+
+        ( s1.close (); s2.close() ; true )
+),
+
 //!!! still no tests for filters with multi-channel inputs
 
 ]);