Skip to content

Commit 7e29c45

Browse files
fangqclaude
andcommitted
[jdata4] fix complex array chunking (1D and ND)
- jdataencode: ND chunking of complex tiles now serialises [real(chunk(:))', imag(chunk(:))'] instead of typecast on the raw complex buffer (which was platform-dependent) - jdatadecode: 1D chunked path restored _ArrayZipSize_ to [1,2N] instead of [2,N], breaking complex(row1,row2) reconstruction; now sets [2, N/2] when _ArrayIsComplex_ is present - jdatadecode: ND chunked path allocates a complex intermediate array, fills real+imag halves per tile, then emits flat [re…,im…] buffer with correct _ArrayZipSize_ = [2, N] - test: add 8 tests covering 1D and ND chunking of complex arrays, both direct decode and roundtrip via savejson/loadjson Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent bf5a3bd commit 7e29c45

3 files changed

Lines changed: 63 additions & 6 deletions

File tree

jdatadecode.m

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,12 @@
284284
ndim = numel(arrsize);
285285
nchunks_nd = ceil(arrsize ./ chunkshape);
286286
ntiles = prod(nchunks_nd);
287-
ndata = cast(zeros(arrsize), arraytype);
287+
iscpx_arr = isfield(data, N_ArrayIsComplex) && data(j).(N_ArrayIsComplex);
288+
if (iscpx_arr)
289+
ndata = complex(cast(zeros(arrsize), arraytype));
290+
else
291+
ndata = cast(zeros(arrsize), arraytype);
292+
end
288293
tidx = cell(1, ndim);
289294
for ci = 1:ntiles
290295
[tidx{:}] = ind2sub(nchunks_nd, ci);
@@ -301,12 +306,26 @@
301306
ranges{d} = r1:r2;
302307
tilesize(d) = r2 - r1 + 1;
303308
end
304-
ndata(ranges{:}) = reshape(rawchunk, tilesize);
309+
if (iscpx_arr)
310+
half = numel(rawchunk) / 2;
311+
ndata(ranges{:}) = complex(reshape(rawchunk(1:half), tilesize), ...
312+
reshape(rawchunk(half + 1:end), tilesize));
313+
else
314+
ndata(ranges{:}) = reshape(rawchunk, tilesize);
315+
end
316+
end
317+
if (iscpx_arr)
318+
ndata = [real(ndata(:))', imag(ndata(:))'];
319+
else
320+
ndata = ndata(:).';
305321
end
306-
ndata = ndata(:).'; % flatten to row, same layout as 1-D path
307322
end
308-
% Set ZipSize to flat row so downstream _ArraySize_ reshape works
309-
data(j).(N_ArrayZipSize) = [1, numel(ndata)];
323+
% Restore ZipSize for downstream complex reconstruction
324+
if (isfield(data, N_ArrayIsComplex) && data(j).(N_ArrayIsComplex))
325+
data(j).(N_ArrayZipSize) = [2, numel(ndata) / 2];
326+
else
327+
data(j).(N_ArrayZipSize) = [1, numel(ndata)];
328+
end
310329
dims = data(j).(N_ArrayZipSize);
311330
elseif (needbase64 && strcmp(zipmethod, 'base64') == 0)
312331
ndata = reshape(typecast(decompfun(base64decode(data(j).(N_ArrayZipData)), decodeparam{:}), arraytype), dims);

