6
6
// option. This file may not be copied, modified, or distributed
7
7
// except according to those terms.
8
8
9
+ use std:: mem:: { size_of, ManuallyDrop } ;
9
10
use alloc:: slice;
10
11
use alloc:: vec;
11
12
use alloc:: vec:: Vec ;
@@ -1583,8 +1584,11 @@ where
1583
1584
}
1584
1585
}
1585
1586
1586
- /// Convert an array or array view to another with the same type, but
1587
- /// different dimensionality type. Errors if the dimensions don't agree.
1587
+ /// Convert an array or array view to another with the same type, but different dimensionality
1588
+ /// type. Errors if the dimensions don't agree (the number of axes must match).
1589
+ ///
1590
+ /// Note that conversion to a dynamic dimensional array will never fail (and is equivalent to
1591
+ /// the `into_dyn` method).
1588
1592
///
1589
1593
/// ```
1590
1594
/// use ndarray::{ArrayD, Ix2, IxDyn};
@@ -1600,15 +1604,29 @@ where
1600
1604
where
1601
1605
D2 : Dimension ,
1602
1606
{
1603
- if let Some ( dim) = D2 :: from_dimension ( & self . dim ) {
1604
- if let Some ( strides) = D2 :: from_dimension ( & self . strides ) {
1607
+ if D :: NDIM == D2 :: NDIM {
1608
+ // safe because D == D2
1609
+ unsafe {
1610
+ let dim = unlimited_transmute :: < D , D2 > ( self . dim ) ;
1611
+ let strides = unlimited_transmute :: < D , D2 > ( self . strides ) ;
1605
1612
return Ok ( ArrayBase {
1606
1613
data : self . data ,
1607
1614
ptr : self . ptr ,
1608
1615
dim,
1609
1616
strides,
1610
1617
} ) ;
1611
1618
}
1619
+ } else if D :: NDIM == None || D2 :: NDIM == None { // one is dynamic dim
1620
+ if let Some ( dim) = D2 :: from_dimension ( & self . dim ) {
1621
+ if let Some ( strides) = D2 :: from_dimension ( & self . strides ) {
1622
+ return Ok ( ArrayBase {
1623
+ data : self . data ,
1624
+ ptr : self . ptr ,
1625
+ dim,
1626
+ strides,
1627
+ } ) ;
1628
+ }
1629
+ }
1612
1630
}
1613
1631
Err ( ShapeError :: from_kind ( ErrorKind :: IncompatibleShape ) )
1614
1632
}
@@ -2375,3 +2393,18 @@ where
2375
2393
} ) ;
2376
2394
}
2377
2395
}
2396
+
2397
+
2398
+ /// Transmute from A to B.
2399
+ ///
2400
+ /// Like transmute, but does not have the compile-time size check which blocks
2401
+ /// using regular transmute in some cases.
2402
+ ///
2403
+ /// **Panics** if the size of A and B are different.
2404
+ #[ inline]
2405
+ unsafe fn unlimited_transmute < A , B > ( data : A ) -> B {
2406
+ // safe when sizes are equal and caller guarantees that representations are equal
2407
+ assert_eq ! ( size_of:: <A >( ) , size_of:: <B >( ) ) ;
2408
+ let old_data = ManuallyDrop :: new ( data) ;
2409
+ ( & * old_data as * const A as * const B ) . read ( )
2410
+ }
0 commit comments