@@ -1336,91 +1336,65 @@ int b2nd_concatenate(b2nd_context_t *ctx, b2nd_array_t **array, const b2nd_array
13361336 BLOSC_ERROR_NULL (src2 , BLOSC2_ERROR_NULL_POINTER );
13371337 BLOSC_ERROR_NULL (array , BLOSC2_ERROR_NULL_POINTER );
13381338
1339- ctx -> ndim = src1 -> ndim ;
1340- // Compute the new shape while checking that the shapes are compatible with the other axes
1339+ // For starters, create a copy of src1 array
1340+ BLOSC_ERROR (b2nd_copy (ctx , src1 , array ));
1341+
1342+ // Check that the shapes are compatible for concatenation
1343+ if (src1 -> ndim != src2 -> ndim ) {
1344+ BLOSC_TRACE_ERROR ("The two arrays must have the same number of dimensions" );
1345+ BLOSC_ERROR (BLOSC2_ERROR_INVALID_PARAM );
1346+ }
1347+ // Compute the new shape
1348+ int64_t newshape [B2ND_MAX_DIM ];
13411349 for (int i = 0 ; i < src1 -> ndim ; ++ i ) {
13421350 if (i == axis ) {
1343- ctx -> shape [i ] = src1 -> shape [i ] + src2 -> shape [i ];
1351+ newshape [i ] = src1 -> shape [i ] + src2 -> shape [i ];
13441352 } else {
13451353 if (src1 -> shape [i ] != src2 -> shape [i ]) {
1346- BLOSC_TRACE_ERROR ("The shapes of the arrays are not compatible in axis %d" , i );
1354+ BLOSC_TRACE_ERROR ("The two arrays must have the same shape in all dimensions except the concatenation axis" );
13471355 BLOSC_ERROR (BLOSC2_ERROR_INVALID_PARAM );
13481356 }
1349- ctx -> shape [i ] = src1 -> shape [i ];
1357+ newshape [i ] = src1 -> shape [i ];
13501358 }
13511359 }
13521360
1353- // Use the same chunkshape and blockshape as src1
1354- for (int i = 0 ; i < src1 -> ndim ; ++ i ) {
1355- ctx -> chunkshape [i ] = src1 -> chunkshape [i ];
1356- ctx -> blockshape [i ] = src1 -> blockshape [i ];
1357- }
1358-
1359- // Create a container for the new array
1360- BLOSC_ERROR (b2nd_empty (ctx , array ));
1361+ // Extend the array, we don't need to specify the start in resize, as we are extending the shape from the end
1362+ BLOSC_ERROR (b2nd_resize (* array , newshape , NULL ));
13611363
1362- // Copy the data from the first array
1364+ // Copy the data from the second array
13631365 int64_t start [B2ND_MAX_DIM ] = {0 };
13641366 int64_t stop [B2ND_MAX_DIM ];
1365- for (int i = 0 ; i < src1 -> ndim ; ++ i ) {
1366- stop [i ] = src1 -> shape [i ];
1367- }
1368- // Copy src1 data chunk by chunk
1369- void * buffer = malloc (src1 -> sc -> typesize * src1 -> extchunknitems );
1370- BLOSC_ERROR_NULL (buffer , BLOSC2_ERROR_MEMORY_ALLOC );
1371- for (int64_t nchunk = 0 ; nchunk < src1 -> sc -> nchunks ; ++ nchunk ) {
1372- BLOSC_ERROR (blosc2_schunk_decompress_chunk (src1 -> sc , nchunk , buffer ,
1373- src1 -> sc -> typesize * src1 -> extchunknitems ));
1374- BLOSC_ERROR (b2nd_set_slice_cbuffer (buffer , src1 -> chunkshape , src1 -> sc -> typesize * src1 -> extchunknitems ,
1375- start , stop , * array ));
1376- }
1377- free (buffer );
1378-
1379- // Copy the data from the second array
1380- for (int i = 0 ; i < src2 -> ndim ; ++ i ) {
1381- if (i == axis ) {
1382- start [i ] = src1 -> shape [i ];
1383- stop [i ] = start [i ] + src2 -> shape [i ];
1384- } else {
1385- start [i ] = 0 ;
1386- stop [i ] = src2 -> shape [i ];
1387- }
1388- }
1389- // Copy src2 data chunk by chunk
1390- buffer = malloc (src2 -> sc -> typesize * src2 -> extchunknitems );
1367+ // Copy chunk by chunk
1368+ void * buffer = malloc (src2 -> sc -> typesize * src2 -> extchunknitems );
13911369 BLOSC_ERROR_NULL (buffer , BLOSC2_ERROR_MEMORY_ALLOC );
13921370 for (int64_t nchunk = 0 ; nchunk < src2 -> sc -> nchunks ; ++ nchunk ) {
13931371 BLOSC_ERROR (blosc2_schunk_decompress_chunk (src2 -> sc , nchunk , buffer ,
13941372 src2 -> sc -> typesize * src2 -> extchunknitems ));
1395- BLOSC_ERROR (b2nd_set_slice_cbuffer (buffer , src2 -> chunkshape , src2 -> sc -> typesize * src2 -> extchunknitems ,
1396- start , stop , * array ));
1397- }
1398- free (buffer );
1373+ // Get multidimensional chunk position
1374+ int64_t nchunk_ndim [B2ND_MAX_DIM ] = {0 };
1375+ blosc2_unidim_to_multidim (src2 -> ndim , src2 -> chunkshape , nchunk , nchunk_ndim );
1376+
1377+ // Set positions for each dimension
1378+ for (int i = 0 ; i < src2 -> ndim ; ++ i ) {
1379+ start [i ] = nchunk_ndim [i ] * src2 -> chunkshape [i ];
1380+ stop [i ] = start [i ] + src2 -> chunkshape [i ];
1381+ if (stop [i ] > src2 -> shape [i ]) {
1382+ stop [i ] = src2 -> shape [i ]; // Handle boundary chunks
1383+ }
13991384
1400- // Copy the metalayers from src1
1401- blosc2_storage * b2_storage = ctx -> b2_storage ;
1402- blosc2_schunk * schunk = src1 -> sc ;
1403- blosc2_schunk * new_schunk = (* array )-> sc ;
1404- for (int nmeta = 0 ; nmeta < schunk -> nmetalayers ; ++ nmeta ) {
1405- blosc2_metalayer * meta = schunk -> metalayers [nmeta ];
1406- if (blosc2_meta_add (new_schunk , meta -> name , meta -> content , meta -> content_len ) < 0 ) {
1407- BLOSC_TRACE_ERROR ("Can not add %s `metalayer`." , meta -> name );
1408- return BLOSC2_ERROR_FAILURE ;
1385+ // Apply offset only for concatenation axis
1386+ if (i == axis ) {
1387+ start [i ] += src1 -> shape [i ];
1388+ stop [i ] += src1 -> shape [i ];
1389+ }
14091390 }
1410- }
14111391
1412- // Copy the vlmetalayers from src1
1413- for (int nvlmeta = 0 ; nvlmeta < schunk -> nvlmetalayers ; ++ nvlmeta ) {
1414- uint8_t * content ;
1415- int32_t content_len ;
1416- if (blosc2_vlmeta_get (schunk , schunk -> vlmetalayers [nvlmeta ]-> name , & content ,
1417- & content_len ) < 0 ) {
1418- BLOSC_ERROR (BLOSC2_ERROR_FAILURE );
1419- }
1420- BLOSC_ERROR (blosc2_vlmeta_add (new_schunk , schunk -> vlmetalayers [nvlmeta ]-> name , content ,
1421- content_len , b2_storage -> cparams ));
1422- free (content );
1392+ // Copy the chunk to the correct position
1393+ BLOSC_ERROR (b2nd_set_slice_cbuffer (buffer , src2 -> chunkshape ,
1394+ src2 -> sc -> typesize * src2 -> extchunknitems ,
1395+ start , stop , * array ));
14231396 }
1397+ free (buffer );
14241398
14251399 return BLOSC2_ERROR_SUCCESS ;
14261400}
0 commit comments