Mercurial > hg > may
changeset 508:3420e5f61a1b sized_matrix
Store size alongside matrix data, so we can now distinguish between different matrix sizes in which one dimension is zero
author | Chris Cannam |
---|---|
date | Wed, 20 Nov 2013 13:57:32 +0000 |
parents | 38e7dce5fa37 |
children | 051c4644d063 |
files | src/may/matrix.yeti src/may/matrix/test/test_matrix.yeti src/may/stream/convolve.yeti src/may/stream/framer.yeti src/may/stream/manipulate.yeti src/may/stream/syntheticstream.yeti src/may/stream/test/test_manipulate.yeti src/may/test/test.yeti |
diffstat | 8 files changed, 242 insertions(+), 205 deletions(-) [+] |
line wrap: on
line diff
--- a/src/may/matrix.yeti Wed Nov 20 12:17:21 2013 +0000 +++ b/src/may/matrix.yeti Wed Nov 20 13:57:32 2013 +0000 @@ -33,10 +33,9 @@ * column-major and row-major storage; and use toSparse and toDense to * convert between sparse and dense storage. * - * Note that the matrix representation does not take into account - * different forms of zero-width or zero-height matrix. All matrices - * of zero width or height are equal to each other, and all are equal - * to the zero-sized matrix. + * Note that the matrix size is preserved even if at least one + * dimension is zero. That is, it is legal to have matrices of size + * 0x0, 0x4, 1x0 etc, and they are distinct from each other. */ module may.matrix; @@ -44,49 +43,28 @@ vec = load may.vector; mm = load may.mathmisc; -typedef opaque matrix_t = - DenseRows array<vec.vector_t> | // array of rows - DenseCols array<vec.vector_t> | // array of columns - SparseCSR { - values is vec.vector_t, - indices is array<number>, // column index of each value - pointers is array<number>, // offset of first value in each row - extent is number // max possible index + 1, i.e. number of columns +typedef opaque matrix_t = { + size is { rows is number, columns is number }, + data is + DenseRows array<vec.vector_t> | // array of rows + DenseCols array<vec.vector_t> | // array of columns + SparseCSR { + values is vec.vector_t, + indices is array<number>, // column index of each value + pointers is array<number>, // offset of first value in each row + extent is number // max possible index + 1, i.e. number of columns } | - SparseCSC { - values is vec.vector_t, - indices is array<number>, // row index of each value - pointers is array<number>, // offset of first value in each column - extent is number // max pointers index + 1, i.e. number of rows - }; + SparseCSC { + values is vec.vector_t, + indices is array<number>, // row index of each value + pointers is array<number>, // offset of first value in each column + extent is number // max pointers index + 1, i.e. number of rows + } +}; -(); - -width m = - case m of - DenseRows r: - if not empty? r then vec.length r[0] else 0 fi; - DenseCols c: - length c; - SparseCSR { values, indices, pointers, extent }: - extent; - SparseCSC { values, indices, pointers, extent }: - (length pointers) - 1; - esac; - -height m = - case m of - DenseRows r: - length r; - DenseCols c: - if not empty? c then vec.length c[0] else 0 fi; - SparseCSR { values, indices, pointers, extent }: - (length pointers) - 1; - SparseCSC { values, indices, pointers, extent }: - extent; - esac; - -size m = { rows = height m, columns = width m }; +size m = m.size; +width m = m.size.columns; +height m = m.size.rows; nonZeroValues m = (nz d = @@ -94,7 +72,7 @@ (map do v: sum (map do n: if n == 0 then 0 else 1 fi done (vec.list v)) done d); - case m of + case m.data of DenseRows d: nz d; DenseCols d: nz d; SparseCSR d: vec.length d.values; @@ -142,7 +120,7 @@ vec.vector dslice); at' m row col = - case m of + case m.data of DenseRows rows: r = rows[row]; vec.at r col; DenseCols cols: c = cols[col]; vec.at c row; SparseCSR data: fromSlice row col data; @@ -152,14 +130,14 @@ //!!! better as getXx or just xx? getColumn j m = - case m of + case m.data of DenseCols cols: cols[j]; SparseCSC data: filledSlice j data; _: vec.fromList (map do i: at' m i j done [0..height m - 1]); esac; getRow i m = - case m of + case m.data of DenseRows rows: rows[i]; SparseCSR data: filledSlice i data; _: vec.fromList (map do j: at' m i j done [0..width m - 1]); @@ -178,7 +156,7 @@ map do i: getColumn i m done [0 .. (width m) - 1]; isRowMajor? m = - case m of + case m.data of DenseRows _: true; DenseCols _: false; SparseCSR _: true; @@ -186,7 +164,7 @@ esac; isSparse? m = - case m of + case m.data of DenseRows _: false; DenseCols _: false; SparseCSR _: true; @@ -203,36 +181,41 @@ else RowMajor () fi; +flippedSize { rows, columns } = { rows = columns, columns = rows }; + newColumnMajorStorage { rows, columns } = - if rows < 1 then array [] - else array (map \(vec.zeros rows) [1..columns]) - fi; + array (map \(vec.zeros rows) [1..columns]); -zeroMatrix { rows, columns } = - DenseCols (newColumnMajorStorage { rows, columns }); +zeroMatrix size = + { + size, + data = DenseCols (newColumnMajorStorage size) + }; -zeroMatrixWithTypeOf m { rows, columns } = - if isRowMajor? m then - DenseRows (newColumnMajorStorage { rows = columns, columns = rows }); - else - DenseCols (newColumnMajorStorage { rows, columns }); - fi; +zeroMatrixWithTypeOf m size = + { + size, + data = + if isRowMajor? m then + DenseRows (newColumnMajorStorage (flippedSize size)); + else + DenseCols (newColumnMajorStorage size); + fi + }; zeroSizeMatrix () = zeroMatrix { rows = 0, columns = 0 }; -empty?' m = (width m == 0 or height m == 0); - generate f { rows, columns } = - if rows < 1 or columns < 1 then zeroSizeMatrix () - else - m = array (map \(new double[rows]) [1..columns]); - for [0..columns-1] do col: - for [0..rows-1] do row: - m[col][row] := f row col; - done; + (m = array (map \(new double[rows]) [1..columns]); + for [0..columns-1] do col: + for [0..rows-1] do row: + m[col][row] := f row col; done; - DenseCols (array (map vec.vector m)) - fi; + done; + { + size = { rows, columns }, + data = DenseCols (array (map vec.vector m)) + }); swapij = map do { i, j, v }: { i = j, j = i, v } done; @@ -248,7 +231,7 @@ (slice indices start end) (vec.list (vec.slice values start end)) done [0..length pointers - 2]); - case m of + case m.data of SparseCSC d: swapij (enumerate d); SparseCSR d: enumerate d; _: []; @@ -263,7 +246,7 @@ [0..vec.length vv - 1] (vec.list vv); done [0..length d - 1]); - case m of + case m.data of DenseCols c: swapij (enumerate c); DenseRows r: enumerate r; _: []; @@ -303,11 +286,14 @@ esac; fi; fillPointers 0 0 (map (.maj) ordered); - tagger { - values = vec.fromList (map (.v) ordered), - indices = array (map (.min) ordered), - pointers, - extent = minorSize, + { + size, + data = tagger { + values = vec.fromList (map (.v) ordered), + indices = array (map (.min) ordered), + pointers, + extent = minorSize, + } }); // Make a sparse matrix from entries that may contain out-of-range @@ -330,24 +316,32 @@ fi; toDense m = - if not (isSparse? m) then m - elif isRowMajor? m then - DenseRows (array (map do row: getRow row m done [0..height m - 1])); - else - DenseCols (array (map do col: getColumn col m done [0..width m - 1])); - fi; + { + size = m.size, + data = + if not (isSparse? m) then m.data + elif isRowMajor? m then + DenseRows (array (map do row: getRow row m done [0..height m - 1])); + else + DenseCols (array (map do col: getColumn col m done [0..width m - 1])); + fi + }; constMatrix n = generate do row col: n done; randomMatrix = generate do row col: Math#random() done; identityMatrix = constMatrix 1; transposed m = - case m of - DenseRows d: DenseCols d; - DenseCols d: DenseRows d; - SparseCSR d: SparseCSC d; - SparseCSC d: SparseCSR d; - esac; + { + size = flippedSize m.size, + data = + case m.data of + DenseRows d: DenseCols d; + DenseCols d: DenseRows d; + SparseCSR d: SparseCSC d; + SparseCSC d: SparseCSR d; + esac + }; flipped m = if isSparse? m then @@ -357,8 +351,7 @@ generate do row col: at' m row col done (size m); else transposed - (generate do row col: at' m col row done - { rows = (width m), columns = (height m) }); + (generate do row col: at' m col row done (flippedSize (size m))); fi fi; @@ -376,21 +369,19 @@ vecComparator d1.values d2.values and d1.indices == d2.indices and d1.pointers == d2.pointers; - case m1 of + case m1.data of DenseRows d1: - case m2 of DenseRows d2: compareVecLists d1 d2; _: false; esac; + case m2.data of DenseRows d2: compareVecLists d1 d2; _: false; esac; DenseCols d1: - case m2 of DenseCols d2: compareVecLists d1 d2; _: false; esac; + case m2.data of DenseCols d2: compareVecLists d1 d2; _: false; esac; SparseCSR d1: - case m2 of SparseCSR d2: compareSparse d1 d2; _: false; esac; + case m2.data of SparseCSR d2: compareSparse d1 d2; _: false; esac; SparseCSC d1: - case m2 of SparseCSC d2: compareSparse d1 d2; _: false; esac; + case m2.data of SparseCSC d2: compareSparse d1 d2; _: false; esac; esac); equal' comparator vecComparator m1 m2 = - if empty?' m1 and empty?' m2 then - true - elif size m1 != size m2 then + if size m1 != size m2 then false elif isRowMajor? m1 != isRowMajor? m2 then equal' comparator vecComparator (flipped m1) m2; @@ -415,25 +406,56 @@ equal = equal' (==) vec.equal; -newMatrix type data = //!!! NB does not copy data - (tagger = case type of RowMajor (): DenseRows; ColumnMajor (): DenseCols esac; - if empty? data or vec.empty? (head data) - then zeroSizeMatrix () - else tagger (array data) - fi); +newMatrixOfSize size type rowscols = //!!! NB does not copy data + if type == RowMajor () then + { + size, + data = DenseRows (array rowscols) + } + else + { + size, + data = DenseCols (array rowscols) + } + fi; + +newMatrix type rowscols = //!!! NB does not copy data + if type == RowMajor () then + { + size = { + rows = length rowscols, + columns = + if empty? rowscols then 0 + else vec.length (head rowscols) + fi, + }, + data = DenseRows (array rowscols) + } + else + { + size = { + columns = length rowscols, + rows = + if empty? rowscols then 0 + else vec.length (head rowscols) + fi, + }, + data = DenseCols (array rowscols) + } + fi; newRowVector data = //!!! NB does not copy data - DenseRows (array [data]); + newMatrix (RowMajor ()) (array [data]); newColumnVector data = //!!! NB does not copy data - DenseCols (array [data]); + newMatrix (ColumnMajor ()) (array [data]); denseLinearOp op m1 m2 = if isRowMajor? m1 then - newMatrix (typeOf m1) + newMatrixOfSize m1.size (typeOf m1) (map2 do c1 c2: op c1 c2 done (asRows m1) (asRows m2)); else - newMatrix (typeOf m1) + newMatrixOfSize m1.size (typeOf m1) (map2 do c1 c2: op c1 c2 done (asColumns m1) (asColumns m2)); fi; @@ -480,9 +502,9 @@ makeSparse (typeOf m) (size m) (map do { i, j, v }: { i, j, v = factor * v } done (enumerate m)) elif isRowMajor? m then - newMatrix (typeOf m) (map (vec.scaled factor) (asRows m)); + newMatrixOfSize m.size (typeOf m) (map (vec.scaled factor) (asRows m)); else - newMatrix (typeOf m) (map (vec.scaled factor) (asColumns m)); + newMatrixOfSize m.size (typeOf m) (map (vec.scaled factor) (asColumns m)); fi; abs' m = @@ -490,9 +512,9 @@ makeSparse (typeOf m) (size m) (map do { i, j, v }: { i, j, v = abs v } done (enumerate m)) elif isRowMajor? m then - newMatrix (typeOf m) (map vec.abs (asRows m)); + newMatrixOfSize m.size (typeOf m) (map vec.abs (asRows m)); else - newMatrix (typeOf m) (map vec.abs (asColumns m)); + newMatrixOfSize m.size (typeOf m) (map vec.abs (asColumns m)); fi; negative m = @@ -500,9 +522,9 @@ makeSparse (typeOf m) (size m) (map do { i, j, v }: { i, j, v = (-v) } done (enumerate m)) elif isRowMajor? m then - newMatrix (typeOf m) (map vec.negative (asRows m)); + newMatrixOfSize m.size (typeOf m) (map vec.negative (asRows m)); else - newMatrix (typeOf m) (map vec.negative (asColumns m)); + newMatrixOfSize m.size (typeOf m) (map vec.negative (asColumns m)); fi; //!!! doc: filter by predicate, always returns sparse matrix @@ -518,11 +540,12 @@ all f (map (.v) (enumerate m)); sparseProductLeft size m1 m2 = - ({ values, indices, pointers } = case m1 of - SparseCSR d: d; - SparseCSC d: d; - _: failWith "sparseProductLeft called for non-sparse m1"; - esac; + ({ values, indices, pointers } = + case m1.data of + SparseCSR d: d; + SparseCSC d: d; + _: failWith "sparseProductLeft called for non-sparse m1"; + esac; rows = isRowMajor? m1; data = array (map \(new double[size.rows]) [1..size.columns]); for [0..size.columns - 1] do j': @@ -535,14 +558,15 @@ data[j'][i] := data[j'][i] + (vec.at values ix) * (vec.at c j); done; done; - DenseCols (array (map vec.vector (list data)))); + newMatrixOfSize size (ColumnMajor ()) (array (map vec.vector (list data)))); sparseProductRight size m1 m2 = - ({ values, indices, pointers } = case m2 of - SparseCSR d: d; - SparseCSC d: d; - _: failWith "sparseProductLeft called for non-sparse m1"; - esac; + ({ values, indices, pointers } = + case m2.data of + SparseCSR d: d; + SparseCSC d: d; + _: failWith "sparseProductLeft called for non-sparse m1"; + esac; rows = isRowMajor? m2; data = array (map \(new double[size.columns]) [1..size.rows]); for [0..size.rows - 1] do i': @@ -555,12 +579,13 @@ data[i'][j] := data[i'][j] + (vec.at values ix) * (vec.at r i); done; done; - DenseRows (array (map vec.vector (list data)))); + newMatrixOfSize size (RowMajor ()) (array (map vec.vector (list data)))); sparseProduct size m1 m2 = - case m2 of + case m2.data of SparseCSC d: - ({ values, indices, pointers } = case m1 of + ({ values, indices, pointers } = + case m1.data of SparseCSR d1: d1; SparseCSC d1: d1; _: failWith "sparseProduct called for non-sparse matrices"; @@ -605,7 +630,7 @@ data[j][i] := vec.sum (vec.multiply row (getColumn j m2)); done; done; - DenseCols (array (map vec.vector (list data)))); + newMatrixOfSize size (ColumnMajor ()) (array (map vec.vector (list data)))); product m1 m2 = if (size m1).columns != (size m2).rows @@ -672,7 +697,7 @@ failWith "Matrix dimensions incompatible for concat (found \(map do m: counter (size m) done mm) not all of which are \(n))"; fi); -concatHorizontal' mm = //!!! doc: storage order is taken from first matrix in sequence; concat is obviously not lazy (unlike std module) +concatHorizontal mm = //!!! doc: storage order is taken from first matrix in sequence; concat is obviously not lazy (unlike std module) case mm of [m]: m; first::rest: @@ -681,16 +706,20 @@ sparseConcat (Horizontal ()) first mm else row = isRowMajor? first; - // horizontal, row-major: against grain with rows - // horizontal, col-major: with grain with cols - if row then concatAgainstGrain DenseRows getRow (.rows) mm; - else concatWithGrain DenseCols getColumn (.columns) mm; - fi; + { + size = { rows = height first, columns = sum (map width mm) }, + data = + // horizontal, row-major: against grain with rows + // horizontal, col-major: with grain with cols + if row then concatAgainstGrain DenseRows getRow (.rows) mm; + else concatWithGrain DenseCols getColumn (.columns) mm; + fi + }; fi); _: zeroSizeMatrix (); esac; -concatVertical' mm = //!!! doc: storage order is taken from first matrix in sequence; concat is obviously not lazy (unlike std module) +concatVertical mm = //!!! doc: storage order is taken from first matrix in sequence; concat is obviously not lazy (unlike std module) case mm of [m]: m; first::rest: @@ -699,23 +728,19 @@ sparseConcat (Vertical ()) first mm else row = isRowMajor? first; - // vertical, row-major: with grain with rows - // vertical, col-major: against grain with cols - if row then concatWithGrain DenseRows getRow (.rows) mm; - else concatAgainstGrain DenseCols getColumn (.columns) mm; - fi; + { + size = { rows = sum (map height mm), columns = width first }, + data = + // vertical, row-major: with grain with rows + // vertical, col-major: against grain with cols + if row then concatWithGrain DenseRows getRow (.rows) mm; + else concatAgainstGrain DenseCols getColumn (.columns) mm; + fi, + }; fi); _: zeroSizeMatrix (); esac; -//!!! doc this filter -- zero-size elts are ignored -concatHorizontal mm = - concatHorizontal' (filter do mat: not (empty?' mat) done mm); - -//!!! doc this filter -- zero-size elts are ignored -concatVertical mm = - concatVertical' (filter do mat: not (empty?' mat) done mm); - //!!! next two v. clumsy //!!! doc note: argument order chosen for consistency with std module slice @@ -728,9 +753,13 @@ elif end > height m then rowSlice m start (height m) else if isRowMajor? m then - DenseRows (array (map ((flip getRow) m) [start .. end - 1])) + newMatrixOfSize { rows = end - start, columns = width m } + (RowMajor ()) + (array (map ((flip getRow) m) [start .. end - 1])) else - DenseCols (array (map do v: vec.slice v start end done (asColumns m))) + newMatrixOfSize { rows = end - start, columns = width m } + (ColumnMajor ()) + (array (map do v: vec.slice v start end done (asColumns m))) fi; fi; fi; @@ -745,9 +774,13 @@ elif end > width m then columnSlice m start (width m) else if not isRowMajor? m then - DenseCols (array (map ((flip getColumn) m) [start .. end - 1])) + newMatrixOfSize { rows = height m, columns = end - start } + (ColumnMajor ()) + (array (map ((flip getColumn) m) [start .. end - 1])) else - DenseRows (array (map do v: vec.slice v start end done (asRows m))) + newMatrixOfSize { rows = height m, columns = end - start } + (RowMajor ()) + (array (map do v: vec.slice v start end done (asRows m))) fi; fi; fi; @@ -786,24 +819,24 @@ fi); minValue m = - if empty?' m then 0 + if width m == 0 or height m == 0 then 0 else minv ll = fold min (head ll) (tail ll); minv (map (.v) (enumerate m)); fi; maxValue m = - if empty?' m then 0 + if width m == 0 or height m == 0 then 0 else maxv ll = fold max (head ll) (tail ll); maxv (map (.v) (enumerate m)); fi; transformRows rf m = - newMatrix (RowMajor ()) (map rf (asRows m)); + newMatrixOfSize m.size (RowMajor ()) (map rf (asRows m)); transformColumns cf m = - newMatrix (ColumnMajor ()) (map cf (asColumns m)); + newMatrixOfSize m.size (ColumnMajor ()) (map cf (asColumns m)); format m = strJoin "\n" @@ -846,8 +879,6 @@ randomMatrix, zeroMatrix, identityMatrix, - zeroSizeMatrix, - empty? = empty?', equal, //!!! if empty is empty?, why is equal not equal? ? equalUnder, transposed, @@ -903,8 +934,6 @@ randomMatrix is { rows is number, columns is number } -> matrix_t, zeroMatrix is { rows is number, columns is number } -> matrix_t, identityMatrix is { rows is number, columns is number } -> matrix_t, - zeroSizeMatrix is () -> matrix_t, - empty? is matrix_t -> boolean, equal is matrix_t -> matrix_t -> boolean, equalUnder is (number -> number -> boolean) -> matrix_t -> matrix_t -> boolean, transposed is matrix_t -> matrix_t,
--- a/src/may/matrix/test/test_matrix.yeti Wed Nov 20 12:17:21 2013 +0000 +++ b/src/may/matrix/test/test_matrix.yeti Wed Nov 20 13:57:32 2013 +0000 @@ -25,8 +25,9 @@ ), "constMatrixEmpty2-\(name)": \( - compare (mat.size (constMatrix 2 { rows = 0, columns = 4 })) { columns = 0, rows = 0 } and - compare (mat.size (constMatrix 2 { rows = 4, columns = 0 })) { columns = 0, rows = 0 } + compare (mat.size (constMatrix 2 { rows = 0, columns = 4 })) { columns = 4, rows = 0 } and + compare (mat.size (constMatrix 2 { rows = 4, columns = 0 })) { columns = 0, rows = 4 } and + compare (vec.list (mat.getColumn 2 (constMatrix 2 { rows = 0, columns = 4 }))) [] ), "constMatrix-\(name)": \( @@ -71,10 +72,15 @@ ), "generateEmpty-\(name)": \( - m = generate do row col: 0 done { rows = 0, columns = 0 }; + m = generate do row col: 6 done { rows = 0, columns = 0 }; compare (mat.size m) { columns = 0, rows = 0 } ), +"generateEmpty2-\(name)": \( + m = generate do row col: 6 done { rows = 4, columns = 0 }; + compare (mat.size m) { columns = 0, rows = 4 } +), + "generate-\(name)": \( m = generate do row col: row * 10 + col done { rows = 2, columns = 3 }; compare (vec.list (mat.getRow 0 m)) [0,1,2] and @@ -123,8 +129,8 @@ "transposedEmpty-\(name)": \( compare (mat.size (mat.transposed (constMatrix 2 { rows = 0, columns = 0 }))) { columns = 0, rows = 0 } and - compare (mat.size (mat.transposed (constMatrix 2 { rows = 0, columns = 4 }))) { columns = 0, rows = 0 } and - compare (mat.size (mat.transposed (constMatrix 2 { rows = 4, columns = 0 }))) { columns = 0, rows = 0 } + compare (mat.size (mat.transposed (constMatrix 2 { rows = 0, columns = 4 }))) { columns = 0, rows = 4 } and + compare (mat.size (mat.transposed (constMatrix 2 { rows = 4, columns = 0 }))) { columns = 4, rows = 0 } ), "transposedSize-\(name)": \( @@ -162,7 +168,7 @@ "flipped-empty-\(name)": \( m = constMatrix 2 { rows = 0, columns = 4 }; - compareMatrices (mat.flipped m) (mat.flipped (constMatrix 0 { rows = 0, columns = 0 })); + compareMatrices (mat.flipped m) (mat.flipped (constMatrix 0 { rows = 0, columns = 4 })); ), "toRowMajor-\(name)": \( @@ -199,7 +205,7 @@ (constMatrix (-1.5) { rows = 3, columns = 4 }) and compareMatrices (mat.scaled 0.5 (constMatrix 2 { rows = 0, columns = 2 })) - (constMatrix 5 { rows = 0, columns = 0 }) + (constMatrix 5 { rows = 0, columns = 2 }) ), "transformRows-\(name)": \( @@ -370,7 +376,7 @@ (newMatrix (RowMajor ()) [[1]]) and compareMatrices (mat.resizedTo { rows = 2, columns = 3 } - (mat.zeroSizeMatrix ())) + (mat.zeroMatrix { rows = 0, columns = 0 })) (newMatrix (RowMajor ()) [[0,0,0],[0,0,0]]) and mat.isSparse? (mat.resizedTo { rows = 1, columns = 1 } @@ -379,19 +385,18 @@ "zeroSizeMatrix-\(name)": \( compareMatrices - (mat.zeroSizeMatrix ()) + (mat.zeroMatrix { rows = 0, columns = 0 }) (newMatrix (ColumnMajor ()) []) and compareMatrices - (mat.zeroSizeMatrix ()) + (mat.zeroMatrix { rows = 0, columns = 1 }) (newMatrix (ColumnMajor ()) [[]]) and + (not mat.equal (newMatrix (ColumnMajor ()) [[]]) + (newMatrix (RowMajor ()) [[]])) and compareMatrices - (newMatrix (ColumnMajor ()) [[]]) - (newMatrix (RowMajor ()) [[]]) and + (mat.zeroMatrix { rows = 0, columns = 0 }) + (mat.newSparseMatrix (ColumnMajor ()) { rows = 0, columns = 0 } []) and compareMatrices - (mat.zeroSizeMatrix ()) - (mat.newSparseMatrix (ColumnMajor ()) { rows = 0, columns = 1 } []) and - compareMatrices - (mat.zeroSizeMatrix ()) + (mat.zeroMatrix { rows = 1, columns = 0 }) (mat.newSparseMatrix (ColumnMajor ()) { rows = 1, columns = 0 } []) ), @@ -421,14 +426,14 @@ compareMatrices (mat.concatHorizontal [(newMatrix (ColumnMajor ()) [[]]), - (newMatrix (RowMajor ()) [[]]), - (mat.zeroSizeMatrix ())]) - (mat.zeroSizeMatrix ()) and + (newMatrix (ColumnMajor ()) [[],[]]), + (mat.zeroMatrix { rows = 0, columns = 6 })]) + (mat.zeroMatrix { rows = 0, columns = 9 }) and compareMatrices (mat.concatHorizontal - [(newMatrix (ColumnMajor ()) [[]]), + [(newMatrix (RowMajor ()) [[]]), (newMatrix (RowMajor ()) [[1,2]]), - (mat.zeroSizeMatrix ())]) + (mat.zeroMatrix { rows = 1, columns = 0 })]) (newMatrix (RowMajor ()) [[1,2]]) ),
--- a/src/may/stream/convolve.yeti Wed Nov 20 12:17:21 2013 +0000 +++ b/src/may/stream/convolve.yeti Wed Nov 20 13:57:32 2013 +0000 @@ -74,7 +74,7 @@ s with { get finished? () = - s.finished? and (mat.empty? history), + s.finished? and mat.width history == 0, get available () = case s.available of Known n: Known (n + mat.width history);
--- a/src/may/stream/framer.yeti Wed Nov 20 12:17:21 2013 +0000 +++ b/src/may/stream/framer.yeti Wed Nov 20 13:57:32 2013 +0000 @@ -120,14 +120,14 @@ streamContiguous rate framesize frames = (var remaining = frames; - var buffered = mat.zeroSizeMatrix (); var position = 0; channels = mat.height (head frames); // so we don't need to keep a head ptr + var buffered = mat.zeroMatrix { rows = channels, columns = 0 }; { get position () = position, get channels () = channels, get sampleRate () = rate, - get finished? () = empty? remaining and mat.empty? buffered, + get finished? () = empty? remaining and mat.width buffered == 0, get available () = // Don't take length of frames -- we don't want to lose laziness. // If the caller cares that much, they can measure frames themselves @@ -170,21 +170,22 @@ first::rest: mat.concatHorizontal (ola rest first []); _: - mat.zeroSizeMatrix (); + mat.zeroMatrix { rows = 0, columns = 0 }; esac); streamOverlapping rate { framesize, hop, window } frames = (var remaining = frames; - var buffered = mat.zeroSizeMatrix (); var position = 0; factor = hop / (framesize/2); w = vec.scaled factor (window framesize); channels = mat.height (head frames); // so we don't need to keep a head ptr + var buffered = mat.zeroMatrix { rows = channels, columns = 0 }; + syncd = synchronized remaining; - finished' () = syncd \(empty? remaining and mat.empty? buffered); + finished' () = syncd \(empty? remaining and mat.width buffered == 0); read' count = (framesFor samples acc =
--- a/src/may/stream/manipulate.yeti Wed Nov 20 12:17:21 2013 +0000 +++ b/src/may/stream/manipulate.yeti Wed Nov 20 13:57:32 2013 +0000 @@ -125,9 +125,7 @@ { read count = (m = s.read count; - if mat.empty? m then m - else mat.difference (mat.zeroMatrix (mat.size m)) m - fi) + mat.difference (mat.zeroMatrix (mat.size m)) m) }; //!!! poor name, confusion with mixed, but consistent with channels.yeti @@ -149,13 +147,14 @@ (sz = { rows = max (mat.height m1) (mat.height m2), columns = min (mat.width m1) (mat.width m2) }; if sz.columns == 0 then - mat.zeroSizeMatrix () + mat.zeroMatrix sz else mat.sum (mat.resizedTo sz m1) (mat.resizedTo sz m2); fi); + channels = head (sortBy (>) (map (.channels) streams)); { get position () = head (sort (map (.position) streams)), - get channels () = head (sortBy (>) (map (.channels) streams)), + get channels () = channels, get sampleRate () = (head streams).sampleRate, //!!! document this get available () = fold do dur s: minDurationOf dur s.available done (Infinite ()) streams, @@ -174,7 +173,7 @@ _: acc; esac; case readTo (None ()) streams count of - None (): mat.zeroSizeMatrix (); + None (): mat.zeroMatrix { rows = channels, columns = 0 }; Some m: m; esac), close () = for streams do s: s.close() done, @@ -215,7 +214,7 @@ if s.available == Infinite () then s else var pos = 0; - var cache = mat.zeroSizeMatrix (); + var cache = mat.zeroMatrix { rows = s.channels, columns = 0 }; chunks = array []; cachedPartsFor count = (start = pos % (mat.width cache); @@ -269,7 +268,8 @@ var lowtide = 0; var hightide = 0; var adcount = 0; - var cache = mat.toRowMajor (mat.zeroSizeMatrix ()); + var cache = mat.toRowMajor + (mat.zeroMatrix { rows = s.channels, columns = 0 }); syncd = synchronized pos; advance i n = (wasLow = (pos[i] == lowtide); @@ -305,7 +305,8 @@ read count = syncd \(ready = hightide - pos[instance]; if s.finished? and ready <= 0 - then mat.toRowMajor (mat.zeroSizeMatrix ()) + then mat.toRowMajor + (mat.zeroMatrix { rows = s.channels, columns = 0 }) else if count > ready then more = s.read (count - ready);
--- a/src/may/stream/syntheticstream.yeti Wed Nov 20 12:17:21 2013 +0000 +++ b/src/may/stream/syntheticstream.yeti Wed Nov 20 13:57:32 2013 +0000 @@ -106,7 +106,7 @@ get sampleRate () = rate, get available () = Known 0, get finished? () = true, - read count = mat.zeroSizeMatrix (), + read count = mat.zeroMatrix { rows = channels, columns = 0 }, close = \(), };
--- a/src/may/stream/test/test_manipulate.yeti Wed Nov 20 12:17:21 2013 +0000 +++ b/src/may/stream/test/test_manipulate.yeti Wed Nov 20 13:57:32 2013 +0000 @@ -620,7 +620,7 @@ compare s2.finished? false and compare s2.available (Known 1) and // when one is known, so is the other - compare (map vec.list (mat.asRows (s1.read 3))) [] 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
--- a/src/may/test/test.yeti Wed Nov 20 12:17:21 2013 +0000 +++ b/src/may/test/test.yeti Wed Nov 20 13:57:32 2013 +0000 @@ -55,7 +55,8 @@ failedTests testHash = select (!= "") - (mapHash do name f: + (map do name: + f = testHash[name]; try if f () then "" else println "Test \(name) failed"; @@ -65,7 +66,7 @@ println "Test \(name) threw exception: \(e)"; name; yrt; - done testHash); + done (sort (keys testHash))); runTests group testHash = (start = System#currentTimeMillis();