changeset 223:51af10e6cd0d

Merge from matrix_opaque_immutable branch
author Chris Cannam
date Sat, 11 May 2013 16:00:58 +0100
parents cd2caf235e1f (current diff) 77c6a81c577f (diff)
children 1cfa054e3077
files yetilab/block/block.yeti yetilab/block/blockfuncs.yeti yetilab/block/blocktype.yeti yetilab/block/complex.yeti yetilab/block/fvector.yeti yetilab/block/test/test_blockfuncs.yeti yetilab/block/test/test_complex.yeti yetilab/block/test/test_fvector.yeti
diffstat 41 files changed, 1012 insertions(+), 954 deletions(-) [+]
line wrap: on
line diff
--- a/Makefile	Tue May 07 21:43:10 2013 +0100
+++ b/Makefile	Sat May 11 16:00:58 2013 +0100
@@ -10,7 +10,7 @@
 	jar cf $@ -C classes yetilab 
 
 clean:	
-	rm -rf com bin/.testrun
+	rm -rf com bin/.testrun classes
 
 distclean:	clean
 	rm -f yetilab.jar
--- a/yetilab/block/block.yeti	Tue May 07 21:43:10 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-
-module yetilab.block.block;
-
-vec = load yetilab.block.fvector;
-
-load yetilab.block.blocktype;
-
-{
-    zeros = vec.zeros,
-    consts = vec.consts,
-    ones = vec.ones,
-    block v = v,
-    data b = b,
-    vector b = vec.copyOf b,
-    floats = vec.floats,
-    fromFloats ff = vec.fromFloats ff,
-    fromList l = vec.vector l,
-    list = vec.list,
-    length = vec.length,
-    empty? = vec.empty?,
-    equal = vec.equal,
-    copyOf = vec.copyOf,
-    rangeOf = vec.rangeOf,
-    resizedTo = vec.resizedTo,
-    concat = vec.concat,
-} as {
-    zeros is number -> block,
-    consts is number -> number -> block,
-    ones is number -> block,
-    block is ~double[] -> block,
-    data is block -> ~double[],
-    vector is block -> ~double[],
-    floats is block -> ~float[],
-    fromFloats is ~float[] -> block,
-    fromList is list?<number> -> block,
-    list is block -> list<number>,
-    length is block -> number,
-    empty? is block -> boolean,
-    equal is block -> block -> boolean,
-    copyOf is block -> block,
-    rangeOf is number -> number -> block -> block, //!!! not well-named now block arg is at the end
-    resizedTo is number -> block -> block,
-    concat is list?<block> -> block,
-}
-
-
-
--- a/yetilab/block/blockfuncs.yeti	Tue May 07 21:43:10 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,68 +0,0 @@
-
-module yetilab.block.blockfuncs;
-
-b = load yetilab.block.block;
-vec = load yetilab.block.fvector;
-
-load yetilab.block.blocktype;
-
-sum' bl =
-   (v = b.data bl;
-    tot = new double[1];
-    for [0..length v - 1] do i:
-        tot[0] := tot[0] + v[i]
-    done;
-    tot[0]);
-
-mean bl =
-    case b.length bl of
-        0: 0;
-        len: sum' bl / len
-    esac;
-
-multiply b1 b2 =
-   (v1 = b.data b1;
-    v2 = b.data b2;
-    len = if length v1 < length v2 then length v1 else length v2 fi;
-    bb = vec.zeros len;
-    for [0..len-1] do i:
-        bb[i] := v1[i] * v2[i]
-    done;
-    b.block bb);
-
-divideBy n bl =
-    b.fromList (map (/ n) (b.list bl));
-
-sqr bl =
-    multiply bl bl;
-
-rms =
-    sqrt . mean . sqr;
-
-sqrt' =
-    b.fromList . (map sqrt) . b.list;
-
-fftshift bl =
-   (len = b.length bl;
-    half = int(len/2 + 0.5); // round up for odd-length sequences
-    b.concat [b.rangeOf half (len-half) bl, b.rangeOf 0 half bl]);
-
-ifftshift bl =
-   (len = b.length bl;
-    half = int(len/2); // round down for odd-length sequences
-    b.concat [b.rangeOf half (len-half) bl, b.rangeOf 0 half bl]);
-
-{
-sum is block -> number = sum',
-mean is block -> number,
-multiply is block -> block -> block, 
-divideBy is number -> block -> block, 
-sqr is block -> block,
-sqrt is block -> block = sqrt',
-rms is block -> number,
-fftshift is block -> block,
-ifftshift is block -> block,
-}
-
-
-        
--- a/yetilab/block/blocktype.yeti	Tue May 07 21:43:10 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,7 +0,0 @@
-
-module yetilab.block.blocktype;
-
-typedef opaque block = ~double[];
-
-();
-
--- a/yetilab/block/complex.yeti	Tue May 07 21:43:10 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,99 +0,0 @@
-
-module yetilab.block.complex;
-
-load yetilab.block.blocktype;
-
-bl = load yetilab.block.block;
-
-import java.lang: ClassCastException;
-
-class Cplx(double real, double imag)
-    int getReal()
-        real,
-    int getImag()
-        imag,
-    double getMagnitude()
-        sqrt (real * real + imag * imag),
-    double getAngle()
-        Math#atan2(imag, real),
-    String toString()
-        if real == int real and imag == int imag then
-            if imag < 0 then
-                " \(int real) - \(int (-imag))i"
-            else 
-                " \(int real) + \(int imag)i"
-            fi
-        else
-            if imag < 0 then
-                " \(real) - \((-imag))i"
-            else 
-                " \(real) + \(imag)i"
-            fi
-        fi,
-    int hashCode()
-        Double#valueOf(real)#hashCode() + Double#valueOf(imag)#hashCode(),
-    boolean equals(Object other)
-        try
-            c = other unsafely_as ~Cplx;
-            c#getReal() == real and c#getImag() == imag
-        catch ClassCastException:
-            false
-        yrt,
-end;
-
-typedef opaque cplx = ~Cplx;
-
-real c1 is ~Cplx -> number =
-    c1#getReal();
-
-imaginary c1 is ~Cplx -> number =
-    c1#getImag();
-
-complex re im is number -> number -> ~Cplx =
-    new Cplx(re, im);
-
-magnitude c is ~Cplx -> number =
-    c#getMagnitude();
-
-angle c is ~Cplx -> number =
-    c#getAngle();
-
-add c1 c2 is ~Cplx -> ~Cplx -> ~Cplx =
-    complex (real c1 + real c2) (imaginary c1 + imaginary c2);
-
-scale r c is number -> ~Cplx -> ~Cplx =
-    complex (r * real c) (r * imaginary c);
-
-zeros n is number -> array<~Cplx> =
-    array (map \(complex 0 0) [1..n]);
-
-magnitudes cc is list?<~Cplx> -> block =
-    bl.fromList (map magnitude cc);
-
-angles cc is list?<~Cplx> -> block =
-    bl.fromList (map angle cc);
-
-{
-   real,
-   imaginary,
-   complex,
-   magnitude,
-   angle,
-   add,
-   scale,
-   zeros,
-   magnitudes,
-   angles,
-} as {
-   real is cplx -> number,
-   imaginary is cplx -> number,
-   complex is number -> number -> cplx,
-   magnitude is cplx -> number,
-   angle is cplx -> number,
-   add is cplx -> cplx -> cplx,
-   scale is number -> cplx -> cplx,
-   zeros is number -> array<cplx>,
-   magnitudes is list?<cplx> -> block,
-   angles is list?<cplx> -> block,
-}
-
--- a/yetilab/block/fvector.yeti	Tue May 07 21:43:10 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,85 +0,0 @@
-module yetilab.block.fvector;
-
-import java.util: Arrays;
-
-zeros n =
-    new double[n];
-
-consts m n =
-   (a = zeros n;
-    for [0..n-1] do i:
-        a[i] := m;
-    done;
-    a);
-
-ones = consts 1.0;
-
-vector l is list?<number> -> ~double[] =
-   (arr = array(l);
-    len = length arr;
-    v = zeros len;
-    for [0..len-1] do i:
-        v[i] := arr[i];
-    done;
-    v);
-
-list' a is ~double[] -> list<number> =
-    list a;
-
-length' =
-    length . list';
-
-empty?' =
-    empty? . list';
-
-floats a is ~double[] -> ~float[] =
-   (len = length' a;
-    f = new float[len];
-    for [0..len-1] do i:
-        f[i] := a[i];
-    done;
-    f);
-
-fromFloats ff is ~float[] -> ~double[] =
-   (len = length (list ff);
-    a = new double[len];
-    for [0..len-1] do i:
-        a[i] := ff[i];
-    done;
-    a);
-
-equal v1 v2 =
-    list' v1 == list' v2;
-
-copyOf v is ~double[] -> ~double[] =
-    Arrays#copyOf(v, list' v |> length);
-
-rangeOf start len v is number -> number -> ~double[] -> ~double[] =
-    Arrays#copyOfRange(v, start, start + len);
-
-resizedTo n v is number -> ~double[] -> ~double[] =
-    Arrays#copyOf(v, n);
-
-concat vv is list?<~double[]> -> ~double[] =
-   (len = sum (map length' vv);
-    vout = zeros len;
-    var base = 0;
-    for vv do v: 
-        vlen = length' v;
-        for [0..vlen-1] do i: vout[base + i] := v[i] done;
-        base := base + vlen;
-    done;
-    vout);
-
-{
-zeros, consts, ones,
-vector,
-length = length',
-empty? = empty?',
-list = list',
-floats, fromFloats,
-equal,
-copyOf, rangeOf, resizedTo,
-concat,
-}
-
--- a/yetilab/block/test/test_blockfuncs.yeti	Tue May 07 21:43:10 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,68 +0,0 @@
-
-module yetilab.block.test.test_blockfuncs;
-
-stdSqrt = sqrt;
-
-{ zeros, consts, ones, fromList, list } = load yetilab.block.block;
-{ sum, mean, multiply, divideBy, sqr, sqrt, rms, fftshift, ifftshift } = load yetilab.block.blockfuncs;
-{ compare } = load yetilab.test.test;
-
-[
-
-"sum": \(
-    compare ((sum . zeros) 0) 0 and
-        compare ((sum . zeros) 5) 0 and
-        compare ((sum . ones) 5) 5 and
-        compare ((sum . fromList) [1,-2,3,0]) 2
-),
-
-"mean": \(
-    compare ((mean . zeros) 0) 0 and
-        compare ((mean . zeros) 5) 0 and
-        compare ((mean . ones) 5) 1 and
-        compare ((mean . fromList) [1,-2,3,0]) 0.5
-),
-
-"multiply": \(
-    compare (list (multiply (zeros 0) (ones 5))) [] and
-        compare (list (multiply (consts (-3) 4) (fromList [1,2,3]))) [-3,-6,-9]
-),
-
-"divideBy": \(
-    compare (list (divideBy 5 (ones 0))) [] and
-        compare (list (divideBy 5 (fromList [1,2,-3]))) [0.2,0.4,-0.6]
-),
-
-"sqr": \(
-    compare ((list . sqr . zeros) 0) [] and
-        compare ((list . sqr . ones) 5) [1,1,1,1,1] and
-        compare ((list . sqr . fromList) [0.5,-2,3,0]) [0.25,4,9,0]
-),
-
-"sqrt": \(
-    compare ((list . sqrt . zeros) 0) [] and
-        compare ((list . sqrt . ones) 5) [1,1,1,1,1] and
-        compare ((list . sqrt . fromList) [0.25,4,9,0]) [0.5,2,3,0]
-),
-
-"rms": \(
-    compare ((rms . zeros) 0) 0 and
-        compare ((rms . ones) 5) 1 and
-        compare ((rms . fromList) [-1,2,2]) (stdSqrt 3)
-),
-
-"fftshift": \(
-    compare ((list . fftshift . zeros) 0) [] and 
-        compare ((list . fftshift . fromList) [1,2,3,4]) [3,4,1,2] and
-        compare ((list . fftshift . fromList) [1,2,3,4,5]) [4,5,1,2,3]
-),
-
-"ifftshift": \(
-    compare ((list . ifftshift . zeros) 0) [] and 
-        compare ((list . ifftshift . fromList) [3,4,1,2]) [1,2,3,4] and
-        compare ((list . ifftshift . fromList) [4,5,1,2,3]) [1,2,3,4,5]
-),
-
-] is hash<string, () -> boolean>;
-
-
--- a/yetilab/block/test/test_complex.yeti	Tue May 07 21:43:10 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-module yetilab.block.test.test_complex;
-
-{ real, imaginary, complex, magnitude, angle, add, scale, zeros, magnitudes, angles }
-   = load yetilab.block.complex;
-
-{ compare } = load yetilab.test.test;
-
-block = load yetilab.block.block;
-
-[
-
-"complex": \( 
-    compare (complex 1 2) (complex 1 2) and
-        complex (-1) 2 != complex 1 2
-),
-
-"real": \(
-    compare (real (complex 3 2)) 3
-),
-
-"imaginary": \(
-    compare (imaginary (complex 3 4)) 4
-),
-
-"magnitude": \(
-    compare (magnitude (complex (-3) 4)) 5
-),
-
-"angle": \(
-    compare (angle (complex 1 0)) 0 and
-        compare (angle (complex 1 1)) (pi/4) and
-        compare (angle (complex 0 1)) (pi/2) and
-        compare (angle (complex (-1) 0)) pi and
-        compare (angle (complex 0 (-1))) (-pi/2)
-),
-
-"add": \(
-    compare (add (complex 2 3) (complex (-4) 5)) (complex (-2) 8)
-),
-
-"scale": \(
-    compare (scale 4 (complex 2 3)) (complex 8 12)
-),
-
-"zeros": \(
-    compare (zeros 0) (array []) and
-        compare (zeros 3) (array [complex 0 0, complex 0 0, complex 0 0])
-),
-
-"magnitudes": \(
-    compare (block.list (magnitudes [ complex (-3) 4, complex 4 3, complex 0 0 ]))
-            [ 5, 5, 0 ] and
-       compare (block.list (magnitudes (array []))) []
-),
-
-"angles": \(
-    compare (block.list (angles [ complex 1 0, complex (-1) 0, complex 0 (-1) ]))
-            [ 0, pi, -pi/2 ] and
-       compare (block.list (angles (array []))) []
-),
-
-
-] is hash<string, () -> boolean>;
-
-
-
--- a/yetilab/block/test/test_fvector.yeti	Tue May 07 21:43:10 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,126 +0,0 @@
-
-module yetilab.block.test.test_fvector;
-
-vec = load yetilab.block.fvector;
-
-{ compare } = load yetilab.test.test;
-
-[
-
-"zeros-empty": \(
-    v = vec.zeros 0;
-    compare (vec.length v) 0;
-),
-
-"zeros": \(
-    v = vec.zeros 3;
-    compare (vec.length v) 3 and
-        compare v[0] 0 and
-        compare v[1] 0 and
-        compare v[2] 0;
-),
-
-"consts-empty": \(
-    v = vec.consts 4 0;
-    compare (vec.length v) 0;
-),
-
-"consts": \(
-    v = vec.consts 4 3;
-    compare (vec.length v) 3 and
-        compare v[0] 4 and
-        compare v[1] 4 and
-        compare v[2] 4;
-),
-
-"ones-empty": \(
-    v = vec.ones 0;
-    compare (vec.length v) 0;
-),
-
-"ones": \(
-    v = vec.ones 3;
-    compare (vec.length v) 3 and
-        compare v[0] 1 and
-        compare v[1] 1 and
-        compare v[2] 1;
-),
-
-"from-list-empty": \(
-    v = vec.vector [];
-    compare (vec.length v) 0;
-),
-
-"from-list": \(
-    v = vec.vector [1,2,3,4];
-    compare (vec.length v) 4 and
-        compare v[0] 1 and
-        compare v[1] 2 and
-        compare v[2] 3 and
-        compare v[3] 4;
-),
-
-"equal-empty": \(
-    vec.equal (vec.vector []) (vec.vector [])
-),
-
-"equal": \(
-    v = vec.vector [1,1,1,1];
-    w = vec.ones 4;
-    w' = vec.zeros 4;
-    w'' = vec.ones 3;
-    vec.equal v w and not vec.equal v w' and not vec.equal v w'';
-),
-
-"copyOf-empty": \(
-    vec.equal (vec.vector []) (vec.copyOf (vec.vector []))
-),
-
-"copyOf": \(
-    v = vec.vector [1,2,3,4];
-    w = vec.copyOf v;
-    vec.equal v w and (
-        v[0] := 0; // check result is not aliasing inputs
-        not vec.equal v w
-    );
-),
-
-"rangeOf": \(
-    v = vec.vector [1,2,3,4];
-    vec.equal (vec.rangeOf 0 4 v) v and (
-        vec.equal (vec.rangeOf 2 2 v) (vec.vector [3,4])
-    )
-),
-
-"resizedTo": \(
-    vec.equal (vec.resizedTo 4 (vec.vector [])) (vec.zeros 4) and
-        vec.equal (vec.resizedTo 2 (vec.vector [1,2])) (vec.vector [1,2]) and
-        vec.equal (vec.resizedTo 3 (vec.vector [1,2])) (vec.vector [1,2,0]) and
-        vec.equal (vec.resizedTo 2 (vec.vector [1,2,3])) (vec.vector [1,2]);
-),
-
-"concat2": \(
-    v = vec.vector [1,2,3];
-    w = vec.vector [4,5,6];
-    x = vec.concat [v, w];
-    x' = vec.vector [1,2,3,4,5,6];
-    vec.equal x x' and
-       (v[0] := 0; // check result is not aliasing inputs
-        w[0] := 0;
-        vec.equal x x') and
-        vec.equal x' (vec.concat [x', vec.vector []]) and
-        vec.equal x' (vec.concat [vec.vector [], x'])
-),
-
-"concatn": \(
-    v = vec.vector [1,2,3];
-    w = vec.vector [4,5,6];
-    vec.equal (vec.concat []) (vec.zeros 0) and
-        vec.equal (vec.concat [v]) v and
-        vec.equal (vec.concat [v,w,v]) (vec.vector [1,2,3,4,5,6,1,2,3])
-),
-
-] is hash<string, () -> boolean>;
-
-
-
--- a/yetilab/feature/features.yeti	Tue May 07 21:43:10 2013 +0100
+++ b/yetilab/feature/features.yeti	Sat May 11 16:00:58 2013 +0100
@@ -1,17 +1,17 @@
 
 module yetilab.feature.features;
 