jdataencode.m

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -530,7 +530,12 @@
530530
ranges{d} = r1:r2;
531531
end
532532
chunk = item(ranges{:});
533-
zipchunks{ci} = compfun(typecast(chunk(:)', 'uint8'), encodeparam{:});
533+
if (~isreal(item))
534+
chunk_flat = [real(chunk(:))', imag(chunk(:))'];
535+
zipchunks{ci} = compfun(typecast(chunk_flat, 'uint8'), encodeparam{:});
536+
else
537+
zipchunks{ci} = compfun(typecast(chunk(:)', 'uint8'), encodeparam{:});
538+
end
534539
if (opt.base64)
535540
zipchunks{ci} = char(base64encode(zipchunks{ci}));
536541
end

test/run_jsonlab_test.m

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4659,6 +4659,39 @@ function run_jsonlab_test(tests)
46594659
dec_nd_json = jdatadecode(loadjson(savejson('', enc_nd_json, 'compact', 1)));
46604660
test_jsonlab('nd chunks roundtrip via savejson/loadjson', @savejson, isequaln(dec_nd_json, big3d), '[true]', 'compact', 1);
46614661

4662+
%% --- _ArrayChunks_ with complex arrays ---
4663+
% 1-D chunking of a complex matrix (compressarraysize=1 forces compression on small arrays)
4664+
cpx2d = complex(reshape(1:12, 3, 4), reshape(101:112, 3, 4));
4665+
enc_cpx1d = jdataencode(cpx2d, 'formatversion', 4, 'compression', 'zlib', ...
4666+
'arraychunks', 8, 'base64', 1, 'prefix', 'x', 'compressarraysize', 1);
4667+
test_jsonlab('complex 1d chunks field exists', @savejson, isfield(enc_cpx1d, 'x_ArrayIsComplex_'), '[true]', 'compact', 1);
4668+
test_jsonlab('complex 1d chunks chunklen', @savejson, enc_cpx1d.x_ArrayChunks_, '[8]', 'compact', 1);
4669+
dec_cpx1d = jdatadecode(enc_cpx1d, 'base64', 1, 'prefix', 'x');
4670+
test_jsonlab('complex 1d chunks roundtrip', @savejson, isequaln(dec_cpx1d, cpx2d), '[true]', 'compact', 1);
4671+
4672+
% roundtrip via savejson/loadjson
4673+
enc_cpx1d_json = jdataencode(cpx2d, 'formatversion', 4, 'compression', 'zlib', ...
4674+
'arraychunks', 8, 'base64', 1, 'compressarraysize', 1);
4675+
dec_cpx1d_json = jdatadecode(loadjson(savejson('', enc_cpx1d_json, 'compact', 1)));
4676+
test_jsonlab('complex 1d chunks roundtrip via savejson/loadjson', @savejson, isequaln(dec_cpx1d_json, cpx2d), '[true]', 'compact', 1);
4677+
4678+
% N-D chunking of a complex 3-D array
4679+
cpx3d = complex(single(reshape(1:60, 3, 4, 5)), single(reshape(101:160, 3, 4, 5)));
4680+
enc_cpxnd = jdataencode(cpx3d, 'formatversion', 4, 'compression', 'zlib', ...
4681+
'arraychunks', [3, 3, 3], 'base64', 1, 'prefix', 'x', 'compressarraysize', 1);
4682+
test_jsonlab('complex nd chunks field exists', @savejson, isfield(enc_cpxnd, 'x_ArrayIsComplex_'), '[true]', 'compact', 1);
4683+
test_jsonlab('complex nd chunks chunkshape', @savejson, isequal(enc_cpxnd.x_ArrayChunks_, [3, 3, 3]), '[true]', 'compact', 1);
4684+
dec_cpxnd = jdatadecode(enc_cpxnd, 'base64', 1, 'prefix', 'x');
4685+
test_jsonlab('complex nd chunks roundtrip', @savejson, isequaln(dec_cpxnd, cpx3d), '[true]', 'compact', 1);
4686+
4687+
enc_cpxnd_json = jdataencode(cpx3d, 'formatversion', 4, 'compression', 'zlib', ...
4688+
'arraychunks', [3, 3, 3], 'base64', 1, 'compressarraysize', 1);
4689+
dec_cpxnd_json = jdatadecode(loadjson(savejson('', enc_cpxnd_json, 'compact', 1)));
4690+
test_jsonlab('complex nd chunks roundtrip via savejson/loadjson', @savejson, isequaln(dec_cpxnd_json, cpx3d), '[true]', 'compact', 1);
4691+
4692+
clear cpx2d enc_cpx1d dec_cpx1d enc_cpx1d_json dec_cpx1d_json;
4693+
clear cpx3d enc_cpxnd dec_cpxnd enc_cpxnd_json dec_cpxnd_json;
4694+
46624695
clear big3d enc_ch enc_ch2 enc_ch3 enc_v2_ch enc_ch_json dec_ch dec_ch2 dec_ch3 dec_ch_json;
46634696
clear enc_nd dec_nd enc_nd_json dec_nd_json;
46644697
clear circ_enc circ_enc2 circ_ref circ_ref2 hank_enc hank_enc2 hank_ref hank_ref2;

0 commit comments

Comments
 (0)