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