-block = load yetilab.block.block;
-cplx = load yetilab.block.complex;
+vec = load yetilab.vector.vector;
+cplx = load yetilab.vector.complex;
 fr = load yetilab.stream.framer;
 
 magdiff frame1 frame2 =
-    sum (map2 do a b: abs(a - b) done (block.data frame1) (block.data frame2));
+    sum (map2 do a b: abs(a - b) done (vec.list frame1) (vec.list frame2));
 
 emptyFrameFor frames =
-    block.zeros
+    vec.zeros
         if empty? frames then 0
-        else block.length (head frames)
+        else vec.length (head frames)
         fi;
 
 features featureFunc frames =
--- a/yetilab/matrix/matrix.yeti	Tue May 07 21:43:10 2013 +0100
+++ b/yetilab/matrix/matrix.yeti	Sat May 11 16:00:58 2013 +0100
@@ -1,7 +1,7 @@
 
 module yetilab.matrix.matrix;
 
-// A matrix is an array of fvectors (i.e. primitive double[]s).
+// A matrix is an array of vectors.
 
 // A matrix can be stored in either column-major (the default) or
 // row-major format. Storage order is an efficiency concern only:
@@ -9,56 +9,64 @@
 // result regardless of storage order.  (The transpose function just
 // switches the row/column order without moving the elements.)
 
-vec = load yetilab.block.fvector;
-block = load yetilab.block.block;
-bf = load yetilab.block.blockfuncs;
+//!!! check that we are not unnecessarily copying in the transform functions
 
-load yetilab.block.blocktype;
+vec = load yetilab.vector.vector;
+bf = load yetilab.vector.blockfuncs;
+
+load yetilab.vector.vectortype;
 load yetilab.matrix.matrixtype;
 
-make d = {
-    get data () = d,
-    get size () =
-        case d of
-        RowM r:
-            major = length r;
-            { 
-                rows = major, 
-                columns = if major > 0 then vec.length r[0] else 0 fi,
-            };
-        ColM c:
-            major = length c;
-            { 
-                rows = if major > 0 then vec.length c[0] else 0 fi,
-                columns = major, 
-            };
-        esac,
-    getColumn j =
-        case d of
-        RowM rows: block.fromList (map do i: getAt i j done [0..length rows-1]);
-        ColM cols: block.block cols[j];
-        esac,
-    getRow i =
-        case d of
-        RowM rows: block.block rows[i];
-        ColM cols: block.fromList (map do j: getAt i j done [0..length cols-1]);
-        esac,
-    getAt row col =
-        case d of
-        RowM rows: r = rows[row]; (r is ~double[])[col];
-        ColM cols: c = cols[col]; (c is ~double[])[row];
-        esac,
-    setAt row col n = //!!! dangerous, could modify copies -- should it be allowed?
-        case d of
-        RowM rows: r = rows[row]; (r is ~double[])[col] := n;
-        ColM cols: c = cols[col]; (c is ~double[])[row] := n;
-        esac,
-    get isRowMajor? () =
-        case d of
-        RowM _: true;
-        ColM _: false;
-        esac,
-    };
+size m =
+    case m of
+    RowM r:
+        major = length r;
+        { 
+            rows = major, 
+            columns = if major > 0 then vec.length r[0] else 0 fi,
+        };
+    ColM c:
+        major = length c;
+        { 
+            rows = if major > 0 then vec.length c[0] else 0 fi,
+            columns = major, 
+        };
+    esac;
+
+width m = (size m).columns;
+height m = (size m).rows;
+
+getAt row col m =
+    case m of
+    RowM rows: r = rows[row]; vec.at col r;
+    ColM cols: c = cols[col]; vec.at row c;
+    esac;
+
+getColumn j m =
+    case m of
+    RowM rows: vec.fromList (map do i: getAt i j m done [0..length rows-1]);
+    ColM cols: cols[j];
+    esac;
+
+getRow i m =
+    case m of
+    RowM rows: rows[i];
+    ColM cols: vec.fromList (map do j: getAt i j m done [0..length cols-1]);
+    esac;
+
+/*
+setAt row col n m = //!!! dangerous, could modify copies -- should it be allowed?
+    case m of
+    RowM rows: r = rows[row]; (vec.data r)[col] := n;
+    ColM cols: c = cols[col]; (vec.data c)[row] := n;
+    esac;
+*/
+
+isRowMajor? m =
+    case m of
+    RowM _: true;
+    ColM _: false;
+    esac;
 
 newColMajorStorage { rows, columns } = 
     if rows < 1 then array []
@@ -66,133 +74,134 @@
     fi;
 
 zeroMatrix { rows, columns } = 
-    make (ColM (newColMajorStorage { rows, columns }));
+    ColM (newColMajorStorage { rows, columns });
 
 zeroMatrixWithTypeOf m { rows, columns } = 
-    if m.isRowMajor? then
-        make (RowM (newColMajorStorage { rows = columns, columns = rows }));
+    if isRowMajor? m then
+        RowM (newColMajorStorage { rows = columns, columns = rows });
     else
-        make (ColM (newColMajorStorage { rows, columns }));
+        ColM (newColMajorStorage { rows, columns });
     fi;
 
+zeroSizeMatrix () = zeroMatrix { rows = 0, columns = 0 };
+
 generate f { rows, columns } =
-   (m = newColMajorStorage { rows, columns };
-    for [0..columns-1] do col:
-        for [0..rows-1] do row:
-            m[col][row] := f row col;
+    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;
         done;
-    done;
-    make (ColM m));
+        ColM (array (map vec.vector m))
+    fi;
 
 constMatrix n = generate do row col: n done;
 randomMatrix = generate do row col: Math#random() done;
 identityMatrix = constMatrix 1;
-zeroSizeMatrix () = zeroMatrix { rows = 0, columns = 0 };
-
-width m = m.size.columns;
-height m = m.size.rows;
 
 transposed m =
-    make
-       (case m.data of
-        RowM d: ColM d;
-        ColM d: RowM d;
-        esac);
+    case m of
+    RowM d: ColM d;
+    ColM d: RowM d;
+    esac;
 
 flipped m =
-    if m.isRowMajor? then
-        generate do row col: m.getAt row col done m.size;
+    if isRowMajor? m then
+        generate do row col: getAt row col m done (size m);
     else
         transposed
-           (generate do row col: m.getAt col row done
-            { rows = m.size.columns, columns = m.size.rows });
+           (generate do row col: getAt col row m done
+            { rows = (width m), columns = (height m) });
     fi;
 
 toRowMajor m =
-    if m.isRowMajor? then m else flipped m fi;
+    if isRowMajor? m then m else flipped m fi;
 
 toColumnMajor m =
-    if not m.isRowMajor? then m else flipped m fi;
+    if not isRowMajor? m then m else flipped m fi;
 
 // Matrices with different storage order but the same contents are
 // equal (but comparing them is slow)
 equal m1 m2 =
-    if m1.size != m2.size then false
-    elif m1.isRowMajor? != m2.isRowMajor? then equal (flipped m1) m2;
+    if size m1 != size m2 then false
+    elif isRowMajor? m1 != isRowMajor? m2 then equal (flipped m1) m2;
     else
         compare d1 d2 = all id (map2 vec.equal d1 d2);
-        case m1.data of
-        RowM d1: case m2.data of RowM d2: compare d1 d2; _: false; esac;
-        ColM d1: case m2.data of ColM d2: compare d1 d2; _: false; esac;
+        case m1 of
+        RowM d1: case m2 of RowM d2: compare d1 d2; _: false; esac;
+        ColM d1: case m2 of ColM d2: compare d1 d2; _: false; esac;
         esac
     fi;
 
+/*!!! not needed now it's immutable?
 copyOf m =
    (copyOfData d = (array (map vec.copyOf d));
-    make
-       (case m.data of
-        RowM d: RowM (copyOfData d);
-        ColM d: ColM (copyOfData d);
-        esac));
+    case m of
+    RowM d: RowM (copyOfData d);
+    ColM d: ColM (copyOfData d);
+    esac);
+*/
 
 newMatrix type data = //!!! NB does not copy data
    (tagger = case type of RowMajor (): RowM; ColumnMajor (): ColM esac;
-    if empty? data or block.empty? (head data)
+    if empty? data or vec.empty? (head data)
     then zeroSizeMatrix ()
-    else make (tagger (array (map block.data data)))
+    else tagger (array data)
     fi);
 
 newRowVector data = //!!! NB does not copy data
-    make (RowM (array [block.data data]));
+    RowM (array [data]);
 
 newColumnVector data = //!!! NB does not copy data
-    make (ColM (array [block.data data]));
+    ColM (array [data]);
 
 scaled factor m = //!!! v inefficient
-    generate do row col: factor * m.getAt row col done m.size;
+    generate do row col: factor * (getAt row col m) done (size m);
 
 sum' m1 m2 =
-    if m1.size != m2.size
-    then failWith "Matrices are not the same size: \(m1.size), \(m2.size)";
+    if (size m1) != (size m2)
+    then failWith "Matrices are not the same size: \(size m1), \(size m2)";
     else
-        generate do row col: m1.getAt row col + m2.getAt row col done m1.size;
+        generate do row col: getAt row col m1 + getAt row col m2 done (size m1);
     fi;
 
 product m1 m2 =
-    if m1.size.columns != m2.size.rows
-    then failWith "Matrix dimensions incompatible: \(m1.size), \(m2.size) (\(m1.size.columns != m2.size.rows)";
+    if (size m1).columns != (size m2).rows
+    then failWith "Matrix dimensions incompatible: \(size m1), \(size m2) (\((size m1).columns != (size m2).rows)";
     else
         generate do row col:
-            bf.sum (bf.multiply (m1.getRow row) (m2.getColumn col))
-        done { rows = m1.size.rows, columns = m2.size.columns }
+            bf.sum (bf.multiply (getRow row m1) (getColumn col m2))
+        done { rows = (size m1).rows, columns = (size m2).columns }
     fi;
 
 asRows m =
-    map m.getRow [0 .. m.size.rows - 1];
+    map do i: getRow i m done [0 .. (height m) - 1];
 
 asColumns m =
