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