% FUNCTION [M, SIZE_M] = READ_MATRIX(P)
% FUNCTION [M, SIZE_M] = READ_MATRIX(FILENAME)
%
% Note: I/O in little endian format.
% Notw: header activated by default.
%
% EXAMPLE WITHOUT HEADER:
%
%   m = randn([5 4 3])
%   p.name = 'm.matrix';
%   p.header = 0;    % Without header
%   write_matrix(m,p);
%
%   p.size = [5 4 Inf];
%   [n, size_n] = read_matrix(p);
%   m-n, size_n
%
%
% EXAMPLE WITH HEADER:
%
%   m = randn([5 4 3])
%   p.name = 'm.matrix';
%   p.header = 1;    % With header
%   write_matrix(m,p);
%
%   [n, size_n] = read_matrix(p);
%   m-n, size_n
%
% by Guillaume LATHOUD at IDIAP (lathoud@idiap.ch)

function [m, size_m] = read_matrix(p_or_filename)

  if ischar( p_or_filename )
    p = [];
    p.name = p_or_filename;
  else
    p = p_or_filename;
  end
  
% parameters

if nargin < 1
  error('read_matrix needs one parameters');
end

required_fields = { 'name' };
check_param(required_fields, fieldnames(p));

p_default.verbose = 1;
p_default.header = 1;
p_default.type = 'float64';
p_default.size = [];
p_default.dir  = '';
p = fill_default(p, p_default);

% verbosity
if p.verbose
  p
end

% check something
if (isempty(p.size) & ~p.header) | (~isempty(p.size) & p.header)
  error('read_matrix needs either p.header=true or p.size.');
end

% open file

f_in = fullfile(p.dir, p.name);
fid_in = fopen(f_in, 'r', 'l');
if fid_in < 0
  error(['read_matrix could not read-open ' f_in]);
end

% read header if asked for it

if p.header
  [p.type, p.size] = read_matrix_header(fid_in);
end

% read data

if prod(p.size) < Inf
  m = fread(fid_in, prod(p.size), p.type);
  m = reshape(m, p.size);
else
  if length(p.size) < 2
    m = fread(fid_in, Inf, p.type);
  else
    aux = prod(p.size(1:end-1));
    [m, count] = fread(fid_in, [aux Inf], p.type);
    
    if rem(count, aux) ~= 0
      error(['read_matrix finished reading an uncomplete column.' ...
	     ' Check you specified the right type.'])
    end
    
    p.size(end) = count/aux;
    m = reshape(m, p.size);
  end
end

% close

fclose(fid_in);

% Reduce size if possible
if strcmp( p.type, 'uint8' )
  m = uint8( m );

elseif strcmp( p.type, 'uint16' )
  m = uint16( m );

elseif strcmp( p.type, 'uint32' )
  m = uint32( m );

elseif strcmp( p.type, 'int8' )
  m = int8( m );

elseif strcmp( p.type, 'int16' )
  m = int16( m );

elseif strcmp( p.type, 'int32' )
  m = int32( m );

end  

% return

size_m = size(m);
