annotate yetilab/matrix/matrix.yeti @ 97:d5fc902dcc3f

Initial matrix tests
author Chris Cannam
date Wed, 20 Mar 2013 22:49:41 +0000
parents a5b4d0f68ca8
children bd135a950af7
rev   line source
Chris@5 1
Chris@94 2 module yetilab.matrix.matrix;
Chris@94 3
Chris@94 4 // A matrix is an array of fvectors (i.e. primitive double[]s).
Chris@94 5
Chris@94 6 // A matrix can be either RowMajor, akin to a C multidimensional array
Chris@96 7 // in which each row is a separate fvector, or ColumnMajor, akin to a
Chris@94 8 // FORTAN multidimensional array in which each column is a separate
Chris@96 9 // fvector. The default is ColumnMajor. Storage order is an efficiency
Chris@94 10 // concern only, all operations behave identically regardless. (The
Chris@94 11 // transpose function just switches the row/column order without
Chris@94 12 // moving the elements.)
Chris@18 13
Chris@93 14 vec = load yetilab.block.fvector;
Chris@96 15 block = load yetilab.block.block;
Chris@9 16
Chris@96 17 make d = {
Chris@96 18 get data () = d,
Chris@96 19 get size () =
Chris@96 20 case d of
Chris@96 21 RowM r:
Chris@96 22 major = length r;
Chris@96 23 {
Chris@96 24 rows = major,
Chris@96 25 columns = if major > 0 then vec.length r[0] else 0 fi,
Chris@96 26 };
Chris@96 27 ColM c:
Chris@96 28 major = length c;
Chris@96 29 {
Chris@96 30 rows = if major > 0 then vec.length c[0] else 0 fi,
Chris@96 31 columns = major,
Chris@96 32 };
Chris@94 33 esac,
Chris@96 34 getColumn j =
Chris@96 35 case d of
Chris@96 36 RowM rows: block.fromList (map do i: getAt i j done [0..length rows-1]);
Chris@96 37 ColM cols: block.block cols[j];
Chris@94 38 esac,
Chris@96 39 getRow i =
Chris@96 40 case d of
Chris@96 41 RowM rows: block.block rows[i];
Chris@96 42 ColM cols: block.fromList (map do j: getAt i j done [0..length cols-1]);
Chris@94 43 esac,
Chris@96 44 getAt row col =
Chris@96 45 case d of
Chris@96 46 RowM rows: r = rows[row]; (r is ~double[])[col];
Chris@96 47 ColM cols: c = cols[col]; (c is ~double[])[row];
Chris@94 48 esac,
Chris@96 49 setAt row col n =
Chris@96 50 case d of
Chris@96 51 RowM rows: r = rows[row]; (r is ~double[])[col] := n;
Chris@96 52 ColM cols: c = cols[col]; (c is ~double[])[row] := n;
Chris@95 53 esac,
Chris@95 54 get isRowMajor? () =
Chris@96 55 case d of
Chris@96 56 RowM _: true;
Chris@96 57 ColM _: false;
Chris@95 58 esac,
Chris@94 59 };
Chris@94 60
Chris@94 61 newStorage rows cols =
Chris@97 62 if rows < 1 then array []
Chris@97 63 else array (map \(vec.zeros rows) [1..cols])
Chris@97 64 fi;
Chris@94 65
Chris@94 66 zeroMatrix rows cols =
Chris@96 67 make (ColM (newStorage rows cols));
Chris@5 68
Chris@20 69 generate f rows cols =
Chris@94 70 (m = newStorage rows cols;
Chris@94 71 for [0..cols-1] do col:
Chris@94 72 for [0..rows-1] do row:
Chris@94 73 m[col][row] := f row col;
Chris@5 74 done;
Chris@5 75 done;
Chris@96 76 make (ColM m));
Chris@5 77
Chris@20 78 constMatrix n = generate do row col: n done;
Chris@20 79 randomMatrix = generate do row col: Math#random() done;
Chris@5 80 identityMatrix = constMatrix 1;
Chris@5 81
Chris@96 82 width m = m.size.columns;
Chris@96 83 height m = m.size.rows;
Chris@6 84
Chris@97 85 equal m1 m2 =
Chris@97 86 (compare d1 d2 =
Chris@97 87 all id (map2 vec.equal d1 d2);
Chris@97 88 case m1.data of
Chris@97 89 RowM d1:
Chris@97 90 case m2.data of RowM d2: compare d1 d2; _: false; esac;
Chris@97 91 ColM d1:
Chris@97 92 case m2.data of ColM d2: compare d1 d2; _: false; esac;
Chris@97 93 esac);
Chris@97 94
Chris@95 95 copyOf m =
Chris@95 96 (copyOfData d = (array (map vec.copyOf d));
Chris@96 97 make
Chris@95 98 (case m.data of
Chris@96 99 RowM d: RowM (copyOfData d);
Chris@96 100 ColM d: ColM (copyOfData d);
Chris@95 101 esac));
Chris@6 102
Chris@95 103 transposed m =
Chris@96 104 make
Chris@95 105 (case m.data of
Chris@96 106 RowM d: ColM d;
Chris@96 107 ColM d: RowM d;
Chris@95 108 esac);
Chris@5 109
Chris@96 110 //!!! Change storage from column to row major order (or back
Chris@96 111 //again). Is there a word for this?
Chris@96 112 flipped m =
Chris@96 113 if m.isRowMajor? then id else transposed fi
Chris@96 114 (generate do row col: m.getAt col row done m.size.columns m.size.rows);
Chris@96 115
Chris@96 116 newMatrix type data is RowMajor () | ColumnMajor () -> list?<list?<number>> -> 'a =
Chris@96 117 (tagger = case type of RowMajor (): RowM; ColumnMajor (): ColM esac;
Chris@97 118 if empty? data or empty? (head data)
Chris@96 119 then zeroMatrix 0 0
Chris@96 120 else make (tagger (array (map vec.vector data)))
Chris@96 121 fi);
Chris@96 122
Chris@96 123 newRowVector data =
Chris@96 124 newMatrix (RowMajor ()) [data];
Chris@96 125
Chris@96 126 newColumnVector data =
Chris@96 127 newMatrix (ColumnMajor ()) [data];
Chris@8 128
Chris@5 129 {
Chris@97 130 constMatrix, randomMatrix, zeroMatrix, identityMatrix,
Chris@96 131 generate,
Chris@96 132 width, height,
Chris@97 133 equal,
Chris@20 134 copyOf,
Chris@15 135 transposed,
Chris@96 136 flipped,
Chris@96 137 newMatrix, newRowVector, newColumnVector
Chris@5 138 }
Chris@5 139