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