1 package Maasha::Matrix;
3 # Copyright (C) 2007 Martin A. Hansen.
5 # This program is free software; you can redistribute it and/or
6 # modify it under the terms of the GNU General Public License
7 # as published by the Free Software Foundation; either version 2
8 # of the License, or (at your option) any later version.
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 # http://www.gnu.org/copyleft/gpl.html
22 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> DESCRIPTION <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
25 # This modules contains subroutines for simple matrix manipulations.
28 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
33 use Storable qw( dclone );
36 use vars qw ( @ISA @EXPORT );
39 @ISA = qw( Exporter );
47 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> SUBROUTINES <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
52 # Martin A. Hansen, April 2007
54 # returns the dimensions of a matrix: rows x cols
56 my ( $matrix, # AoA data structure
63 $rows = scalar @{ $matrix };
64 $cols = scalar @{ $matrix->[ 0 ] };
66 return wantarray ? ( $rows, $cols ) : [ $rows, $cols ];
72 # Martin A. Hansen, April 2007.
74 # Checks that the matrix of even columns.
75 # return 1 if ok else 0.
77 my ( $matrix, # AoA data structure
82 my ( $dims, $row, $check );
84 $dims = matrix_dims( $matrix );
86 $check = $dims->[ COLS ];
88 foreach $row ( @{ $matrix } ) {
89 return 0 if scalar @{ $row } != $check;
98 # Martin A. Hansen, April 2007.
100 # For each column in a given matrix print:
102 my ( $matrix, # AoA data structure
105 my ( $dims, $i, $col, $list, $type, $sort, $uniq, $min, $max, $mean );
107 die qq(ERROR: cannot summarize uneven matrix\n) if not matrix_check( $matrix );
109 $dims = matrix_dims( $matrix );
111 print join( "\t", "TYPE", "LEN", "UNIQ", "SORT", "MIN", "MAX", "MEAN" ), "\n";
113 for ( $i = 0; $i < $dims->[ COLS ]; $i++ )
115 $col = cols_get( $matrix, $i, $i );
116 $list = matrix_flip( $col )->[ 0 ];
118 if ( list_check_numeric( $list ) ) {
124 if ( list_check_sort( $list, $type ) ) {
130 if ( $type eq "num" )
132 if ( $sort eq "yes" )
135 $max = $list->[ -1 ];
139 ( $min, $max ) = Maasha::Calc::minmax( $list );
142 $mean = sprintf( "%.2f", Maasha::Calc::mean( $list ) );
151 $uniq = list_uniq( $list );
153 print join( "\t", $type, $dims->[ ROWS ], $uniq, $sort, $min, $max, $mean ), "\n";
160 # Martin A. Hansen, April 2007
162 # flips a matrix making rows to columns and visa versa.
164 my ( $matrix, # AoA data structure
169 my ( $i, $c, $dims, $AoA );
171 die qq(ERROR: cannot flip uneven matrix\n) if not matrix_check( $matrix );
173 $dims = matrix_dims( $matrix );
175 for ( $i = 0; $i < $dims->[ ROWS ]; $i++ )
177 for ( $c = 0; $c < $dims->[ COLS ]; $c++ ) {
178 $AoA->[ $c ]->[ $i ] = $matrix->[ $i ]->[ $c ];
184 return wantarray ? @{ $matrix } : $matrix;
188 sub matrix_rotate_right
190 # Martin A. Hansen, April 2007
192 # Rotates elements in a given matrix a given
193 # number of positions to the right by popping columns,
194 # from the right matrix edge and prefixed to the left edge.
196 my ( $matrix, # AoA data structure
197 $shift, # number of shifts - DEFAULT=1
202 my ( $i, $dims, $col, $AoA );
206 die qq(ERROR: cannot right rotate uneven matrix\n) if not matrix_check( $matrix );
208 $dims = matrix_dims( $matrix );
210 for ( $i = 0; $i < $shift; $i++ )
212 $col = cols_get( $matrix, $dims->[ COLS ] - 1, $dims->[ COLS ] - 1 );
213 $AoA = cols_get( $matrix, 0, $dims->[ COLS ] - 2 );
215 cols_unshift( $AoA, $col );
220 return wantarray ? @{ $matrix } : $matrix;
224 sub matrix_rotate_left
226 # Martin A. Hansen, April 2007
228 # Rotates elements in a given matrix a given
229 # number of positions to the left while columns
230 # are shifted from the left matrix edge and appended,
233 my ( $matrix, # AoA data structure
234 $shift, # number of shifts - DEFAULT=1
239 my ( $i, $dims, $col, $AoA );
243 die qq(ERROR: cannot right rotate uneven matrix\n) if not matrix_check( $matrix );
245 $dims = matrix_dims( $matrix );
247 for ( $i = 0; $i < $shift; $i++ )
249 $col = cols_get( $matrix, 0, 0 );
250 $AoA = cols_get( $matrix, 1, $dims->[ COLS ] - 1 );
252 cols_push( $AoA, $col );
257 return wantarray ? @{ $matrix } : $matrix;
263 # Martin A. Hansen, April 2007
265 # Rotates elements in a given matrix a given
266 # number of positions up while rows are shifted
267 # from the top of the matrix to the bottom.
269 my ( $matrix, # AoA data structure
270 $shift, # number of shifts - DEFAULT=1
275 my ( $dims, $i, $row, $AoA );
279 $dims = matrix_dims( $matrix );
281 for ( $i = 0; $i < $shift; $i++ )
283 $row = rows_get( $matrix, 0, 0 );
284 $AoA = rows_get( $matrix, 1, $dims->[ ROWS ] - 1 );
286 rows_push( $AoA, dclone $row );
291 return wantarray ? @{ $matrix } : $matrix;
295 sub matrix_rotate_down
297 # Martin A. Hansen, April 2007
299 # Rotates elements in a given matrix a given
300 # number of positions down while rows are shifted
301 # from the bottom matrix edge to the top edge.
303 my ( $matrix, # AoA data structure
304 $shift, # number of shifts - DEFAULT=1
309 my ( $dims, $i, $row, $AoA );
313 $dims = matrix_dims( $matrix );
315 for ( $i = 0; $i < $shift; $i++ )
317 $row = rows_get( $matrix, $dims->[ ROWS ] - 1, $dims->[ ROWS ] - 1 );
318 $AoA = rows_get( $matrix, 0, $dims->[ ROWS ] - 2 );
320 rows_unshift( $AoA, $row );
325 return wantarray ? @{ $matrix } : $matrix;
331 # Martin A. Hansen, April 2007
333 # returns a submatrix sliced from a given matrix
335 my ( $matrix, # AoA data structure
336 $row_beg, # first row - OPTIONAL (default 0)
337 $row_end, # last row - OPTIONAL (default last row)
338 $col_beg, # first col - OPTIONAL (default 0)
339 $col_end, # last col - OPTIONAL (default last col)
344 my ( $submatrix, $subsubmatrix );
346 $submatrix = rows_get( $matrix, $row_beg, $row_end );
347 $subsubmatrix = cols_get( $submatrix, $col_beg, $col_end );
349 return wantarray ? @{ $subsubmatrix } : $subsubmatrix;
355 # Martin A. Hansen, April 2008.
357 # Returns a single row from a given matrix.
359 my ( $matrix, # AoA data structure
365 my ( $dims, $i, @list );
367 $dims = matrix_dims( $matrix );
369 Maasha::Common::error( qq(Row->$row outside of matrix->$dims->[ ROWS ]) ) if $row > $dims->[ ROWS ];
371 @list = @{ $matrix->[ $row ] };
373 return wantarray ? @list : \@list;
379 # Martin A. Hansen, April 2007
381 # returns a range of requested rows from a given matrix.
383 my ( $matrix, # AoA data structure
384 $row_beg, # first row - OPTIONAL (default 0)
385 $row_end, # last row - OPTIONAL (default last row)
394 if ( not defined $row_end ) {
395 $row_end = scalar @{ $matrix };
398 if ( $row_end >= scalar @{ $matrix } )
400 warn qq(WARNING: row end larger than matrix\n);
401 $row_end = scalar( @{ $matrix } ) - 1;
404 die qq(ERROR: row begin "$row_beg" larger than row end "$row_end"\n) if $row_end < $row_beg;
406 if ( $row_beg == 0 and $row_end == scalar( @{ $matrix } ) - 1 ) {
407 @rows = @{ $matrix };
409 @rows = @{ $matrix }[ $row_beg .. $row_end ];
412 return wantarray ? @rows : \@rows;
418 # Martin A. Hansen, April 2008.
420 # Returns a single column from a given matrix.
422 my ( $matrix, # AoA data structure
423 $col, # column to get
428 my ( $dims, $i, @list );
430 $dims = matrix_dims( $matrix );
432 Maasha::Common::error( qq(Column->$col outside of matrix->$dims->[ COLS ]) ) if $col > $dims->[ COLS ];
434 for ( $i = 0; $i < $dims->[ ROWS ]; $i++ ) {
435 push @list, $matrix->[ $i ]->[ $col ];
438 return wantarray ? @list : \@list;
444 # Martin A. Hansen, April 2007
446 # returns a range of requested columns from a given matrix
448 my ( $matrix, # AoA data structure
449 $col_beg, # first column - OPTIONAL (default 0)
450 $col_end, # last column - OPTIONAL (default last column)
455 my ( $dims, @cols, $row, @AoA );
457 $dims = matrix_dims( $matrix );
461 if ( not defined $col_end ) {
462 $col_end = $dims->[ COLS ] - 1;
465 if ( $col_end > $dims->[ COLS ] - 1 )
467 warn qq(WARNING: column end larger than matrix\n);
468 $col_end = $dims->[ COLS ] - 1;
471 die qq(ERROR: column begin "$col_beg" larger than column end "$col_end"\n) if $col_end < $col_beg;
473 if ( $col_beg == 0 and $col_end == $dims->[ COLS ] - 1 )
479 foreach $row ( @{ $matrix } )
481 @cols = @{ $row }[ $col_beg .. $col_end ];
483 push @AoA, [ @cols ];
487 return wantarray ? @AoA : \@AoA;
499 $list = cols_get( $matrix, $col, $col );
500 $list = matrix_flip( $list )->[ 0 ];
502 die qq(ERROR: cannot sum non-nummerical column\n);
504 $sum = Maasha::Calc::sum( $list );
512 # Martin A. Hansen, April 2007.
514 # Appends one or more rows to a matrix.
516 my ( $matrix, # AoA data structure
517 $rows, # list of rows
522 push @{ $matrix }, @{ $rows };
524 return wantarray ? @{ $matrix } : $matrix;
530 # Martin A. Hansen, April 2007.
532 # Prefixes one or more rows to a matrix.
534 my ( $matrix, # AoA data structure
535 $rows, # list of rows
540 unshift @{ $matrix }, @{ $rows };
542 return wantarray ? @{ $matrix } : $matrix;
548 # Martin A. Hansen, April 2007.
550 # Appends one or more lists as columns to a matrix.
552 my ( $matrix, # AoA data structure
553 $cols, # list of columns
558 my ( $dims_matrix, $dims_cols, $i );
560 $dims_matrix = matrix_dims( $matrix );
561 $dims_cols = matrix_dims( $cols );
563 die qq(ERROR: Cannot merge columns with different row count\n) if $dims_matrix->[ ROWS ] != $dims_cols->[ ROWS ];
565 for ( $i = 0; $i < $dims_matrix->[ ROWS ]; $i++ )
567 push @{ $matrix->[ $i ] }, @{ $cols->[ $i ] };
570 return wantarray ? @{ $matrix } : $matrix;
576 # Martin A. Hansen, April 2007.
578 # Prefixes one or more lists as columns to a matrix.
580 my ( $matrix, # AoA data structure
581 $cols, # list of columns
586 my ( $dims_matrix, $dims_cols, $i );
588 $dims_matrix = matrix_dims( $matrix );
589 $dims_cols = matrix_dims( $cols );
591 die qq(ERROR: Cannot merge columns with different row count\n) if $dims_matrix->[ ROWS ] != $dims_cols->[ ROWS ];
593 for ( $i = 0; $i < $dims_matrix->[ ROWS ]; $i++ ) {
594 unshift @{ $matrix->[ $i ] }, @{ $cols->[ $i ] };
597 return wantarray ? @{ $matrix } : $matrix;
603 # Martin A. Hansen, April 2007.
605 # Given a matrix and a range of rows, rotates these rows
606 # left by shifting a given number of elements from
607 # the first position to the last.
609 my ( $matrix, # AoA data structure
610 $beg, # first row to shift
611 $end, # last row to shit
612 $shift, # number of shifts - DEFAULT=1
621 for ( $i = $beg; $i <= $end; $i++ )
623 $row = rows_get( $matrix, $i, $i );
625 for ( $c = 0; $c < $shift; $c++ )
627 $row = list_rotate_left( @{ $row } );
628 $matrix->[ $i ] = $row;
632 return wantarray ? @{ $matrix } : $matrix;
636 sub rows_rotate_right
638 # Martin A. Hansen, April 2007.
640 # Given a matrix and a range of rows, rotates these rows
641 # right by shifting a given number of elements from the
642 # last position to the first.
644 my ( $matrix, # AoA data structure
645 $beg, # first row to shift
646 $end, # last row to shit
647 $shift, # number of shifts - DEFAULT=1
652 my ( $dims, $i, $c, $row );
656 $dims = matrix_dims( $matrix );
658 die qq(ERROR: end < beg: $end < $beg\n) if $end < $beg;
659 die qq(ERROR: row outside matrix\n) if $end >= $dims->[ ROWS ];
661 for ( $i = $beg; $i <= $end; $i++ )
663 $row = rows_get( $matrix, $i, $i );
665 for ( $c = 0; $c < $shift; $c++ )
667 $row = list_rotate_right( @{ $row } );
668 $matrix->[ $i ] = $row;
672 return wantarray ? @{ $matrix } : $matrix;
678 # Martin A. Hansen, April 2007.
680 # Given a matrix and a range of columns, rotates these columns
681 # ups by shifting the the first cell of each row from the
682 # first position to the last.
684 my ( $matrix, # AoA data structure
685 $beg, # first row to shift
686 $end, # last row to shit
687 $shift, # number of shifts - DEFAULT=1
692 my ( $dims, $i, $c, $cols_pre, $col_select, $cols_post, $list );
696 $dims = matrix_dims( $matrix );
698 $cols_pre = cols_get( $matrix, 0, $beg - 1 ) if $beg > 0;
699 $cols_post = cols_get( $matrix, $end + 1, $dims->[ COLS ] - 1 ) if $end < $dims->[ COLS ] - 1;
701 for ( $i = $beg; $i <= $end; $i++ )
703 $col_select = cols_get( $matrix, $i, $i );
705 $list = matrix_flip( $col_select )->[ 0 ];
707 for ( $c = 0; $c < $shift; $c++ ) {
708 $list = list_rotate_left( $list );
711 $col_select = matrix_flip( [ $list ] );
714 cols_push( $cols_pre, $col_select );
716 $cols_pre = $col_select;
720 cols_push( $cols_pre, $cols_post ) if $cols_post;
724 return wantarray ? @{ $matrix } : $matrix;
730 # Martin A. Hansen, April 2007.
732 # Given a matrix and a range of columns, rotates these columns
733 # ups by shifting the the first cell of each row from the
734 # first position to the last.
736 my ( $matrix, # AoA data structure
737 $beg, # first row to shift
738 $end, # last row to shit
739 $shift, # number of shifts - DEFAULT=1
744 my ( $dims, $i, $c, $cols_pre, $col_select, $cols_post, $list );
748 $dims = matrix_dims( $matrix );
750 $cols_pre = cols_get( $matrix, 0, $beg - 1 ) if $beg > 0;
751 $cols_post = cols_get( $matrix, $end + 1, $dims->[ COLS ] - 1 ) if $end < $dims->[ COLS ] - 1;
753 for ( $i = $beg; $i <= $end; $i++ )
755 $col_select = cols_get( $matrix, $i, $i );
757 $list = matrix_flip( $col_select )->[ 0 ];
759 for ( $c = 0; $c < $shift; $c++ ) {
760 $list = list_rotate_right( $list );
763 $col_select = matrix_flip( [ $list ] );
766 cols_push( $cols_pre, $col_select );
768 $cols_pre = $col_select;
772 cols_push( $cols_pre, $cols_post ) if $cols_post;
776 return wantarray ? @{ $matrix } : $matrix;
782 # Martin A. Hansen, April 2007.
784 # given a list, shifts off the first element,
785 # and appends to the list, which is returned.
787 my ( $list, # list to rotate
790 my ( @new_list, $elem );
792 @new_list = @{ $list };
794 $elem = shift @new_list;
796 push @new_list, $elem;
798 return wantarray ? @new_list : \@new_list;
802 sub list_rotate_right
804 # Martin A. Hansen, April 2007.
806 # given a list, pops off the last element,
807 # and prefixes to the list, which is returned.
809 my ( $list, # list to rotate
812 my ( @new_list, $elem );
814 @new_list = @{ $list };
816 $elem = pop @new_list;
818 unshift @new_list, $elem;
820 return wantarray ? @new_list : \@new_list;
824 sub list_check_numeric
826 # Martin A. Hansen, April 2007.
828 # Checks if a given list only contains
829 # numerical elements. return 1 if numerical,
832 my ( $list, # list to check
839 foreach $elem ( @{ $list } ) {
840 return 0 if not $elem =~ /^\d+$/; # how about scientific notation ala 123.2312e-03 ?
849 # Martin A. Hansen, April 2007.
851 # Checks if a given list is sorted.
852 # If the sort type is not specified, we
853 # are going to check the type and make a guess.
854 # Returns 1 if sorted else 0.
856 my ( $list, # list to check
857 $type, # numerical of alphabetical
866 if ( list_check_numeric( $list ) ) {
874 if ( $type =~ /^a.*/i ) {
881 if ( @{ $list } > 1 )
885 for ( $i = 1; $i < @{ $list }; $i++ )
887 $cmp = $list->[ $i - 1 ] <=> $list->[ $i ];
889 return 0 if $cmp > 0;
894 for ( $i = 1; $i < @{ $list }; $i++ )
896 $cmp = $list->[ $i - 1 ] cmp $list->[ $i ];
898 return 0 if $cmp > 0;
909 # Martin A. Hansen, April 2007.
911 # returns the number of unique elements in a
919 my ( %hash, $count );
921 map { $hash{ $_ } = 1 } @{ $list };
923 $count = scalar keys %hash;
931 # Martin A. Hansen, April 2007.
933 my ( $matrix, # AoA data structure
937 my ( $dims, $list, $i, $max, $len, %hash, $elem, @list );
939 $dims = matrix_dims( $matrix );
941 $list = cols_get( $matrix, $col, $col );
942 $list = matrix_flip( $list )->[ 0 ];
946 for ( $i = 0; $i < @{ $list }; $i++ )
948 $hash{ $list->[ $i ] }++;
950 $len = length $list->[ $i ];
952 $max = $len if $len > $max;
957 if ( list_check_numeric( $list ) ) {
958 @list = sort { $a <=> $b } @list;
960 @list = sort { $a cmp $b } @list;
963 foreach $elem ( @list )
965 print $elem, " " x ( $max - length( $elem ) ),
966 sprintf( " %6s ", $hash{ $elem } ),
967 sprintf( "%.2f\n", ( $hash{ $elem } / $dims->[ ROWS ] ) * 100 );
974 # Martin A. Hansen, July 2008.
976 # Merge two given tables based on identifiers in a for each table
977 # specified column which should contain a unique identifier.
978 # Initially the tables are sorted and tab2 is merged onto tab1
981 my ( $tab1, # table 1 - an AoA.
982 $tab2, # table 2 - an AoA.
983 $col1, # identifier in row1
984 $col2, # identifier in row2
985 $sort_type, # alphabetical or numeric comparison
990 my ( $num, $cmp, $i, $c, @row_cpy, $max );
995 if ( $sort_type =~ /num/i )
999 @{ $tab1 } = sort { $a->[ $col1 ] <=> $b->[ $col1 ] } @{ $tab1 };
1000 @{ $tab2 } = sort { $a->[ $col2 ] <=> $b->[ $col2 ] } @{ $tab2 };
1004 @{ $tab1 } = sort { $a->[ $col1 ] cmp $b->[ $col1 ] } @{ $tab1 };
1005 @{ $tab2 } = sort { $a->[ $col2 ] cmp $b->[ $col2 ] } @{ $tab2 };
1011 while ( $i < @{ $tab1 } and $c < @{ $tab2 } )
1014 $cmp = $tab1->[ $i ]->[ $col1 ] <=> $tab2->[ $c ]->[ $col2 ];
1016 $cmp = $tab1->[ $i ]->[ $col1 ] cmp $tab2->[ $c ]->[ $col2 ];
1021 @row_cpy = @{ $tab2->[ $c ] };
1023 splice @row_cpy, $col2, 1;
1025 push @{ $tab1->[ $i ] }, @row_cpy;
1036 map { push @{ $tab1->[ $i ] }, "null" } 0 .. ( scalar @{ $tab2->[ $c ] } - 2 );
1042 map { push @{ $tab1->[ -1 ] }, "null" } 0 .. ( scalar @{ $tab1->[ 0 ] } - scalar @{ $tab1->[ -1 ] } + 1 );
1046 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> BINARY SEARCH <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
1051 # Martin A. Hansen, February 2008.
1053 # Uses binary search to locate the interval containing a
1054 # given number. The intervals are defined by begin and end
1055 # positions in seperate columns in a matrix. If a interval is
1056 # found then the index of that matrix row is returned, otherwise
1059 my ( $matrix, # data structure
1060 $col1, # column with interval begins
1061 $col2, # column with interval ends
1062 $num, # number to search for
1065 # Returns an integer.
1067 my ( $high, $low, $try );
1070 $high = @{ $matrix };
1072 while ( $low < $high )
1074 $try = int( ( $high + $low ) / 2 );
1076 # print "num->$num low->$low high->$high try->$try int1->$matrix->[ $try ]->[ $col1 ] int2->$matrix->[ $try ]->[ $col2 ]\n";
1078 if ( $num < $matrix->[ $try ]->[ $col1 ] )
1082 elsif ( $num > $matrix->[ $try ]->[ $col2 ] )
1098 # Martin A. Hansen, February 2008.
1100 # Uses binary search to locate a number in a list of numbers.
1101 # If the number is found, then the index (the position of the number
1102 # in the list) is returned, otherwise -1 is returned.
1104 my ( $list, # list of numbers
1105 $num, # number to search for
1108 # Returns an integer.
1110 my ( $high, $low, $try );
1115 while ( $low < $high )
1117 $try = int( ( $high + $low ) / 2 );
1119 # print "num->$num low->$low high->$high try->$try int->$list->[ $try ]\n";
1121 if ( $num < $list->[ $try ] )
1125 elsif ( $num > $list->[ $try ] )
1139 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> DISK SUBROUTINES <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
1144 # Martin A. Hansen, April 2007
1146 # Reads tabular data from file into a matrix
1147 # AoA data structure.
1149 my ( $path, # full path to file with data
1150 $delimiter, # column delimiter - OPTIONAL (default tab)
1151 $comments, # regex for comment lines to skip - OPTIONAL
1152 $fields_ok, # list of fields to accept - OPTIONAL
1157 my ( $fh, $line, @fields, @AoA );
1159 $delimiter ||= "\t";
1161 $fh = Maasha::Common::read_open( $path );
1163 while ( $line = <$fh> )
1167 next if $comments and $line =~ /^$comments/;
1169 @fields = split /$delimiter/, $line;
1171 map { splice( @fields, $_, 1 ) } @{ $fields_ok } if $fields_ok;
1173 push @AoA, [ @fields ];
1178 return wantarray ? @AoA : \@AoA;
1184 # Martin A. Hansen, April 2007
1186 # Writes a tabular data structure to STDOUT or file.
1188 my ( $matrix, # AoA data structure
1189 $path, # full path to output file - OPTIONAL (default STDOUT)
1190 $delimiter, # column delimiter - OPTIONAL (default tab)
1195 $fh = Maasha::Common::write_open( $path ) if $path;
1197 $delimiter ||= "\t";
1199 foreach $row ( @{ $matrix } )
1202 print $fh join( $delimiter, @{ $row } ), "\n";
1204 print join( $delimiter, @{ $row } ), "\n";
1214 # Martin A. Hansen, April 2007.
1216 # stores a matrix to a binary file.
1218 my ( $path, # full path to file
1219 $matrix, # data structure
1222 Maasha::Common::file_store( $path, $matrix );
1228 # Martin A. Hansen, April 2007.
1230 # retrieves a matrix from a binary file
1232 my ( $path, # full path to file
1235 my $matrix = Maasha::Common::file_retrieve( $path );
1237 return wantarray ? @{ $matrix } : $matrix;
1241 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<