@@ -252,7 +252,7 @@ impl<A, D> Array<A, D>
252
252
/// [1., 1., 1., 1.],
253
253
/// [1., 1., 1., 1.]]);
254
254
/// ```
255
- pub fn try_append_array ( & mut self , axis : Axis , array : ArrayView < A , D > )
255
+ pub fn try_append_array ( & mut self , axis : Axis , mut array : ArrayView < A , D > )
256
256
-> Result < ( ) , ShapeError >
257
257
where
258
258
A : Clone ,
@@ -312,7 +312,7 @@ impl<A, D> Array<A, D>
312
312
// make a raw view with the new row
313
313
// safe because the data was "full"
314
314
let tail_ptr = self . data . as_end_nonnull ( ) ;
315
- let tail_view = RawArrayViewMut :: new ( tail_ptr, array_shape, strides. clone ( ) ) ;
315
+ let mut tail_view = RawArrayViewMut :: new ( tail_ptr, array_shape, strides. clone ( ) ) ;
316
316
317
317
struct SetLenOnDrop < ' a , A : ' a > {
318
318
len : usize ,
@@ -332,37 +332,86 @@ impl<A, D> Array<A, D>
332
332
}
333
333
}
334
334
335
- // we have a problem here XXX
336
- //
337
335
// To be robust for panics and drop the right elements, we want
338
336
// to fill the tail in-order, so that we can drop the right elements on
339
- // panic. Don't know how to achieve that.
337
+ // panic.
340
338
//
341
- // It might be easier to retrace our steps in a scope guard to drop the right
342
- // elements.. (PartialArray style).
339
+ // We have: Zip::from(tail_view).and(array)
340
+ // Transform tail_view into standard order by inverting and moving its axes.
341
+ // Keep the Zip traversal unchanged by applying the same axis transformations to
342
+ // `array`. This ensures the Zip traverses the underlying memory in order.
343
343
//
344
- // assign the new elements
344
+ // XXX It would be possible to skip this transformation if the element
345
+ // doesn't have drop. However, in the interest of code coverage, all elements
346
+ // use this code initially.
347
+
348
+ if tail_view. ndim ( ) > 1 {
349
+ for i in 0 ..tail_view. ndim ( ) {
350
+ if tail_view. stride_of ( Axis ( i) ) < 0 {
351
+ tail_view. invert_axis ( Axis ( i) ) ;
352
+ array. invert_axis ( Axis ( i) ) ;
353
+ }
354
+ }
355
+ sort_axes_to_standard_order ( & mut tail_view, & mut array) ;
356
+ }
345
357
Zip :: from ( tail_view) . and ( array)
358
+ . debug_assert_c_order ( )
346
359
. for_each ( |to, from| {
347
360
to. write ( from. clone ( ) ) ;
348
361
length_guard. len += 1 ;
349
362
} ) ;
350
363
351
- //length_guard.len += len_to_append;
352
- dbg ! ( len_to_append) ;
353
364
drop ( length_guard) ;
354
365
355
366
// update array dimension
356
367
self . strides = strides;
357
368
self . dim = res_dim;
358
- dbg ! ( & self . dim) ;
359
-
360
369
}
361
370
// multiple assertions after pointer & dimension update
362
371
debug_assert_eq ! ( self . data. len( ) , self . len( ) ) ;
363
372
debug_assert_eq ! ( self . len( ) , new_len) ;
364
- debug_assert ! ( self . is_standard_layout( ) ) ;
365
373
366
374
Ok ( ( ) )
367
375
}
368
376
}
377
+
378
+ fn sort_axes_to_standard_order < S , S2 , D > ( a : & mut ArrayBase < S , D > , b : & mut ArrayBase < S2 , D > )
379
+ where
380
+ S : RawData ,
381
+ S2 : RawData ,
382
+ D : Dimension ,
383
+ {
384
+ if a. ndim ( ) <= 1 {
385
+ return ;
386
+ }
387
+ sort_axes_impl ( & mut a. dim , & mut a. strides , & mut b. dim , & mut b. strides ) ;
388
+ debug_assert ! ( a. is_standard_layout( ) ) ;
389
+ }
390
+
391
+ fn sort_axes_impl < D > ( adim : & mut D , astrides : & mut D , bdim : & mut D , bstrides : & mut D )
392
+ where
393
+ D : Dimension ,
394
+ {
395
+ debug_assert ! ( adim. ndim( ) > 1 ) ;
396
+ debug_assert_eq ! ( adim. ndim( ) , bdim. ndim( ) ) ;
397
+ // bubble sort axes
398
+ let mut changed = true ;
399
+ while changed {
400
+ changed = false ;
401
+ for i in 0 ..adim. ndim ( ) - 1 {
402
+ let axis_i = i;
403
+ let next_axis = i + 1 ;
404
+
405
+ // make sure higher stride axes sort before.
406
+ debug_assert ! ( astrides. slice( ) [ axis_i] as isize >= 0 ) ;
407
+ if ( astrides. slice ( ) [ axis_i] as isize ) < astrides. slice ( ) [ next_axis] as isize {
408
+ changed = true ;
409
+ adim. slice_mut ( ) . swap ( axis_i, next_axis) ;
410
+ astrides. slice_mut ( ) . swap ( axis_i, next_axis) ;
411
+ bdim. slice_mut ( ) . swap ( axis_i, next_axis) ;
412
+ bstrides. slice_mut ( ) . swap ( axis_i, next_axis) ;
413
+ }
414
+ }
415
+ }
416
+ }
417
+
0 commit comments