diff --git a/AUTHORS.txt b/AUTHORS.txt index 1a6a06baec5585280904fac64424442d8588432a..80446a891155012e9f0c8ed615ba6c9b1e120fe1 100644 --- a/AUTHORS.txt +++ b/AUTHORS.txt @@ -25,3 +25,12 @@ This toolbox contains patches submitted by the following contributors: - Blake Johnson <bjohnso at bbn.com> part of revision 341 +- Niclas Borlin <Niclas.Borlin at cs.umu.se> + various fixes in revision 394, including + - loadjson crashes for all-zero sparse matrix. + - loadjson crashes for empty sparse matrix. + - Non-zero size of 0-by-N and N-by-0 empty matrices is lost after savejson/loadjson. + - loadjson crashes for sparse real column vector. + - loadjson crashes for sparse complex column vector. + - Data is corrupted by savejson for sparse real row vector. + - savejson crashes for sparse complex row vector. diff --git a/examples/demo_jsonlab_basic.m b/examples/demo_jsonlab_basic.m index 75128d5025075b64a265014b3bf80096c196a4aa..d094a64ee5eaf77eb3c629e75e65d6b2868ec7b5 100644 --- a/examples/demo_jsonlab_basic.m +++ b/examples/demo_jsonlab_basic.m @@ -56,6 +56,70 @@ data2json=data2json-data2json*i savejson('complex_sparse',data2json) json2data=loadjson(ans) +fprintf(1,'\n%%=================================================\n') +fprintf(1,'%% an all-zero sparse matrix\n') +fprintf(1,'%%=================================================\n\n') + +data2json=sparse(2,3); +savejson('all_zero_sparse',data2json) +json2data=loadjson(ans) + +fprintf(1,'\n%%=================================================\n') +fprintf(1,'%% an empty sparse matrix\n') +fprintf(1,'%%=================================================\n\n') + +data2json=sparse([]); +savejson('empty_sparse',data2json) +json2data=loadjson(ans) + +fprintf(1,'\n%%=================================================\n') +fprintf(1,'%% an empty 0-by-0 real matrix\n') +fprintf(1,'%%=================================================\n\n') + +data2json=[]; +savejson('empty_0by0_real',data2json) +json2data=loadjson(ans) + +fprintf(1,'\n%%=================================================\n') +fprintf(1,'%% an empty 0-by-3 real matrix\n') +fprintf(1,'%%=================================================\n\n') + +data2json=zeros(0,3); +savejson('empty_0by3_real',data2json) +json2data=loadjson(ans) + +fprintf(1,'\n%%=================================================\n') +fprintf(1,'%% a sparse real column vector\n') +fprintf(1,'%%=================================================\n\n') + +data2json=sparse([0,3,0,1,4]'); +savejson('sparse_column_vector',data2json) +json2data=loadjson(ans) + +fprintf(1,'\n%%=================================================\n') +fprintf(1,'%% a sparse complex column vector\n') +fprintf(1,'%%=================================================\n\n') + +data2json=data2json-1i*data2json; +savejson('complex_sparse_column_vector',data2json) +json2data=loadjson(ans) + +fprintf(1,'\n%%=================================================\n') +fprintf(1,'%% a sparse real row vector\n') +fprintf(1,'%%=================================================\n\n') + +data2json=sparse([0,3,0,1,4]); +savejson('sparse_row_vector',data2json) +json2data=loadjson(ans) + +fprintf(1,'\n%%=================================================\n') +fprintf(1,'%% a sparse complex row vector\n') +fprintf(1,'%%=================================================\n\n') + +data2json=data2json-1i*data2json; +savejson('complex_sparse_row_vector',data2json) +json2data=loadjson(ans) + fprintf(1,'\n%%=================================================\n') fprintf(1,'%% a structure\n') fprintf(1,'%%=================================================\n\n') diff --git a/loadjson.m b/loadjson.m index 4563b8052e8f60764403e4a627b868219914bb50..2dfcd27f257c2df39591cc2e3ae1aaf736637d50 100644 --- a/loadjson.m +++ b/loadjson.m @@ -133,13 +133,28 @@ if(~isempty(strmatch('x0x5F_ArrayType_',fn)) && ~isempty(strmatch('x0x5F_ArrayDa end if(~isempty(strmatch('x0x5F_ArrayIsSparse_',fn))) if(data(j).x0x5F_ArrayIsSparse_) - if(iscpx && size(ndata,2)==4) - ndata(:,3)=complex(ndata(:,3),ndata(:,4)); - end if(~isempty(strmatch('x0x5F_ArraySize_',fn))) dim=data(j).x0x5F_ArraySize_; - ndata=sparse(ndata(:,1),ndata(:,2),ndata(:,3),dim(1),prod(dim(2:end))); + if(iscpx && size(ndata,2)==4-any(dim==1)) + ndata(:,end-1)=complex(ndata(:,end-1),ndata(:,end)); + end + if isempty(ndata) + % All-zeros sparse + ndata=sparse(dim(1),prod(dim(2:end))); + elseif dim(1)==1 + % Sparse row vector + ndata=sparse(1,ndata(:,1),ndata(:,2),dim(1),prod(dim(2:end))); + elseif dim(2)==1 + % Sparse column vector + ndata=sparse(ndata(:,1),1,ndata(:,2),dim(1),prod(dim(2:end))); + else + % Generic sparse array. + ndata=sparse(ndata(:,1),ndata(:,2),ndata(:,3),dim(1),prod(dim(2:end))); + end else + if(iscpx && size(ndata,2)==4) + ndata(:,3)=complex(ndata(:,3),ndata(:,4)); + end ndata=sparse(ndata(:,1),ndata(:,2),ndata(:,3)); end end diff --git a/savejson.m b/savejson.m index f9da0a508232549e71e67ff8349002e88d9e99cb..31632723e032a99954b306753a40265ee0275d9f 100644 --- a/savejson.m +++ b/savejson.m @@ -255,7 +255,8 @@ end padding1=repmat(sprintf('\t'),1,level); padding0=repmat(sprintf('\t'),1,level+1); -if(length(size(item))>2 || issparse(item) || ~isreal(item) || jsonopt('ArrayToStruct',0,varargin{:})) +if(length(size(item))>2 || issparse(item) || ~isreal(item) || ... + isempty(item) ||jsonopt('ArrayToStruct',0,varargin{:})) if(isempty(name)) txt=sprintf('%s{\n%s"_ArrayType_": "%s",\n%s"_ArraySize_": %s,\n',... padding1,padding0,class(item),padding0,regexprep(mat2str(size(item)),'\s+',',') ); @@ -283,13 +284,24 @@ if(issparse(item)) data=full(item(find(item))); if(~isreal(item)) data=[real(data(:)),imag(data(:))]; + if(size(item,1)==1) + % Kludge to have data's 'transposedness' match item's. + % (Necessary for complex row vector handling below.) + data=data'; + end txt=sprintf(dataformat,txt,padding0,'"_ArrayIsComplex_": ','1', sprintf(',\n')); end txt=sprintf(dataformat,txt,padding0,'"_ArrayIsSparse_": ','1', sprintf(',\n')); - if(find(size(item)==1)) + if(size(item,1)==1) + % Row vector, store only column indices. + txt=sprintf(dataformat,txt,padding0,'"_ArrayData_": ',... + matdata2json([iy(:),data'],level+2,varargin{:}), sprintf('\n')); + elseif(size(item,2)==1) + % Column vector, store only row indices. txt=sprintf(dataformat,txt,padding0,'"_ArrayData_": ',... matdata2json([ix,data],level+2,varargin{:}), sprintf('\n')); else + % General case, store row and column indices. txt=sprintf(dataformat,txt,padding0,'"_ArrayData_": ',... matdata2json([ix,iy,data],level+2,varargin{:}), sprintf('\n')); end