181 lines
6.1 KiB
Matlab
181 lines
6.1 KiB
Matlab
function [A,rows,cols,entries,rep,field,symm] = mmread(filename)
|
|
%
|
|
% function [A] = mmread(filename)
|
|
%
|
|
% function [A,rows,cols,entries,rep,field,symm] = mmread(filename)
|
|
%
|
|
% Reads the contents of the Matrix Market file 'filename'
|
|
% into the matrix 'A'. 'A' will be either sparse or full,
|
|
% depending on the Matrix Market format indicated by
|
|
% 'coordinate' (coordinate sparse storage), or
|
|
% 'array' (dense array storage). The data will be duplicated
|
|
% as appropriate if symmetry is indicated in the header.
|
|
%
|
|
% Optionally, size information about the matrix can be
|
|
% obtained by using the return values rows, cols, and
|
|
% entries, where entries is the number of nonzero entries
|
|
% in the final matrix. Type information can also be retrieved
|
|
% using the optional return values rep (representation), field,
|
|
% and symm (symmetry).
|
|
%
|
|
|
|
mmfile = fopen(filename,'r');
|
|
if ( mmfile == -1 )
|
|
disp(filename);
|
|
error('File not found');
|
|
end;
|
|
|
|
header = fgets(mmfile);
|
|
if (header == -1 )
|
|
error('Empty file.')
|
|
end
|
|
|
|
% NOTE: If using a version of Matlab for which strtok is not
|
|
% defined, substitute 'gettok' for 'strtok' in the
|
|
% following lines, and download gettok.m from the
|
|
% Matrix Market site.
|
|
[head0, header] = strtok(header); % see note above
|
|
[head1, header] = strtok(header);
|
|
[rep, header] = strtok(header);
|
|
[field, header] = strtok(header);
|
|
[symm, header] = strtok(header);
|
|
head1 = lower(head1);
|
|
rep = lower(rep);
|
|
field = lower(field);
|
|
symm = lower(symm);
|
|
if isempty(symm)
|
|
disp(['Not enough words in header line of file ',filename])
|
|
disp('Recognized format: ')
|
|
disp('%%MatrixMarket matrix representation field symmetry')
|
|
error('Check header line.')
|
|
end
|
|
if ~strcmp(head0,'%%MatrixMarket')
|
|
error('Not a valid MatrixMarket header.')
|
|
end
|
|
if ~strcmp(head1,'matrix')
|
|
disp(['This seems to be a MatrixMarket ',head1,' file.']);
|
|
disp('This function only knows how to read MatrixMarket matrix files.');
|
|
disp(' ');
|
|
error(' ');
|
|
end
|
|
|
|
% Read through comments, ignoring them
|
|
commentline = fgets(mmfile);
|
|
while ~isempty(commentline) && commentline(1) == '%',
|
|
commentline = fgets(mmfile);
|
|
end
|
|
|
|
% Read size information, then branch according to
|
|
% sparse or dense format
|
|
|
|
switch rep,
|
|
case 'coordinate', % read matrix given in sparse coordinate format
|
|
[sizeinfo,count] = sscanf(commentline, '%d%d%d');
|
|
while count == 0,
|
|
commentline = fgets(mmfile);
|
|
if commentline == -1,
|
|
error('End-of-file reached before size information was found.')
|
|
end
|
|
[sizeinfo,count] = sscanf(commentline, '%d%d%d');
|
|
if count > 0 && count ~= 3,
|
|
error('Invalid size specification line.')
|
|
end
|
|
end
|
|
rows = sizeinfo(1);
|
|
cols = sizeinfo(2);
|
|
entries = sizeinfo(3);
|
|
|
|
T = fscanf(mmfile, '%f');
|
|
switch field,
|
|
case 'real', % real valued entries:
|
|
check_size(T, 3 * entries);
|
|
T = reshape(T(:), 3, entries)';
|
|
A = sparse(T(:,1), T(:,2), T(:,3), rows , cols);
|
|
case 'complex', % complex valued entries:
|
|
check_size(T, 4 * entries);
|
|
T = reshape(T(:), 4, entries)';
|
|
A = sparse(T(:,1), T(:,2), T(:,3) + T(:,4)*1i, rows , cols);
|
|
case 'pattern', % pattern matrix (no values given):
|
|
check_size(T, 2 * entries);
|
|
T = reshape(T(:), 2, entries)';
|
|
A = sparse(T(:,1), T(:,2), ones(entries, 1), rows , cols);
|
|
end
|
|
case 'array', % read matrix given in dense array (column major) format
|
|
[sizeinfo, count] = sscanf(commentline, '%d%d');
|
|
while count == 0
|
|
commentline = fgets(mmfile);
|
|
if commentline == -1
|
|
error('End-of-file reached before size information was found.')
|
|
end
|
|
[sizeinfo, count] = sscanf(commentline, '%d%d');
|
|
if count > 0 && count ~= 2
|
|
error('Invalid size specification line.')
|
|
end
|
|
end
|
|
rows = sizeinfo(1);
|
|
cols = sizeinfo(2);
|
|
entries = rows*cols;
|
|
|
|
A = fscanf(mmfile, '%f');
|
|
switch field,
|
|
case 'real', % real valued entries:
|
|
% do nothing
|
|
case 'complex', % complex valued entries:
|
|
A = A(1:2:end-1) + 1i * A(2:2:end);
|
|
case 'pattern', % pattern (makes no sense for dense)
|
|
disp('Matrix type:',field)
|
|
error('Pattern matrix type invalid for array storage format.');
|
|
otherwise,
|
|
disp('Matrix type:',field)
|
|
error('Invalid matrix type specification. Check header against MM documentation.');
|
|
end
|
|
if any(strcmp(symm,{'symmetric','hermitian','skew-symmetric'}))
|
|
for j=1:cols-1,
|
|
currenti = j*rows;
|
|
A = [A(1:currenti);
|
|
zeros(j,1);
|
|
A(currenti+1:length(A))];
|
|
end
|
|
elseif ~strcmp(symm,'general'),
|
|
disp('Unrecognized symmetry')
|
|
disp(symm)
|
|
disp('Recognized choices:')
|
|
disp(' symmetric')
|
|
disp(' hermitian')
|
|
disp(' skew-symmetric')
|
|
disp(' general')
|
|
error('Check symmetry specification in header.');
|
|
end
|
|
A = reshape(A,rows,cols);
|
|
end
|
|
|
|
fclose(mmfile);
|
|
|
|
%
|
|
% If symmetric, skew-symmetric or Hermitian, duplicate lower
|
|
% triangular part and modify entries as appropriate:
|
|
%
|
|
|
|
switch symm,
|
|
case 'symmetric',
|
|
A = A + A.' - diag(diag(A));
|
|
entries = nnz(A);
|
|
case 'hermitian',
|
|
A = A + A' - diag(diag(A));
|
|
entries = nnz(A);
|
|
case 'skew-symmetric',
|
|
A = A - A.';
|
|
entries = nnz(A);
|
|
end
|
|
% Done.
|
|
|
|
end
|
|
|
|
|
|
function check_size(T, n)
|
|
if size(T) ~= n
|
|
disp('Data file does not contain expected amount of data.');
|
|
disp('Check that number of data lines matches nonzero count.');
|
|
error('Invalid data.');
|
|
end
|
|
end |