-    map m.getColumn [0 .. m.size.columns - 1];
+    map do i: getColumn i m done [0 .. (width m) - 1];
 
 concatAgainstGrain tagger getter counter mm =
-   (n = counter (head mm).size;
-    make (tagger (array
+   (n = counter (size (head mm));
+    tagger (array
        (map do i:
-           block.data (block.concat (map do m: getter m i done mm))
-           done [0..n-1]))));
+           vec.concat (map (getter i) mm)
+           done [0..n-1])));
 
 concatWithGrain tagger getter counter mm =
-    make (tagger (array
+    tagger (array
        (concat
            (map do m:
-               n = counter m.size;
-               map do i: block.data (getter m i) done [0..n-1]
-               done mm))));
+               n = counter (size m);
+               map do i: getter i m done [0..n-1]
+               done mm)));
 
 checkDimensionsFor direction first mm =
    (counter = if direction == Horizontal () then (.rows) else (.columns) fi;
-    n = counter first.size;
-    if not (all id (map do m: counter m.size == n done mm)) then
-        failWith "Matrix dimensions incompatible for concat (found \(map do m: counter m.size done mm) not all of which are \(n))";
+    n = counter (size first);
+    if not (all id (map do m: counter (size m) == n done mm)) then
+        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
@@ -200,19 +209,19 @@
     case mm of
     first::rest: 
         checkDimensionsFor direction first mm;
-        row = first.isRowMajor?;
+        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 RowM (.getRow) (.rows) mm;
-            else concatWithGrain ColM (.getColumn) (.columns) mm;
+            if row then concatAgainstGrain RowM getRow (.rows) mm;
+            else concatWithGrain ColM getColumn (.columns) mm;
             fi;
         Vertical ():
-            if row then concatWithGrain RowM (.getRow) (.rows) mm;
-            else concatAgainstGrain ColM (.getColumn) (.columns) mm;
+            if row then concatWithGrain RowM getRow (.rows) mm;
+            else concatAgainstGrain ColM getColumn (.columns) mm;
             fi;
         esac;
     [single]: single;
@@ -220,28 +229,28 @@
     esac;
 
 rowSlice start count m = //!!! doc: storage order same as input
-    if m.isRowMajor? then
-        make (RowM (array (map (block.data . m.getRow) [start .. start + count - 1])))
+    if isRowMajor? m then
+        RowM (array (map ((flip getRow) m) [start .. start + count - 1]))
     else 
-        make (ColM (array (map (block.data . (block.rangeOf start count)) (asColumns m))))
+        ColM (array (map (vec.rangeOf start count) (asColumns m)))
     fi;
 
 columnSlice start count m = //!!! doc: storage order same as input
-    if not m.isRowMajor? then
-        make (ColM (array (map (block.data . m.getColumn) [start .. start + count - 1])))
+    if not isRowMajor? m then
+        ColM (array (map ((flip getColumn) m) [start .. start + count - 1]))
     else 
-        make (RowM (array (map (block.data . (block.rangeOf start count)) (asRows m))))
+        RowM (array (map (vec.rangeOf start count) (asRows m)))
     fi;
 
 resizedTo newsize m =
-   (if newsize == m.size then
+   (if newsize == (size m) then
         m
-    elif m.size.rows == 0 or m.size.columns == 0 then
+    elif (height m) == 0 or (width m) == 0 then
         zeroMatrixWithTypeOf m newsize;
     else
-        growrows = newsize.rows - m.size.rows;
-        growcols = newsize.columns - m.size.columns;
-        rowm = m.isRowMajor?;
+        growrows = newsize.rows - (height m);
+        growcols = newsize.columns - (width m);
+        rowm = isRowMajor? m;
         resizedTo newsize
             if rowm and growrows < 0 then
                 rowSlice 0 newsize.rows m
@@ -254,40 +263,83 @@
             else
                 if growrows > 0 then
                     concat (Vertical ())
-                       [m, zeroMatrixWithTypeOf m (m.size with { rows = growrows })]
+                       [m, zeroMatrixWithTypeOf m ((size m) with { rows = growrows })]
                 else
                     concat (Horizontal ())
-                       [m, zeroMatrixWithTypeOf m (m.size with { columns = growcols })]
+                       [m, zeroMatrixWithTypeOf m ((size m) with { columns = growcols })]
                 fi
             fi
     fi);
 
 {
+    size,
+    width,
+    height,
+    getAt,
+    getColumn,
+    getRow,
+//    setAt,
+    isRowMajor?,
+    generate,
+    constMatrix,
+    randomMatrix,
+    zeroMatrix,
+    identityMatrix,
+    zeroSizeMatrix,
+    equal,
+//    copyOf,
+    transposed,
+    flipped,
+    toRowMajor,
+    toColumnMajor,
+    scaled,
+    resizedTo,
+    asRows,
+    asColumns,
+    sum = sum',
+    product,
+    concat,
+    rowSlice,
+    columnSlice,
+    newMatrix,
+    newRowVector,
+    newColumnVector,
+}
+as
+{
+//!!! check whether these are right to be .selector rather than just selector
+
+    size is matrix -> { .rows is number, .columns is number },
+    width is matrix -> number,
+    height is matrix -> number,
+    getAt is number -> number -> matrix -> number,
+    getColumn is number -> matrix -> vector,
+    getRow is number -> matrix -> vector,
+//    setAt is number -> number -> number -> matrix -> (), //!!! lose?
+    isRowMajor? is matrix -> boolean,
     generate is (number -> number -> number) -> { .rows is number, .columns is number } -> matrix,
     constMatrix is number -> { .rows is number, .columns is number } -> matrix,
     randomMatrix is { .rows is number, .columns is number } -> matrix,
     zeroMatrix is { .rows is number, .columns is number } -> matrix, 
     identityMatrix is { .rows is number, .columns is number } -> matrix, 
     zeroSizeMatrix is () -> matrix,
-    width is matrix -> number,
-    height is matrix -> number,
     equal is matrix -> matrix -> boolean,
-    copyOf is matrix -> matrix,
+//    copyOf is matrix -> matrix,
     transposed is matrix -> matrix,
     flipped is matrix -> matrix, 
     toRowMajor is matrix -> matrix, 
     toColumnMajor is matrix -> matrix,
     scaled is number -> matrix -> matrix,
     resizedTo is { .rows is number, .columns is number } -> matrix -> matrix,
-    asRows is matrix -> list<block>, 
-    asColumns is matrix -> list<block>,
-    sum is matrix -> matrix -> matrix = sum',
+    asRows is matrix -> list<vector>, 
+    asColumns is matrix -> list<vector>,
+    sum is matrix -> matrix -> matrix,
     product is matrix -> matrix -> matrix,
     concat is (Horizontal () | Vertical ()) -> list<matrix> -> matrix,
     rowSlice is number -> number -> matrix -> matrix, 
     columnSlice is number -> number -> matrix -> matrix,
-    newMatrix is (ColumnMajor () | RowMajor ()) -> list<block> -> matrix, 
-    newRowVector is block -> matrix, 
-    newColumnVector is block -> matrix,
+    newMatrix is (ColumnMajor () | RowMajor ()) -> list<vector> -> matrix, 
+    newRowVector is vector -> matrix, 
+    newColumnVector is vector -> matrix,
 }
 
--- a/yetilab/matrix/matrixtype.yeti	Tue May 07 21:43:10 2013 +0100
+++ b/yetilab/matrix/matrixtype.yeti	Sat May 11 16:00:58 2013 +0100
@@ -1,17 +1,9 @@
 
 module yetilab.matrix.matrixtype;
 
-load yetilab.block.blocktype;
+load yetilab.vector.vectortype;
 
-typedef matrix = {
-    data is RowM array<~double[]> | ColM array<~double[]>,
-    size is { rows is number, columns is number },
-    getColumn is number -> block,
-    getRow is number -> block,
-    getAt is number -> number -> number,
-    setAt is number -> number -> number -> (),
-    isRowMajor? is boolean
-};
+typedef opaque matrix = RowM. array<vector> | ColM. array<vector>;
 
 ();
 
--- a/yetilab/matrix/test/test_matrix.yeti	Tue May 07 21:43:10 2013 +0100
+++ b/yetilab/matrix/test/test_matrix.yeti	Sat May 11 16:00:58 2013 +0100
@@ -2,7 +2,10 @@
 module yetilab.matrix.test.test_matrix;
 
 mat = load yetilab.matrix.matrix;
-block = load yetilab.block.block;
+vec = load yetilab.vector.vector;
+
+load yetilab.vector.vectortype;
+load yetilab.matrix.matrixtype;
 
 import yeti.lang: FailureException;
 
@@ -16,74 +19,74 @@
     randomMatrix s = flipper (mat.randomMatrix s);
     identityMatrix s = flipper (mat.identityMatrix s);
     generate f s = flipper (mat.generate f s);
-    newMatrix t d = flipper (mat.newMatrix t (map block.fromList d));
+    newMatrix t d = flipper (mat.newMatrix t (map vec.fromList d));
 [
 
 "constMatrixEmpty-\(name)": \(
     m = constMatrix 2 { rows = 0, columns = 0 };
-    compare m.size { columns = 0, rows = 0 }
+    compare (mat.size m) { columns = 0, rows = 0 }
 ),
 
 "constMatrixEmpty2-\(name)": \(
-    compare (constMatrix 2 { rows = 0, columns = 4 }).size { columns = 0, rows = 0 } and
-        compare (constMatrix 2 { rows = 4, columns = 0 }).size { columns = 0, rows = 0 }
+    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 }
 ),
 
 "constMatrix-\(name)": \(
     m = constMatrix 2 { rows = 3, columns = 4 };
-    compare m.size { columns = 4, rows = 3 } and
-        all id (map do row: compare (block.list (m.getRow row)) [2,2,2,2] done [0..2]) and
-        all id (map do col: compare (block.list (m.getColumn col)) [2,2,2] done [0..3])
+    compare (mat.size m) { columns = 4, rows = 3 } and
+        all id (map do row: compare (vec.list (mat.getRow row m)) [2,2,2,2] done [0..2]) and
+        all id (map do col: compare (vec.list (mat.getColumn col m)) [2,2,2] done [0..3])
 ),
 
 "randomMatrixEmpty-\(name)": \(
     m = randomMatrix { rows = 0, columns = 0 };
-    compare m.size { columns = 0, rows = 0 }
+    compare (mat.size m) { columns = 0, rows = 0 }
 ),
 
 "randomMatrix-\(name)": \(
     m = randomMatrix { rows = 3, columns = 4 };
-    compare m.size { columns = 4, rows = 3 }
+    compare (mat.size m) { columns = 4, rows = 3 }
 ),
 
 "zeroMatrixEmpty-\(name)": \(
     m = zeroMatrix { rows = 0, columns = 0 };
-    compare m.size { columns = 0, rows = 0 }
+    compare (mat.size m) { columns = 0, rows = 0 }
 ),
 
 "zeroMatrix-\(name)": \(
     m = zeroMatrix { rows = 3, columns = 4 };
-    compare m.size { columns = 4, rows = 3 } and
-        all id (map do row: compare (block.list (m.getRow row)) [0,0,0,0] done [0..2]) and
-        all id (map do col: compare (block.list (m.getColumn col)) [0,0,0] done [0..3])
+    compare (mat.size m) { columns = 4, rows = 3 } and
+        all id (map do row: compare (vec.list (mat.getRow row m)) [0,0,0,0] done [0..2]) and
+        all id (map do col: compare (vec.list (mat.getColumn col m)) [0,0,0] done [0..3])
 ),
 
 "identityMatrixEmpty-\(name)": \(
     m = identityMatrix { rows = 0, columns = 0 };
-    compare m.size { columns = 0, rows = 0 }
+    compare (mat.size m) { columns = 0, rows = 0 }
 ),
 
 "identityMatrix-\(name)": \(
     m = identityMatrix { rows = 3, columns = 4 };
-    compare m.size { columns = 4, rows = 3 } and
-        all id (map do row: compare (block.list (m.getRow row)) [1,1,1,1] done [0..2]) and
-        all id (map do col: compare (block.list (m.getColumn col)) [1,1,1] done [0..3])
+    compare (mat.size m) { columns = 4, rows = 3 } and
+        all id (map do row: compare (vec.list (mat.getRow row m)) [1,1,1,1] done [0..2]) and
+        all id (map do col: compare (vec.list (mat.getColumn col m)) [1,1,1] done [0..3])
 ),
 
 "generateEmpty-\(name)": \(
     m = generate do row col: 0 done { rows = 0, columns = 0 };
-    compare m.size { columns = 0, rows = 0 }
+    compare (mat.size m) { columns = 0, rows = 0 }
 ),
 
 "generate-\(name)": \(
     m = generate do row col: row * 10 + col done { rows = 2, columns = 3 };
-    compare (block.list (m.getRow 0)) [0,1,2] and
-        compare (block.list (m.getRow 1)) [10,11,12]
+    compare (vec.list (mat.getRow 0 m)) [0,1,2] and
+        compare (vec.list (mat.getRow 1 m)) [10,11,12]
 ),
 
 "widthAndHeight-\(name)": \(
     m = constMatrix 2 { rows = 3, columns = 4 };
-    compare m.size { columns = mat.width m, rows = mat.height m }
+    compare (mat.size m) { columns = mat.width m, rows = mat.height m }
 ),
 
 "equal-\(name)": \(
@@ -104,17 +107,17 @@
     m = generate generator { rows = 2, columns = 3 };
     all id
        (map do row: all id
-           (map do col: m.getAt row col == generator row col done [0..2])
+           (map do col: mat.getAt row col m == generator row col done [0..2])
             done [0..1])
 ),
-
+/*!!!
 "setAt-\(name)": \(
     generator row col = row * 10 + col;
     m = generate generator { rows = 2, columns = 3 };
-    m.setAt 1 2 16;
-    compare (m.getAt 1 2) 16 and
-        compare (m.getAt 1 1) 11 and
-        compare (m.getAt 0 2) 2
+    mat.setAt 1 2 16 m;
+    compare (mat.getAt 1 2 m) 16 and
+        compare (mat.getAt 1 1 m) 11 and
+        compare (mat.getAt 0 2 m) 2
 ),
 
 "copyOfEqual-\(name)": \(
@@ -127,18 +130,18 @@
     m = constMatrix 2 { rows = 3, columns = 4 };
     m' = m;
     m'' = mat.copyOf m;
-    m.setAt 0 0 6;
+    mat.setAt 0 0 6 m;
     compareMatrices m' m and not mat.equal m m'';
 ),
-
+*/
 "transposedEmpty-\(name)": \(
-    compare (mat.transposed (constMatrix 2 { rows = 0, columns = 0 })).size { columns = 0, rows = 0 } and
-        compare (mat.transposed (constMatrix 2 { rows = 0, columns = 4 })).size { columns = 0, rows = 0 } and
-        compare (mat.transposed (constMatrix 2 { rows = 4, columns = 0 })).size { columns = 0, rows = 0 }
+    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 }
 ),
 
 "transposedSize-\(name)": \(
-    compare (mat.transposed (constMatrix 2 { rows = 3, columns = 4 })).size { columns = 3, rows = 4 }
+    compare (mat.size (mat.transposed (constMatrix 2 { rows = 3, columns = 4 }))) { columns = 3, rows = 4 }
 ),
 
 "transposed-\(name)": \(
@@ -148,7 +151,7 @@
     all id
        (map do row: all id
            // like getAt test, but with col/row flipped
-           (map do col: m'.getAt col row == generator row col done [0..2])
+           (map do col: mat.getAt col row m' == generator row col done [0..2])
             done [0..1])
 ),
 
@@ -270,14 +273,14 @@
 
 "asRows-\(name)": \(
     compare
-       (map block.list
+       (map vec.list
            (mat.asRows (newMatrix (ColumnMajor ()) [[1,4],[2,5],[3,6]])))
         [[1,2,3],[4,5,6]];
 ),
 
 "asColumns-\(name)": \(
     compare
-       (map block.list
+       (map vec.list
            (mat.asColumns (newMatrix (ColumnMajor ()) [[1,4],[2,5],[3,6]])))
         [[1,4],[2,5],[3,6]];
 ),
--- a/yetilab/stream/audiofile.yeti	Tue May 07 21:43:10 2013 +0100
+++ b/yetilab/stream/audiofile.yeti	Sat May 11 16:00:58 2013 +0100
@@ -12,7 +12,7 @@
 import java.nio: ByteBuffer, ByteOrder;
 
 ch = load yetilab.stream.channels;
-block = load yetilab.block.block;
+vec = load yetilab.vector.vector;
 
 decode8u bytes doubles n is ~byte[] -> ~double[] -> number -> () =
    (for [0..n-1] do i:
@@ -61,12 +61,12 @@
     bytesPerSample = format#getSampleSizeInBits() / 8;
     bytes = new byte[nframes * channels * bytesPerSample];
     bytesRead = aistream#read(bytes);
-    if bytesRead <= 0 then block.zeros 0;
+    if bytesRead <= 0 then vec.zeros 0;
     else
         n = int(bytesRead / bytesPerSample);
         doubles = new double[n];
         decode { format } bytes doubles n;
-        block.block doubles;
+        vec.vector doubles;
     fi;
    );
 
--- a/yetilab/stream/channels.yeti	Tue May 07 21:43:10 2013 +0100
+++ b/yetilab/stream/channels.yeti	Sat May 11 16:00:58 2013 +0100
@@ -1,62 +1,70 @@
 
 module yetilab.stream.channels;
 
-vec = load yetilab.block.fvector;
-block = load yetilab.block.block;
+vec = load yetilab.vector.vector;
 mat = load yetilab.matrix.matrix;
+
+load yetilab.vector.vectortype;
+
+//!!! "internal" vector function to retrieve data for read-only
+// purposes without copying
+//!!! need to have this in some internal-use module 
+raw =
+   (raw' v is ~double[] -> ~double[] = v;
+    raw' as vector -> ~double[]);
         
 interleaved m = 
-   ({ columns, rows } = m.size;
+   ({ columns, rows } = (mat.size m);
     if rows == 1 then
-        m.getRow 0
+        mat.getRow 0 m
     else
-        v = vec.zeros (columns * rows);
+        v = new double[columns * rows];
         for [0..rows-1] do row:
             for [0..columns-1] do col:
-                v[col * rows + row] := m.getAt row col;
+                v[col * rows + row] := mat.getAt row col m;
             done;
         done;
-        block.block v;
+        vec.vector v;
     fi);
 
 deinterleaved channels b =
     if channels == 1 then
         mat.newRowVector b
     else
-        rows = (block.length b) / channels;
-        vv = array (map \(vec.zeros rows) [0..channels-1]);
-        v = block.data b;
+        rows = (vec.length b) / channels;
+        vv = array (map \(new double[rows]) [0..channels-1]);
+        v = raw b;
         for [0..rows-1] do row:
             for [0..channels-1] do col:
                 vv[col][row] := v[channels * row + col];
             done
         done;
-        mat.newMatrix (RowMajor ()) (map block.block vv);
+        mat.newMatrix (RowMajor ()) (map vec.vector vv);
     fi;
 
 mixedDown m =  //!!! sum or average? at the moment we sum
-   ({ columns, rows } = m.size;
-    v = vec.zeros columns;
+   ({ columns, rows } = (mat.size m);
+    v = new double[columns];
     for [0..rows-1] do row:
         for [0..columns-1] do col:
-            v[col] := v[col] + m.getAt row col;
+            v[col] := v[col] + mat.getAt row col m;
         done;
     done;
-    block.block v);
+    vec.vector v);
 
 mixedDownFromInterleaved channels b =
     if channels == 1 then
         b;
     else
-        v = block.data b;
-        columns = ((vec.length v) / channels);
-        v' = vec.zeros columns;
+        columns = ((vec.length b) / channels);
+        v = raw b;
+        v' = new double[columns];
         for [0..channels-1] do row:
             for [0..columns-1] do col:
                 v'[col] := v'[col] + v[col * channels + row];
             done;
         done;
-        block.block v';
+        vec.vector v';
     fi;
 
 mixedFromInterleavedTo targetChannels channels b = 
@@ -65,9 +73,9 @@
     elif targetChannels == 1 then
         mixedDownFromInterleaved channels b;
     else
-        v = block.data b;
-        columns = ((vec.length v) / channels);
-        v' = vec.zeros (columns * targetChannels);
+        columns = ((vec.length b) / channels);
+        v = raw b;
+        v' = new double[columns * targetChannels];
         for [0..targetChannels-1] do target:
             for [0..columns-1] do col:
                 if target < channels then
@@ -77,18 +85,18 @@
                 fi
             done
         done;
-        block.block v';
+        vec.vector v';
     fi;
 
 mixedTo targetChannels m = 
-    if targetChannels == m.size.rows then    // n -> n: pass unmodified
+    if targetChannels == mat.height m then   // n -> n: pass unmodified
         m
     elif targetChannels == 1 then            // n -> 1: mix down
         deinterleaved 1 (mixedDown m)
-    elif m.size.rows == 1 then               // 1 -> n: copy to all channels
-        mat.newMatrix (RowMajor ()) (map \(m.getRow 0) [1..targetChannels])
+    elif mat.height m == 1 then              // 1 -> n: copy to all channels
+        mat.newMatrix (RowMajor ()) (map \(mat.getRow 0 m) [1..targetChannels])
     else                                     // n -> m: truncate or add zeros
-        mat.resizedTo { rows = targetChannels, columns = m.size.columns } m
+        mat.resizedTo { rows = targetChannels, columns = mat.width m } m
     fi;
 
 mixedAndInterleavedTo targetChannels m = 
--- a/yetilab/stream/filter.yeti	Tue May 07 21:43:10 2013 +0100
+++ b/yetilab/stream/filter.yeti	Sat May 11 16:00:58 2013 +0100
@@ -2,7 +2,6 @@
 module yetilab.stream.filter;
 
 mat = load yetilab.matrix.matrix;
-bl = load yetilab.block.block;
 ch = load yetilab.stream.channels;
 
 load yetilab.stream.streamtype;
@@ -88,8 +87,8 @@
 
 mixed streams =
    (mix m1 m2 =
-       (sz = { rows = max m1.size.rows m2.size.rows,
-               columns = min m1.size.columns m2.size.columns };
+       (sz = { rows = max (mat.height m1) (mat.height m2),
+               columns = min (mat.width m1) (mat.width m2) };
         if sz.columns == 0 then
             mat.zeroSizeMatrix ()
         else
@@ -132,9 +131,9 @@
         get finished? () = any id (map (.finished?) streams),
         read count =
            (outs = map do s: s.read count done streams;
-            minlen = head (sort (map do m: m.size.columns done outs));
+            minlen = head (sort (map mat.width outs));
             outs = map do m:
-                mat.resizedTo { rows = m.size.rows, columns = minlen } m
+                mat.resizedTo { rows = mat.height m, columns = minlen } m
                 done outs;
             mat.concat (Vertical ()) outs
             ),
@@ -154,8 +153,8 @@
         var cache = mat.zeroSizeMatrix ();
         chunks = array [];
         cachedPartsFor count =
-           (start = pos % cache.size.columns;
-            avail = cache.size.columns - start;
+           (start = pos % (mat.width cache);
+            avail = (mat.width cache) - start;
             if avail >= count then
                 pos := pos + count;
                 [mat.columnSlice start count cache]
@@ -165,11 +164,11 @@
                     cachedPartsFor (count - avail);
             fi);
         readFromCache count =
-           (if cache.size.columns == 0 then
+           (if (mat.width cache) == 0 then
                 cache := mat.concat (Horizontal ()) (list chunks);
                 clearArray chunks;
             fi;
-            if cache.size.columns == 0 then
+            if (mat.width cache) == 0 then
                 cache
             else
                 mat.concat (Horizontal ()) (cachedPartsFor count);
@@ -184,7 +183,7 @@
                     readFromCache count
                 else
                     part = s.read count;
-                    len = part.size.columns;
+                    len = (mat.width part);
                     push chunks part;
                     pos := pos + len;
                     if len == count then part
--- a/yetilab/stream/framer.yeti	Tue May 07 21:43:10 2013 +0100
+++ b/yetilab/stream/framer.yeti	Sat May 11 16:00:58 2013 +0100
@@ -6,8 +6,8 @@
  * overlapping) frames of data.
  */
 
-block = load yetilab.block.block;
-bf = load yetilab.block.blockfuncs;
+vec = load yetilab.vector.vector;
+bf = load yetilab.vector.blockfuncs;
 af = load yetilab.stream.audiofile;
 win = load yetilab.transform.window;
 fft = load yetilab.transform.fft;
@@ -33,9 +33,9 @@
     // (zero-padded if necessary) just read
     buffer = map2
         do buf row:
-            block.concat
-               [block.rangeOf hop (size-hop) buf,
-                block.resizedTo hop (m.getRow row)];
+            vec.concat
+               [vec.rangeOf hop (size-hop) buf,
+                vec.resizedTo hop (mat.getRow row m)];
         done buffer [0..stream.channels-1];
 
     // Number of "valid" elements (not tail-end zero-padding) left in buffer
@@ -54,7 +54,7 @@
         blockList framesize stream
     else
         overlappingBlockList framesize hop stream 
-            framesize (map \(block.zeros framesize) [0..stream.channels-1]);
+            framesize (map \(vec.zeros framesize) [0..stream.channels-1]);
     fi;
 
 monoFrames params stream =
--- a/yetilab/stream/playback.yeti	Tue May 07 21:43:10 2013 +0100
+++ b/yetilab/stream/playback.yeti	Sat May 11 16:00:58 2013 +0100
@@ -1,8 +1,7 @@
 
 module yetilab.stream.playback;
 
-block = load yetilab.block.block;
-fr = load yetilab.stream.framer;
+vec = load yetilab.vector.vector;
 af = load yetilab.stream.audiofile;
 ch = load yetilab.stream.channels;
 
@@ -12,16 +11,15 @@
 import java.nio: ByteBuffer, ByteOrder;
 
 playBlock line b is ~SourceDataLine -> 'a -> () =
-   (len = block.length b;
-    samples = block.data b;
+   (len = vec.length b;
+    samples = vec.primitive b;
     nb = len * 2;
     bytes = new byte[nb];
     bb = ByteBuffer#wrap(bytes, 0, nb);
     bb#order(ByteOrder#LITTLE_ENDIAN);
     sb = bb#asShortBuffer();
     for [0..len-1] do i: sb#put(i, samples[i] * 32767.0); () done;
-    actual = line#write(bytes, 0, nb); 
-    ());
+    \() line#write(bytes, 0, nb));
 
 play line blocks = for blocks (playBlock line);
     
--- a/yetilab/stream/syntheticstream.yeti	Tue May 07 21:43:10 2013 +0100
+++ b/yetilab/stream/syntheticstream.yeti	Sat May 11 16:00:58 2013 +0100
@@ -2,10 +2,9 @@
 module yetilab.stream.syntheticstream;
 
 ch = load yetilab.stream.channels;
-vec = load yetilab.block.fvector;
-block = load yetilab.block.block;
+vec = load yetilab.vector.vector;
 
-load yetilab.block.blocktype;
+load yetilab.vector.vectortype;
 load yetilab.stream.streamtype;
 
 generated sampleRate generator =
@@ -18,12 +17,12 @@
         get available () = Infinite (),
         get finished? () = false,
         read count = ch.deinterleaved 1
-           (result = vec.zeros count;
+           (result = new double[count];
             for [0..count-1] do i:
                 result[i] := generator (position + i)
             done;
             position := position + count;
-            block.block result),
+            vec.vector result),
         close = \(),
     });
 
@@ -37,7 +36,7 @@
     generated rate \0;
 
 precalculated rate data =
-   (n = block.length data;
+   (n = vec.length data;
     var position = 0;
     {
         get position () = position,
@@ -47,7 +46,7 @@
         get finished? () = not (n > position),
         read count = ch.deinterleaved 1
            (rc = min count (n - position);
-            result = block.rangeOf position rc data;
+            result = vec.rangeOf position rc data;
             position := position + rc;
             result),
         close = \(),
@@ -55,7 +54,7 @@
 
 {
     generated is number -> (number -> number) -> stream, 
-    precalculated is number -> block -> stream,
+    precalculated is number -> vector -> stream,
     sinusoid is number -> number -> stream, 
     whiteNoise is number -> stream,
     silent is number -> stream,
--- a/yetilab/stream/test/audiofile_reference.yeti	Tue May 07 21:43:10 2013 +0100
+++ b/yetilab/stream/test/audiofile_reference.yeti	Sat May 11 16:00:58 2013 +0100
@@ -3,8 +3,7 @@
 
 syn = load yetilab.stream.syntheticstream;
 filt = load yetilab.stream.filter;
-vec = load yetilab.block.fvector;
-block = load yetilab.block.block;
+vec = load yetilab.vector.vector;
 
 pulseChannel rate =
    (pulseFreq = 2;
--- a/yetilab/stream/test/test_audiofile.yeti	Tue May 07 21:43:10 2013 +0100
+++ b/yetilab/stream/test/test_audiofile.yeti	Sat May 11 16:00:58 2013 +0100
@@ -2,7 +2,8 @@
 module yetilab.stream.test.test_audiofile;
 
 af = load yetilab.stream.audiofile;
-bl = load yetilab.block.block;
+vec = load yetilab.vector.vector;
+mat = load yetilab.matrix.matrix;
 
 { compare } = load yetilab.test.test;
 
@@ -31,11 +32,11 @@
         f = opener (testfile "20samples");
         first15 = f.read 15;
         last5 = f.read 10;
-        compare first15.size { rows = 1, columns = 15 } and
-            compare last5.size { rows = 1, columns = 5 } and
-            compare (bl.list (first15.getRow 0))
+        compare (mat.size first15) { rows = 1, columns = 15 } and
+            compare (mat.size last5) { rows = 1, columns = 5 } and
+            compare (vec.list (mat.getRow 0 first15))
                 [ float (32767/32768),0,0,0,0,0,0,0,0,0,0,0,0,0,0 ] and
-            compare (bl.list (last5.getRow 0)) [ 0,0,0,0,-1 ] and
+            compare (vec.list (mat.getRow 0 last5)) [ 0,0,0,0,-1 ] and
             ( f.close () ; true )
         done [ af.open, af.openMono ]);
 ),
--- a/yetilab/stream/test/test_channels.yeti	Tue May 07 21:43:10 2013 +0100
+++ b/yetilab/stream/test/test_channels.yeti	Sat May 11 16:00:58 2013 +0100
@@ -3,73 +3,73 @@
 
 ch = load yetilab.stream.channels;
 mat = load yetilab.matrix.matrix;
-bl = load yetilab.block.block;
+vec = load yetilab.vector.vector;
 
 { compare, compareUsing } = load yetilab.test.test;
 
-newMatrix data = mat.newMatrix (ColumnMajor ()) (map bl.fromList data);
+newMatrix data = mat.newMatrix (ColumnMajor ()) (map vec.fromList data);
 
 compareBlocks b1 b2 =
-    compare (bl.list b1) (bl.list b2);
+    compare (vec.list b1) (vec.list b2);
 
 [
 
 "interleaved": \(
     compareBlocks (ch.interleaved (newMatrix [[1,4],[2,5],[3,6]]))
-       (bl.fromList [1,4,2,5,3,6]) and
+       (vec.fromList [1,4,2,5,3,6]) and
         compareBlocks (ch.interleaved (newMatrix [[1],[2],[3]]))
-           (bl.fromList [1,2,3])
+           (vec.fromList [1,2,3])
 ),
 
 "deinterleaved": \(
-    compareUsing mat.equal (ch.deinterleaved 2 (bl.fromList [1,4,2,5,3,6]))
+    compareUsing mat.equal (ch.deinterleaved 2 (vec.fromList [1,4,2,5,3,6]))
        (newMatrix [[1,4],[2,5],[3,6]]) and
-        compareUsing mat.equal (ch.deinterleaved 1 (bl.fromList [1,2,3]))
+        compareUsing mat.equal (ch.deinterleaved 1 (vec.fromList [1,2,3]))
            (newMatrix [[1],[2],[3]])
 ),
 
 "mixedDown": \(
     compareBlocks (ch.mixedDown (newMatrix [[1,4],[2,5],[3,6]]))
-       (bl.fromList [5,7,9]) and
+       (vec.fromList [5,7,9]) and
         compareBlocks (ch.mixedDown (newMatrix []))
-           (bl.fromList [])
+           (vec.fromList [])
 ),
 
 "mixedDownFromInterleaved": \(
-    compareBlocks (ch.mixedDownFromInterleaved 2 (bl.fromList [1,4,2,5,3,6]))
-       (bl.fromList [5,7,9]) and
-        compareBlocks (ch.mixedDownFromInterleaved 1 (bl.fromList [1,2,3]))
-           (bl.fromList [1,2,3])
+    compareBlocks (ch.mixedDownFromInterleaved 2 (vec.fromList [1,4,2,5,3,6]))
+       (vec.fromList [5,7,9]) and
+        compareBlocks (ch.mixedDownFromInterleaved 1 (vec.fromList [1,2,3]))
+           (vec.fromList [1,2,3])
 ),
 
 "mixedFromInterleavedTo": \(
-    compareBlocks (ch.mixedFromInterleavedTo 1 2 (bl.fromList [1,4,2,5,3,6]))
-       (bl.fromList [5,7,9]) and
-        compareBlocks (ch.mixedFromInterleavedTo 2 2 (bl.fromList [1,4,2,5,3,6]))
-           (bl.fromList [1,4,2,5,3,6]) and
-        compareBlocks (ch.mixedFromInterleavedTo 3 2 (bl.fromList [1,4,2,5,3,6]))
-           (bl.fromList [1,4,0,2,5,0,3,6,0]) and
-        compareBlocks (ch.mixedFromInterleavedTo 1 1 (bl.fromList [1,2,3]))
-           (bl.fromList [1,2,3]) and
-        compareBlocks (ch.mixedFromInterleavedTo 2 1 (bl.fromList [1,2,3]))
-           (bl.fromList [1,1,2,2,3,3]) and
-        compareBlocks (ch.mixedFromInterleavedTo 3 1 (bl.fromList [1,2,3]))
-           (bl.fromList [1,1,0,2,2,0,3,3,0])
+    compareBlocks (ch.mixedFromInterleavedTo 1 2 (vec.fromList [1,4,2,5,3,6]))
+       (vec.fromList [5,7,9]) and
+        compareBlocks (ch.mixedFromInterleavedTo 2 2 (vec.fromList [1,4,2,5,3,6]))
+           (vec.fromList [1,4,2,5,3,6]) and
+        compareBlocks (ch.mixedFromInterleavedTo 3 2 (vec.fromList [1,4,2,5,3,6]))
+           (vec.fromList [1,4,0,2,5,0,3,6,0]) and
+        compareBlocks (ch.mixedFromInterleavedTo 1 1 (vec.fromList [1,2,3]))
+           (vec.fromList [1,2,3]) and
+        compareBlocks (ch.mixedFromInterleavedTo 2 1 (vec.fromList [1,2,3]))
+           (vec.fromList [1,1,2,2,3,3]) and
+        compareBlocks (ch.mixedFromInterleavedTo 3 1 (vec.fromList [1,2,3]))
+           (vec.fromList [1,1,0,2,2,0,3,3,0])
 ),
 
 "mixedAndInterleavedTo": \(
     compareBlocks (ch.mixedAndInterleavedTo 1 (newMatrix [[1,4],[2,5],[3,6]]))
-       (bl.fromList [5,7,9]) and
+       (vec.fromList [5,7,9]) and
         compareBlocks (ch.mixedAndInterleavedTo 2 (newMatrix [[1,4],[2,5],[3,6]]))
-           (bl.fromList [1,4,2,5,3,6]) and
+           (vec.fromList [1,4,2,5,3,6]) and
         compareBlocks (ch.mixedAndInterleavedTo 3 (newMatrix [[1,4],[2,5],[3,6]]))
-           (bl.fromList [1,4,0,2,5,0,3,6,0]) and
+           (vec.fromList [1,4,0,2,5,0,3,6,0]) and
         compareBlocks (ch.mixedAndInterleavedTo 1 (newMatrix [[1],[2],[3]]))
-           (bl.fromList [1,2,3]) and
+           (vec.fromList [1,2,3]) and
         compareBlocks (ch.mixedAndInterleavedTo 2 (newMatrix [[1],[2],[3]]))
-           (bl.fromList [1,1,2,2,3,3]) and
+           (vec.fromList [1,1,2,2,3,3]) and
         compareBlocks (ch.mixedAndInterleavedTo 3 (newMatrix [[1],[2],[3]]))
-           (bl.fromList [1,1,1,2,2,2,3,3,3])
+           (vec.fromList [1,1,1,2,2,2,3,3,3])
 ),
 
 ] is hash<string, () -> boolean>;
--- a/yetilab/stream/test/test_filter.yeti	Tue May 07 21:43:10 2013 +0100
+++ b/yetilab/stream/test/test_filter.yeti	Sat May 11 16:00:58 2013 +0100
@@ -1,7 +1,7 @@
 
 module yetilab.stream.test.test_filter;
 
-bl = load yetilab.block.block;
+vec = load yetilab.vector.vector;
 mat = load yetilab.matrix.matrix;
 syn = load yetilab.stream.syntheticstream;
 filt = load yetilab.stream.filter;
@@ -41,7 +41,7 @@
         compare str.sampleRate 2 and
         compare str.available (Known 3) and
         compare str.finished? false and
-        compare (bl.list ((str.read 4).getRow 0)) [ 0,1,2 ] and
+        compare (vec.list (mat.getRow 0 (str.read 4))) [ 0,1,2 ] and
         compare str.position 3 and
         compare str.available (Known 0) and
         compare str.finished? true and
@@ -52,11 +52,11 @@
     // as above
     str = filt.withDuration 3 (syn.generated 2 id);
     compare str.position 0 and
-        compare (bl.list ((str.read 2).getRow 0)) [ 0,1 ] and
+        compare (vec.list (mat.getRow 0 (str.read 2))) [ 0,1 ] and
         compare str.position 2 and
         compare str.available (Known 1) and
         compare str.finished? false and
-        compare (bl.list ((str.read 2).getRow 0)) [ 2 ] and
+        compare (vec.list (mat.getRow 0 (str.read 2))) [ 2 ] and
         compare str.position 3 and
         compare str.available (Known 0) and
         compare str.finished? true and
@@ -74,11 +74,11 @@
         compare str.sampleRate 2 and
         compare str.available (Known 5) and
         compare str.finished? false and
-        compare (bl.list ((str.read 4).getRow 0)) [ 0,1,2,0 ] and
+        compare (vec.list (mat.getRow 0 (str.read 4))) [ 0,1,2,0 ] and
         compare str.position 4 and
         compare str.available (Known 1) and
         compare str.finished? false and
-        compare (bl.list ((str.read 2).getRow 0)) [ 0 ] and
+        compare (vec.list (mat.getRow 0 (str.read 2))) [ 0 ] and
         compare str.position 5 and
         compare str.available (Known 0) and
         compare str.finished? true and
@@ -92,7 +92,7 @@
         compare str.sampleRate 2 and
         compare str.available (maybeKnown 3) and
         compare str.finished? false and
-        compare (bl.list ((str.read 4).getRow 0)) [ 0,1,2 ] and
+        compare (vec.list (mat.getRow 0 (str.read 4))) [ 0,1,2 ] and
         compare str.position 3 and
         compare str.available (Known 0) and
         compare str.finished? true and
@@ -106,7 +106,7 @@
         compare str.sampleRate 2 and
         compare str.available (Infinite ()) and
         compare str.finished? false and
-        compare (bl.list ((str.read 4).getRow 0)) [ 0,1,2,3 ] and
+        compare (vec.list (mat.getRow 0 (str.read 4))) [ 0,1,2,3 ] and
         compare str.position 4 and
         compare str.available (Infinite ()) and
         compare str.finished? false and
@@ -120,11 +120,11 @@
         compare str.sampleRate 2 and
         compare str.available (maybeKnown 5) and
         compare str.finished? false and
-        compare (bl.list ((str.read 4).getRow 0)) [ 0,0,0,1 ] and
+        compare (vec.list (mat.getRow 0 (str.read 4))) [ 0,0,0,1 ] and
         compare str.position 4 and
         compare str.available (maybeKnown 1) and
         compare str.finished? false and
-        compare (bl.list ((str.read 4).getRow 0)) [ 2 ] and
+        compare (vec.list (mat.getRow 0 (str.read 4))) [ 2 ] and
         compare str.position 5 and
         compare str.available (Known 0) and
         compare str.finished? true and
@@ -138,11 +138,11 @@
         compare str.sampleRate 2 and
         compare str.available (maybeKnown 5) and
         compare str.finished? false and
-        compare (bl.list ((str.read 1).getRow 0)) [ 0 ] and
+        compare (vec.list (mat.getRow 0 (str.read 1))) [ 0 ] and
         compare str.position 1 and
         compare str.available (maybeKnown 4) and
         compare str.finished? false and
-        compare (bl.list ((str.read 4).getRow 0)) [ 0,0,1,2 ] and
+        compare (vec.list (mat.getRow 0 (str.read 4))) [ 0,0,1,2 ] and
         compare str.position 5 and
         compare str.available (Known 0) and
         compare str.finished? true and
@@ -156,7 +156,7 @@
         compare str.sampleRate 2 and
         compare str.available (maybeKnown 5) and
         compare str.finished? false and
-        compare (bl.list ((str.read 7).getRow 0)) [ 0,0,0,1,2 ] and
+        compare (vec.list (mat.getRow 0 (str.read 7))) [ 0,0,0,1,2 ] and
         compare str.position 5 and
         compare str.available (Known 0) and
         compare str.finished? true and
@@ -170,13 +170,13 @@
         compare str.sampleRate 2 and
         compare str.available (Infinite ()) and
         compare str.finished? false and
-        compare (bl.list ((str.read 2).getRow 0)) [ 0,0 ] and
+        compare (vec.list (mat.getRow 0 (str.read 2))) [ 0,0 ] and
         compare str.position 2 and
         compare str.finished? false and
-        compare (bl.list ((str.read 2).getRow 0)) [ 0,1 ] and
+        compare (vec.list (mat.getRow 0 (str.read 2))) [ 0,1 ] and
         compare str.position 4 and
         compare str.finished? false and
-        compare (bl.list ((str.read 2).getRow 0)) [ 2,3 ] and
+        compare (vec.list (mat.getRow 0 (str.read 2))) [ 2,3 ] and
         compare str.position 6 and
         compare str.finished? false and
         ( str.close (); true )
@@ -189,7 +189,7 @@
         compare str.sampleRate 2 and
         compare str.available (maybeKnown 3) and
         compare str.finished? false and
-        compare (map bl.list (mat.asRows (str.read 4))) [[0,1,2],[0,1,2]] and
+        compare (map vec.list (mat.asRows (str.read 4))) [[0,1,2],[0,1,2]] and
         compare str.position 3 and
         compare str.available (Known 0) and
         compare str.finished? true and
@@ -206,7 +206,7 @@
         compare str.sampleRate 2 and
         compare str.available (maybeKnown 3) and
         compare str.finished? false and
-        compare (map bl.list (mat.asRows (str.read 4))) [[0,2,4]] and
+        compare (map vec.list (mat.asRows (str.read 4))) [[0,2,4]] and
         compare str.position 3 and
         compare str.available (Known 0) and
         compare str.finished? true and
@@ -223,7 +223,7 @@
         compare str.sampleRate 2 and
         compare str.available (maybeKnown 3) and
         compare str.finished? false and
-        compare (map bl.list (mat.asRows (str.read 4))) [[0,1,2],[1,2,3],[0,0,0]] and
+        compare (map vec.list (mat.asRows (str.read 4))) [[0,1,2],[1,2,3],[0,0,0]] and
         compare str.position 3 and
         compare str.available (Known 0) and
         compare str.finished? true and
@@ -237,7 +237,7 @@
         compare str.sampleRate 2 and
         compare str.available (maybeKnown 3) and
         compare str.finished? false and
-        compare (map bl.list (mat.asRows (str.read 4))) [[0,1,2],[0,1,2],[0,1,2]] and
+        compare (map vec.list (mat.asRows (str.read 4))) [[0,1,2],[0,1,2],[0,1,2]] and
         compare str.position 3 and
         compare str.available (Known 0) and
         compare str.finished? true and
@@ -251,7 +251,7 @@
         compare str.sampleRate 2 and
         compare str.available (Infinite ()) and
         compare str.finished? false and
-        compare (map bl.list (mat.asRows (str.read 4))) [[0,1,2,3]] and
+        compare (map vec.list (mat.asRows (str.read 4))) [[0,1,2,3]] and
         compare str.available (Infinite ()) and
         compare str.position 4 and
         ( str.close (); true )
@@ -264,7 +264,7 @@
         compare str.sampleRate 2 and
         compare str.available (maybeKnown 3) and
         compare str.finished? false and
-        compare (map bl.list (mat.asRows (str.read 4))) [[0,1,2]] and
+        compare (map vec.list (mat.asRows (str.read 4))) [[0,1,2]] and
         compare str.available (Known 0) and
         compare str.finished? true and
         compare str.position 3 and
@@ -273,14 +273,14 @@
 
 "mixed-precalc-trunc-\(name)": \(
     str = filt.mixed
-       [syn.precalculated 2 (bl.fromList [1,2]),
+       [syn.precalculated 2 (vec.fromList [1,2]),
         withDuration 3 (syn.generated 2 (0-))];
     compare str.position 0 and
         compare str.channels 1 and
         compare str.sampleRate 2 and
         compare str.available (maybeKnown 2) and
         compare str.finished? false and
-        compare (map bl.list (mat.asRows (str.read 4))) [[1,1]] and
+        compare (map vec.list (mat.asRows (str.read 4))) [[1,1]] and
         compare str.available (Known 0) and
         compare str.finished? true and
         compare str.position 2 and
@@ -289,15 +289,15 @@
 
 "mixed-2-1-\(name)": \(
     str = filt.mixed
-       [syn.precalculated 2 (bl.fromList [1,2]),
-        filt.multiplexed [syn.precalculated 2 (bl.fromList [3,4]),
+       [syn.precalculated 2 (vec.fromList [1,2]),
+        filt.multiplexed [syn.precalculated 2 (vec.fromList [3,4]),
                           withDuration 3 (syn.generated 2 (0-))]];
     compare str.position 0 and
         compare str.channels 2 and
         compare str.sampleRate 2 and
         compare str.available (maybeKnown 2) and
         compare str.finished? false and
-        compare (map bl.list (mat.asRows (str.read 4))) [[4,6], [0,-1]] and
+        compare (map vec.list (mat.asRows (str.read 4))) [[4,6], [0,-1]] and
         compare str.available (Known 0) and
         compare str.finished? true and
         compare str.position 2 and
@@ -306,15 +306,15 @@
 
 "mixed-3-\(name)": \(
     str = filt.mixed
-       [syn.precalculated 2 (bl.fromList [1,2]),
-        syn.precalculated 2 (bl.fromList [3,4]),
+       [syn.precalculated 2 (vec.fromList [1,2]),
+        syn.precalculated 2 (vec.fromList [3,4]),
         withDuration 3 (syn.generated 2 (0-))];
     compare str.position 0 and
         compare str.channels 1 and
         compare str.sampleRate 2 and
         compare str.available (maybeKnown 2) and
         compare str.finished? false and
-        compare (map bl.list (mat.asRows (str.read 4))) [[4,5]] and
+        compare (map vec.list (mat.asRows (str.read 4))) [[4,5]] and
         compare str.available (Known 0) and
         compare str.finished? true and
         compare str.position 2 and
@@ -328,7 +328,7 @@
         compare str.sampleRate 2 and
         compare str.available (Infinite ()) and
         compare str.finished? false and
-        compare (map bl.list (mat.asRows (str.read 4)))
+        compare (map vec.list (mat.asRows (str.read 4)))
             [[0,1,2,3], [0,-1,-2,-3]] and
         compare str.available (Infinite ()) and
         compare str.position 4 and
@@ -342,7 +342,7 @@
         compare str.sampleRate 2 and
         compare str.available (maybeKnown 3) and
         compare str.finished? false and
-        compare (map bl.list (mat.asRows (str.read 4))) [[0,1,2], [0,-1,-2]] and
+        compare (map vec.list (mat.asRows (str.read 4))) [[0,1,2], [0,-1,-2]] and
         compare str.available (Known 0) and
         compare str.finished? true and
         compare str.position 3 and
@@ -351,14 +351,14 @@
 
 "multiplexed-precalc-trunc-\(name)": \(
     str = filt.multiplexed
-       [syn.precalculated 2 (bl.fromList [1,2]),
+       [syn.precalculated 2 (vec.fromList [1,2]),
         withDuration 3 (syn.generated 2 (0-))];
     compare str.position 0 and
         compare str.channels 2 and
         compare str.sampleRate 2 and
         compare str.available (maybeKnown 2) and
         compare str.finished? false and
-        compare (map bl.list (mat.asRows (str.read 4))) [[1,2], [0,-1]] and
+        compare (map vec.list (mat.asRows (str.read 4))) [[1,2], [0,-1]] and
         compare str.available (Known 0) and
         compare str.finished? true and
         compare str.position 2 and
@@ -367,15 +367,15 @@
 
 "multiplexed-2-1-\(name)": \(
     str = filt.multiplexed
-       [syn.precalculated 2 (bl.fromList [1,2]),
-        filt.multiplexed [syn.precalculated 2 (bl.fromList [3,4]),
+       [syn.precalculated 2 (vec.fromList [1,2]),
+        filt.multiplexed [syn.precalculated 2 (vec.fromList [3,4]),
                           withDuration 3 (syn.generated 2 (0-))]];
     compare str.position 0 and
         compare str.channels 3 and
         compare str.sampleRate 2 and
         compare str.available (maybeKnown 2) and
         compare str.finished? false and
-        compare (map bl.list (mat.asRows (str.read 4))) [[1,2], [3,4], [0,-1]] and
+        compare (map vec.list (mat.asRows (str.read 4))) [[1,2], [3,4], [0,-1]] and
         compare str.available (Known 0) and
         compare str.finished? true and
         compare str.position 2 and
@@ -384,15 +384,15 @@
 
 "multiplexed-2-1b-\(name)": \(
     str = filt.multiplexed
-       [syn.precalculated 2 (bl.fromList [1,2]),
-        syn.precalculated 2 (bl.fromList [3,4]),
+       [syn.precalculated 2 (vec.fromList [1,2]),
+        syn.precalculated 2 (vec.fromList [3,4]),
         withDuration 3 (syn.generated 2 (0-))];
     compare str.position 0 and
         compare str.channels 3 and
         compare str.sampleRate 2 and
         compare str.available (maybeKnown 2) and
         compare str.finished? false and
-        compare (map bl.list (mat.asRows (str.read 4))) [[1,2], [3,4], [0,-1]] and
+        compare (map vec.list (mat.asRows (str.read 4))) [[1,2], [3,4], [0,-1]] and
         compare str.available (Known 0) and
         compare str.finished? true and
         compare str.position 2 and
@@ -401,21 +401,21 @@
 
 "repeated-2-\(name)": \(
     str = filt.repeated
-       (syn.precalculated 2 (bl.fromList [1,2,3]));
+       (syn.precalculated 2 (vec.fromList [1,2,3]));
     compare str.position 0 and
         compare str.channels 1 and
         compare str.sampleRate 2 and
         compare str.available (Infinite ()) and
         compare str.finished? false and
-        compare (map bl.list (mat.asRows (str.read 1))) [[1]] and
+        compare (map vec.list (mat.asRows (str.read 1))) [[1]] and
         compare str.position 1 and
-        compare (map bl.list (mat.asRows (str.read 2))) [[2,3]] and
+        compare (map vec.list (mat.asRows (str.read 2))) [[2,3]] and
         compare str.position 3 and
-        compare (map bl.list (mat.asRows (str.read 3))) [[1,2,3]] and
+        compare (map vec.list (mat.asRows (str.read 3))) [[1,2,3]] and
         compare str.position 6 and
-        compare (map bl.list (mat.asRows (str.read 5))) [[1,2,3,1,2]] and
-        compare (map bl.list (mat.asRows (str.read 9))) [[3,1,2,3,1,2,3,1,2]] and
-        compare (map bl.list (mat.asRows (str.read 2))) [[3,1]] and
+        compare (map vec.list (mat.asRows (str.read 5))) [[1,2,3,1,2]] and
+        compare (map vec.list (mat.asRows (str.read 9))) [[3,1,2,3,1,2,3,1,2]] and
+        compare (map vec.list (mat.asRows (str.read 2))) [[3,1]] and
         compare str.available (Infinite ()) and
         compare str.finished? false and
         compare str.position 22 and
--- a/yetilab/stream/test/test_framer.yeti	Tue May 07 21:43:10 2013 +0100
+++ b/yetilab/stream/test/test_framer.yeti	Sat May 11 16:00:58 2013 +0100
@@ -2,17 +2,17 @@
 module yetilab.stream.test.test_framer;
 
 fr = load yetilab.stream.framer;
-block = load yetilab.block.block;
+vec = load yetilab.vector.vector;
 mat = load yetilab.matrix.matrix;
 syn = load yetilab.stream.syntheticstream;
 
 { compare, compareUsing } = load yetilab.test.test;
 
-testStream n is number -> 'a  = syn.precalculated 1000 (block.fromList [1..n]);
+testStream n is number -> 'a  = syn.precalculated 1000 (vec.fromList [1..n]);
 
 compareFrames frames1 frames2 =
     all id (map2 do f1 f2: compareUsing mat.equal f1 f2 done frames1
-       (map (mat.newRowVector . block.fromList) frames2));
+       (map (mat.newRowVector . vec.fromList) frames2));
 
 [
 
--- a/yetilab/stream/test/test_syntheticstream.yeti	Tue May 07 21:43:10 2013 +0100
+++ b/yetilab/stream/test/test_syntheticstream.yeti	Sat May 11 16:00:58 2013 +0100
@@ -1,7 +1,7 @@
 
 module yetilab.stream.test.test_syntheticstream;
 
-bl = load yetilab.block.block;
+vec = load yetilab.vector.vector;
 mat = load yetilab.matrix.matrix;
 syn = load yetilab.stream.syntheticstream;
 
@@ -21,7 +21,7 @@
         compare str.sampleRate 2 and
         compare str.available (Infinite ()) and
         compare str.finished? false and
-        compare (bl.list ((str.read 4).getRow 0)) [ 0,1,2,3 ] and
+        compare (vec.list (mat.getRow 0 (str.read 4))) [ 0,1,2,3 ] and
         compare str.position 4
 ),
 
@@ -33,7 +33,7 @@
         compare str.sampleRate 8 and
         compare str.available (Infinite ()) and
         compare str.finished? false and
-        compareApprox epsilon (bl.list ((str.read 6).getRow 0)) [ 0, 1, 0, -1, 0, 1 ] and
+        compareApprox epsilon (vec.list (mat.getRow 0 (str.read 6))) [ 0, 1, 0, -1, 0, 1 ] and
         compare str.position 6
 ),
 
@@ -44,33 +44,33 @@
         compare str.sampleRate 8 and
         compare str.available (Infinite ()) and
         compare str.finished? false and
-        compare (bl.list ((str.read 3).getRow 0)) [ 0, 0, 0 ] and
+        compare (vec.list (mat.getRow 0 (str.read 3))) [ 0, 0, 0 ] and
         compare str.position 3
 ),
 
 "precalculated-empty": \(
-    str = syn.precalculated 2 (bl.fromList []);
+    str = syn.precalculated 2 (vec.fromList []);
     compare str.position 0 and
         compare str.channels 1 and
         compare str.sampleRate 2 and
         compare str.available (Known 0) and
         compare str.finished? true and
-        compare (bl.list ((str.read 3).getRow 0)) [] and
+        compare (vec.list (mat.getRow 0 (str.read 3))) [] and
         compare str.position 0
 ),
 
 "precalculated": \(
-    str = syn.precalculated 2 (bl.fromList [ 1, 2, 3, 4 ]);
+    str = syn.precalculated 2 (vec.fromList [ 1, 2, 3, 4 ]);
     compare str.position 0 and
         compare str.channels 1 and
         compare str.sampleRate 2 and
         compare str.available (Known 4) and
         compare str.finished? false and
-        compare (bl.list ((str.read 3).getRow 0)) [ 1, 2, 3 ] and
+        compare (vec.list (mat.getRow 0 (str.read 3))) [ 1, 2, 3 ] and
         compare str.position 3 and
         compare str.available (Known 1) and
         compare str.finished? false and
-        compare (bl.list ((str.read 3).getRow 0)) [ 4 ] and
+        compare (vec.list (mat.getRow 0 (str.read 3))) [ 4 ] and
         compare str.position 4 and
         compare str.available (Known 0) and
         compare str.finished? true
--- a/yetilab/test/all.yeti	Tue May 07 21:43:10 2013 +0100
+++ b/yetilab/test/all.yeti	Sat May 11 16:00:58 2013 +0100
@@ -4,9 +4,9 @@
 { runTests } = load yetilab.test.test;
 
 tests = [
-"fvector"    : load yetilab.block.test.test_fvector,
-"blockfuncs" : load yetilab.block.test.test_blockfuncs,
-"complex"    : load yetilab.block.test.test_complex,
+"vector"     : load yetilab.vector.test.test_vector,
+"blockfuncs" : load yetilab.vector.test.test_blockfuncs,
+"complex"    : load yetilab.vector.test.test_complex,
 "framer"     : load yetilab.stream.test.test_framer,
 "channels"   : load yetilab.stream.test.test_channels,
 "audiofile"  : load yetilab.stream.test.test_audiofile,
--- a/yetilab/test/test.yeti	Tue May 07 21:43:10 2013 +0100
+++ b/yetilab/test/test.yeti	Sat May 11 16:00:58 2013 +0100
@@ -1,7 +1,5 @@
 module yetilab.test.test;
 
-block = load yetilab.block.block;
-
 import yeti.lang: FailureException;
 
 var goodCompares = 0;
--- a/yetilab/transform/fft.yeti	Tue May 07 21:43:10 2013 +0100
+++ b/yetilab/transform/fft.yeti	Sat May 11 16:00:58 2013 +0100
@@ -3,12 +3,13 @@
 
 import edu.emory.mathcs.jtransforms.fft: DoubleFFT_1D;
 
-b = load yetilab.block.block;
-vec = load yetilab.block.fvector;
-complex = load yetilab.block.complex;
+vec = load yetilab.vector.vector;
+complex = load yetilab.vector.complex;
 
-packedToComplex p =
-   (n = (vec.length p) / 2;
+load yetilab.vector.complextype;
+
+packedToComplex len p is number -> ~double[] -> array<cplx> =
+   (n = len / 2;
     array
        (map do i:
             re = if i == n then p[1] else p[i*2] fi;
@@ -18,24 +19,25 @@
 
 complexToPacked arr =
    (n = length arr;
-    v = vec.vector
-       (map do i:
-            ix = int (i/2);
+    v = new double[n*2-2];
+    for [0..(n-1)*2-1] do i:
+        ix = int (i/2);
+        v[i] :=
             if i == ix*2 then
                 complex.real arr[ix]
             else 
                 complex.imaginary arr[ix] 
             fi;
-            done [0..(n-1)*2-1]);
+    done;
     v[1] := complex.real arr[n-1];
     v);
 
 realForward n = 
    (d = new DoubleFFT_1D(n);
     do bl:
-        v = b.vector bl;
+        v = vec.primitive bl;
         d#realForward(v);
-        packedToComplex v;
+        packedToComplex (vec.length bl) v;
     done);
 
 realInverse n = 
@@ -43,7 +45,7 @@
     do arr:
         v = complexToPacked arr;
         d#realInverse(v, true);
-        b.block v;
+        vec.vector v;
     done);
 
 {
--- a/yetilab/transform/test/test_fft.yeti	Tue May 07 21:43:10 2013 +0100
+++ b/yetilab/transform/test/test_fft.yeti	Sat May 11 16:00:58 2013 +0100
@@ -2,15 +2,15 @@
 module yetilab.transform.test.test_fft;
 
 { realForward, realInverse } = load yetilab.transform.fft;
-{ list, fromList } = load yetilab.block.block;
-{ complex } = load yetilab.block.complex;
+{ list, fromList } = load yetilab.vector.vector;
+{ complex } = load yetilab.vector.complex;
 
 { compare } = load yetilab.test.test;
 
 testFFT orig reals imags =
    (out = realForward (length orig) (fromList orig);
     back = realInverse (length orig) out;
-    compare out (array (map2 complex reals imags)) and compare orig (list back));
+    compare out (array (map2 complex reals imags)) and compare (list back) orig);
 
 [
 
--- a/yetilab/transform/window.yeti	Tue May 07 21:43:10 2013 +0100
+++ b/yetilab/transform/window.yeti	Sat May 11 16:00:58 2013 +0100
@@ -1,11 +1,11 @@
 
 module yetilab.transform.window;
 
-b = load yetilab.block.block;
-bf = load yetilab.block.blockfuncs;
+vec = load yetilab.vector.vector;
+bf = load yetilab.vector.blockfuncs;
 
 cosinewin a0 a1 a2 a3 n =
-    b.fromList
+    vec.fromList
        (map do i:
             a0
             - a1 * cos(2 * pi * i / n)
@@ -18,10 +18,10 @@
 blackman = cosinewin 0.42 0.50 0.08 0.0;
 nuttall = cosinewin 0.3635819 0.4891775 0.1365995 0.0106411;
 blackmanHarris = cosinewin 0.35875 0.48829 0.14128 0.01168;
-boxcar = b.consts 0.5;
+boxcar = vec.consts 0.5;
 
 bartlett n =
-    b.fromList
+    vec.fromList
        (m = n/2;
         concat [
             map do i:
@@ -36,7 +36,7 @@
     case frames of
         []: frames;
          _: (first = head frames;
-             window = windowFunc (b.length first);
+             window = windowFunc (vec.length first);
              map (bf.multiply window) frames);
     esac;
 
--- a/yetilab/vamp/test/test_vamp.yeti	Tue May 07 21:43:10 2013 +0100
+++ b/yetilab/vamp/test/test_vamp.yeti	Sat May 11 16:00:58 2013 +0100
@@ -4,7 +4,7 @@
 synthetic = load yetilab.stream.syntheticstream;
 filter = load yetilab.stream.filter;
 mat = load yetilab.matrix.matrix;
-block = load yetilab.block.block;
+vec = load yetilab.vector.vector;
 
 { compare, compareUsing } = load yetilab.test.test;
 
@@ -92,7 +92,7 @@
         compareUsing mat.equal g 
            (mat.newMatrix (ColumnMajor ())
                (map do x:
-                   (block.fromList . floats) (map do y:
+                   (vec.fromList . floats) (map do y:
                         (x + y + 2) / 30
                         done [0..9])
                     done [0..19]));
@@ -106,7 +106,7 @@
         compareUsing mat.equal g 
            (mat.newMatrix (ColumnMajor ())
                (map do x:
-                   (block.fromList . floats) (map do y:
+                   (vec.fromList . floats) (map do y:
                         (x + y + 2) / 20
                         done [0..9])
                     done [0..9]));
--- a/yetilab/vamp/vamp.yeti	Tue May 07 21:43:10 2013 +0100
+++ b/yetilab/vamp/vamp.yeti	Sat May 11 16:00:58 2013 +0100
@@ -10,7 +10,7 @@
 
 import java.util: Map, List;
 
-bl = load yetilab.block.block;
+vec = load yetilab.vector.vector;
 fr = load yetilab.stream.framer;
 af = load yetilab.stream.audiofile;
 mat = load yetilab.matrix.matrix;
@@ -24,7 +24,7 @@
 feature f is ~Feature -> 'a = {
     timestamp = if f#hasTimestamp then Time (realTime f#timestamp) else Untimed () fi,
     duration = if f#hasDuration then Time (realTime f#duration) else Untimed () fi,
-    values = bl.fromFloats f#values,
+    values = vec.fromFloats f#values,
     label = f#label,
     };
 
@@ -209,7 +209,7 @@
         None (): map (outputDescriptor (None ())) p#getOutputDescriptors();
         esac,
     process frame time is 'a -> ~RealTime -> 'b = 
-        featureSet p#process((map bl.floats (mat.asRows frame)) as ~float[][], 0, time),
+        featureSet p#process((map vec.floats (mat.asRows frame)) as ~float[][], 0, time),
     getRemainingFeatures () = featureSet p#getRemainingFeatures(),
     dispose () = p#dispose(),
     });
@@ -233,9 +233,9 @@
         Error "Failed to load Vamp plugin with key \(key)"
     yrt;
 
-//!!! bring block typedef into scope -- this shouldn't be necessary,
+//!!! bring vector typedef into scope -- this shouldn't be necessary,
 //but see comment in processed below
-load yetilab.block.blocktype;
+load yetilab.vector.vectortype;
 
 processed { p, sampleRate, hop } frames count 
     // I don't know why this type declaration is necessary. Without
@@ -247,7 +247,7 @@
                   list<{ timestamp is Time number | Untimed (), 
                          duration  is Time number | Untimed (),
                          label is string,
-                         values is block
+                         values is vector
                        }>>> =
     case frames of
     frame::rest:
--- a/yetilab/vamp/vamppost.yeti	Tue May 07 21:43:10 2013 +0100
+++ b/yetilab/vamp/vamppost.yeti	Sat May 11 16:00:58 2013 +0100
@@ -1,7 +1,7 @@
 module yetilab.vamp.vamppost;
 
 mat = load yetilab.matrix.matrix;
-bl = load yetilab.block.block;
+vec = load yetilab.vector.vector;
 
 fillOneSamplePerStep config features =
    (fill' n pending features =
@@ -76,14 +76,14 @@
         {
             start = t0,
             step = t1 - t0,
-            values = map do f: (bl.data f.values)[0] done features;
+            values = map do f: vec.at 0 f.values done features;
         }
     fi;
 
 structureCurve features =
     map do f: {
         time = timeOf f,
-        value = (bl.data f.values)[0],
+        value = vec.at 0 f.values,
         label = f.label
     } done features;
 
@@ -96,7 +96,7 @@
 structureSegmentation features =
     map do f: {
         time = timeOf f,
-        type = (bl.data f.values)[0],
+        type = vec.at 0 f.values,
         label = f.label
     } done features;
 
@@ -104,8 +104,8 @@
     map do f: {
         time = timeOf f,
         duration = f.duration,
-        pitch = (bl.data f.values)[0], //!!! no, might be empty
-        otherValues = array (tail (bl.list f.values)), //!!! no, might be empty
+        pitch = vec.at 0 f.values, //!!! no, might be empty
+        otherValues = array (tail (vec.list f.values)), //!!! no, might be empty
         label = f.label
     } done features;
 
@@ -113,14 +113,14 @@
     map do f: {
         time = timeOf f,
         duration = f.duration,
-        values = array (bl.list f.values),
+        values = array (vec.list f.values),
         label = f.label
     } done features;
 
 structureWithoutDuration features =
     map do f: {
         time = timeOf f,
-        values = array (bl.list f.values),
+        values = array (vec.list f.values),
         label = f.label
     } done features;
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/yetilab/vector/blockfuncs.yeti	Sat May 11 16:00:58 2013 +0100
@@ -0,0 +1,73 @@
+
+module yetilab.vector.blockfuncs;
+
+vec = load yetilab.vector.vector;
+
+load yetilab.vector.vectortype;
+
+//!!! "internal" vector function to retrieve data for read-only
+// purposes without copying
+raw =
+   (raw' v is ~double[] -> ~double[] = v;
+    raw' as vector -> ~double[]);
+
+sum' v =
+   (dat = raw v;
+    tot = new double[1];
+    for [0..length dat - 1] do i:
+        tot[0] := tot[0] + dat[i]
+    done;
+    tot[0]);
+
+mean v =
+    case vec.length v of
+        0: 0;
+        len: sum' v / len
+    esac;
+
+multiply b1 b2 =
+   (v1 = raw b1;
+    v2 = raw b2;
+    len = if length v1 < length v2 then length v1 else length v2 fi;
+    out = new double[len];
+    for [0..len-1] do i:
+        out[i] := v1[i] * v2[i]
+    done;
+    vec.vector out);
+
+divideBy n v =
+    vec.fromList (map (/ n) (vec.list v));
+
+sqr v =
+    multiply v v;
+
+rms =
+    sqrt . mean . sqr;
+
+sqrt' =
+    vec.fromList . (map sqrt) . vec.list;
+
+fftshift v =
+   (len = vec.length v;
+    half = int(len/2 + 0.5); // round up for odd-length sequences
+    vec.concat [vec.rangeOf half (len-half) v, vec.rangeOf 0 half v]);
+
+ifftshift v =
+   (len = vec.length v;
+    half = int(len/2); // round down for odd-length sequences
+    vec.concat [vec.rangeOf half (len-half) v, vec.rangeOf 0 half v]);
+
+{
+sum is vector -> number = sum',
+mean is vector -> number,
+multiply is vector -> vector -> vector, 
+divideBy is number -> vector -> vector, 
+sqr is vector -> vector,
+sqrt is vector -> vector = sqrt',
+rms is vector -> number,
+fftshift is vector -> vector,
+ifftshift is vector -> vector,
+}
+
+
+        
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/yetilab/vector/complex.yeti	Sat May 11 16:00:58 2013 +0100
@@ -0,0 +1,98 @@
+
+module yetilab.vector.complex;
+
+load yetilab.vector.vectortype;
+load yetilab.vector.complextype;
+
+vec = load yetilab.vector.vector;
+
+import java.lang: ClassCastException;
+
+class Cplx(double real, double imag)
+    int getReal()
+        real,
+    int getImag()
+        imag,
+    double getMagnitude()
+        sqrt (real * real + imag * imag),
+    double getAngle()
+        Math#atan2(imag, real),
+    String toString()
+        if real == int real and imag == int imag then
+            if imag < 0 then
+                " \(int real) - \(int (-imag))i"
+            else 
+                " \(int real) + \(int imag)i"
+            fi
+        else
+            if imag < 0 then
+                " \(real) - \((-imag))i"
+            else 
+                " \(real) + \(imag)i"
+            fi
+        fi,
+    int hashCode()
+        Double#valueOf(real)#hashCode() + Double#valueOf(imag)#hashCode(),
+    boolean equals(Object other)
+        try
+            c = other unsafely_as ~Cplx;
+            c#getReal() == real and c#getImag() == imag
+        catch ClassCastException:
+            false
+        yrt,
+end;
+
+real c1 is ~Cplx -> number =
+    c1#getReal();
+
+imaginary c1 is ~Cplx -> number =
+    c1#getImag();
+
+complex re im is number -> number -> ~Cplx =
+    new Cplx(re, im);
+
+magnitude c is ~Cplx -> number =
+    c#getMagnitude();
+
+angle c is ~Cplx -> number =
+    c#getAngle();
+
+add c1 c2 is ~Cplx -> ~Cplx -> ~Cplx =
+    complex (real c1 + real c2) (imaginary c1 + imaginary c2);
+
+scale r c is number -> ~Cplx -> ~Cplx =
+    complex (r * real c) (r * imaginary c);
+
+zeros n is number -> array<~Cplx> =
+    array (map \(complex 0 0) [1..n]);
+
+magnitudes cc is list?<~Cplx> -> vector =
+    vec.fromList (map magnitude cc);
+
+angles cc is list?<~Cplx> -> vector =
+    vec.fromList (map angle cc);
+
+{
+   real,
+   imaginary,
+   complex,
+   magnitude,
+   angle,
+   add,
+   scale,
+   zeros,
+   magnitudes,
+   angles,
+} as {
+   real is cplx -> number,
+   imaginary is cplx -> number,
+   complex is number -> number -> cplx,
+   magnitude is cplx -> number,
+   angle is cplx -> number,
+   add is cplx -> cplx -> cplx,
+   scale is number -> cplx -> cplx,
+   zeros is number -> array<cplx>,
+   magnitudes is list?<cplx> -> vector,
+   angles is list?<cplx> -> vector,
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/yetilab/vector/complextype.yeti	Sat May 11 16:00:58 2013 +0100
@@ -0,0 +1,7 @@
+
+module yetilab.vector.complextype;
+
+typedef opaque cplx = ~Cplx;
+
+();
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/yetilab/vector/test/test_blockfuncs.yeti	Sat May 11 16:00:58 2013 +0100
@@ -0,0 +1,68 @@
+
+module yetilab.vector.test.test_blockfuncs;
+
+stdSqrt = sqrt;
+
+{ zeros, consts, ones, fromList, list } = load yetilab.vector.vector;
+{ sum, mean, multiply, divideBy, sqr, sqrt, rms, fftshift, ifftshift } = load yetilab.vector.blockfuncs;
+{ compare } = load yetilab.test.test;
+
+[
+
+"sum": \(
+    compare ((sum . zeros) 0) 0 and
+        compare ((sum . zeros) 5) 0 and
+        compare ((sum . ones) 5) 5 and
+        compare ((sum . fromList) [1,-2,3,0]) 2
+),
+
+"mean": \(
+    compare ((mean . zeros) 0) 0 and
+        compare ((mean . zeros) 5) 0 and
+        compare ((mean . ones) 5) 1 and
+        compare ((mean . fromList) [1,-2,3,0]) 0.5
+),
+
+"multiply": \(
+    compare (list (multiply (zeros 0) (ones 5))) [] and
+        compare (list (multiply (consts (-3) 4) (fromList [1,2,3]))) [-3,-6,-9]
+),
+
+"divideBy": \(
+    compare (list (divideBy 5 (ones 0))) [] and
+        compare (list (divideBy 5 (fromList [1,2,-3]))) [0.2,0.4,-0.6]
+),
+
+"sqr": \(
+    compare ((list . sqr . zeros) 0) [] and
+        compare ((list . sqr . ones) 5) [1,1,1,1,1] and
+        compare ((list . sqr . fromList) [0.5,-2,3,0]) [0.25,4,9,0]
+),
+
+"sqrt": \(
+    compare ((list . sqrt . zeros) 0) [] and
+        compare ((list . sqrt . ones) 5) [1,1,1,1,1] and
+        compare ((list . sqrt . fromList) [0.25,4,9,0]) [0.5,2,3,0]
+),
+
+"rms": \(
+    compare ((rms . zeros) 0) 0 and
+        compare ((rms . ones) 5) 1 and
+        compare ((rms . fromList) [-1,2,2]) (stdSqrt 3)
+),
+
+"fftshift": \(
+    compare ((list . fftshift . zeros) 0) [] and 
+        compare ((list . fftshift . fromList) [1,2,3,4]) [3,4,1,2] and
+        compare ((list . fftshift . fromList) [1,2,3,4,5]) [4,5,1,2,3]
+),
+
+"ifftshift": \(
+    compare ((list . ifftshift . zeros) 0) [] and 
+        compare ((list . ifftshift . fromList) [3,4,1,2]) [1,2,3,4] and
+        compare ((list . ifftshift . fromList) [4,5,1,2,3]) [1,2,3,4,5]
+),
+
+] is hash<string, () -> boolean>;
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/yetilab/vector/test/test_complex.yeti	Sat May 11 16:00:58 2013 +0100
@@ -0,0 +1,66 @@
+module yetilab.vector.test.test_complex;
+
+{ real, imaginary, complex, magnitude, angle, add, scale, zeros, magnitudes, angles }
+   = load yetilab.vector.complex;
+
+{ compare } = load yetilab.test.test;
+
+vec = load yetilab.vector.vector;
+
+[
+
+"complex": \( 
+    compare (complex 1 2) (complex 1 2) and
+        complex (-1) 2 != complex 1 2
+),
+
+"real": \(
+    compare (real (complex 3 2)) 3
+),
+
+"imaginary": \(
+    compare (imaginary (complex 3 4)) 4
+),
+
+"magnitude": \(
+    compare (magnitude (complex (-3) 4)) 5
+),
+
+"angle": \(
+    compare (angle (complex 1 0)) 0 and
+        compare (angle (complex 1 1)) (pi/4) and
+        compare (angle (complex 0 1)) (pi/2) and
+        compare (angle (complex (-1) 0)) pi and
+        compare (angle (complex 0 (-1))) (-pi/2)
+),
+
+"add": \(
+    compare (add (complex 2 3) (complex (-4) 5)) (complex (-2) 8)
+),
+
+"scale": \(
+    compare (scale 4 (complex 2 3)) (complex 8 12)
+),
+
+"zeros": \(
+    compare (zeros 0) (array []) and
+        compare (zeros 3) (array [complex 0 0, complex 0 0, complex 0 0])
+),
+
+"magnitudes": \(
+    compare (vec.list (magnitudes [ complex (-3) 4, complex 4 3, complex 0 0 ]))
+            [ 5, 5, 0 ] and
+       compare (vec.list (magnitudes (array []))) []
+),
+
+"angles": \(
+    compare (vec.list (angles [ complex 1 0, complex (-1) 0, complex 0 (-1) ]))
+            [ 0, pi, -pi/2 ] and
+       compare (vec.list (angles (array []))) []
+),
+
+
+] is hash<string, () -> boolean>;
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/yetilab/vector/test/test_vector.yeti	Sat May 11 16:00:58 2013 +0100
@@ -0,0 +1,130 @@
+
+module yetilab.vector.test.test_vector;
+
+vec = load yetilab.vector.vector;
+
+{ compare } = load yetilab.test.test;
+
+[
+
+"zeros-empty": \(
+    v = vec.zeros 0;
+    compare (vec.length v) 0;
+),
+
+"zeros": \(
+    v = vec.zeros 3;
+    a = vec.array v;
+    compare (vec.length v) 3 and
+        compare a[0] 0 and
+        compare a[1] 0 and
+        compare a[2] 0;
+),
+
+"consts-empty": \(
+    v = vec.consts 4 0;
+    compare (vec.length v) 0;
+),
+
+"consts": \(
+    v = vec.consts 4 3;
+    a = vec.array v;
+    compare (vec.length v) 3 and
+        compare a[0] 4 and
+        compare a[1] 4 and
+        compare a[2] 4;
+),
+
+"ones-empty": \(
+    v = vec.ones 0;
+    compare (vec.length v) 0;
+),
+
+"ones": \(
+    v = vec.ones 3;
+    a = vec.array v;
+    compare (vec.length v) 3 and
+        compare a[0] 1 and
+        compare a[1] 1 and
+        compare a[2] 1;
+),
+
+"from-list-empty": \(
+    v = vec.fromList [];
+    compare (vec.length v) 0;
+),
+
+"from-list": \(
+    v = vec.fromList [1,2,3,4];
+    a = vec.array v;
+    compare (vec.length v) 4 and
+        compare a[0] 1 and
+        compare a[1] 2 and
+        compare a[2] 3 and
+        compare a[3] 4;
+),
+
+"equal-empty": \(
+    vec.equal (vec.fromList []) (vec.fromList [])
+),
+
+"equal": \(
+    v = vec.fromList [1,1,1,1];
+    w = vec.ones 4;
+    w' = vec.zeros 4;
+    w'' = vec.ones 3;
+    vec.equal v w and not vec.equal v w' and not vec.equal v w'';
+),
+/*
+"copyOf-empty": \(
+    vec.equal (vec.fromList []) (vec.copyOf (vec.fromList []))
+),
+
+"copyOf": \(
+    v = vec.fromList [1,2,3,4];
+    w = vec.copyOf v;
+    vec.equal v w and (
+        v[0] := 0; // check result is not aliasing inputs
+        not vec.equal v w
+    );
+),
+*/
+"rangeOf": \(
+    v = vec.fromList [1,2,3,4];
+    vec.equal (vec.rangeOf 0 4 v) v and (
+        vec.equal (vec.rangeOf 2 2 v) (vec.fromList [3,4])
+    )
+),
+
+"resizedTo": \(
+    vec.equal (vec.resizedTo 4 (vec.fromList [])) (vec.zeros 4) and
+        vec.equal (vec.resizedTo 2 (vec.fromList [1,2])) (vec.fromList [1,2]) and
+        vec.equal (vec.resizedTo 3 (vec.fromList [1,2])) (vec.fromList [1,2,0]) and
+        vec.equal (vec.resizedTo 2 (vec.fromList [1,2,3])) (vec.fromList [1,2]);
+),
+
+"concat2": \(
+    v = vec.fromList [1,2,3];
+    w = vec.fromList [4,5,6];
+    x = vec.concat [v, w];
+    x' = vec.fromList [1,2,3,4,5,6];
+    vec.equal x x' and
+/*       (v[0] := 0; // check result is not aliasing inputs
+        w[0] := 0;
+        vec.equal x x') and */
+        vec.equal x' (vec.concat [x', vec.fromList []]) and
+        vec.equal x' (vec.concat [vec.fromList [], x'])
+),
+
+"concatn": \(
+    v = vec.fromList [1,2,3];
+    w = vec.fromList [4,5,6];
+    vec.equal (vec.concat []) (vec.zeros 0) and
+        vec.equal (vec.concat [v]) v and
+        vec.equal (vec.concat [v,w,v]) (vec.fromList [1,2,3,4,5,6,1,2,3])
+),
+
+] is hash<string, () -> boolean>;
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/yetilab/vector/vector.yeti	Sat May 11 16:00:58 2013 +0100
@@ -0,0 +1,124 @@
+
+module yetilab.vector.vector;
+
+load yetilab.vector.vectortype;
+
+import java.util: Arrays;
+
+//!!! This is supposed to be 100% immutable and without copying when duplicating for read only
+
+zeros n =
+    new double[n];
+
+consts m n =
+   (a = zeros n;
+    for [0..n-1] do i:
+        a[i] := m;
+    done;
+    a);
+
+ones = consts 1.0;
+
+fromList l is list?<number> -> ~double[] =
+   (arr = array(l);
+    len = length arr;
+    v = zeros len;
+    for [0..len-1] do i:
+        v[i] := arr[i];
+    done;
+    v);
+
+list' a is ~double[] -> list<number> =
+    list a;
+
+array' a is ~double[] -> array<number> =
+    array a;
+
+length' =
+    length . list';
+
+empty?' =
+    empty? . list';
+
+at' n v is number -> ~double[] -> number =
+    v[n];
+
+floats a is ~double[] -> ~float[] =
+   (len = length' a;
+    f = new float[len];
+    for [0..len-1] do i:
+        f[i] := a[i];
+    done;
+    f);
+
+fromFloats ff is ~float[] -> ~double[] =
+   (len = length (list ff);
+    a = new double[len];
+    for [0..len-1] do i:
+        a[i] := ff[i];
+    done;
+    a);
+
+equal v1 v2 =
+    list' v1 == list' v2;
+
+copyOf v is ~double[] -> ~double[] =
+    Arrays#copyOf(v, list' v |> length);
+
+rangeOf start len v is number -> number -> ~double[] -> ~double[] =
+    Arrays#copyOfRange(v, start, start + len);
+
+resizedTo n v is number -> ~double[] -> ~double[] =
+    Arrays#copyOf(v, n);
+
+concat vv is list?<~double[]> -> ~double[] =
+   (len = sum (map length' vv);
+    vout = zeros len;
+    var base = 0;
+    for vv do v: 
+        vlen = length' v;
+        for [0..vlen-1] do i: vout[base + i] := v[i] done;
+        base := base + vlen;
+    done;
+    vout);
+
+{
+    zeros,
+    consts,
+    ones,
+    vector v = v,
+    primitive = copyOf,
+    floats,
+    fromFloats,
+    fromList,
+    list = list',
+    array = array',
+    length = length',
+    empty? = empty?',
+    at = at',
+    equal,
+    rangeOf,
+    resizedTo,
+    concat,
+} as {
+    zeros is number -> vector,
+    consts is number -> number -> vector,
+    ones is number -> vector,
+    vector is ~double[] -> vector,
+    primitive is vector -> ~double[],
+    floats is vector -> ~float[],
+    fromFloats is ~float[] -> vector,
+    fromList is list?<number> -> vector,
+    list is vector -> list<number>,
+    array is vector -> array<number>,
+    length is vector -> number,
+    empty? is vector -> boolean,
+    at is number -> vector -> number,
+    equal is vector -> vector -> boolean,
+    rangeOf is number -> number -> vector -> vector, //!!! not well-named now vector arg is at the end
+    resizedTo is number -> vector -> vector,
+    concat is list?<vector> -> vector,
+}
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/yetilab/vector/vectortype.yeti	Sat May 11 16:00:58 2013 +0100
@@ -0,0 +1,7 @@
+
+module yetilab.vector.vectortype;
+
+typedef opaque vector = ~double[];
+
+();
+