@@ -16,6 +16,7 @@ use crate::imp_prelude::*;
16
16
17
17
use crate :: { arraytraits, DimMax } ;
18
18
use crate :: argument_traits:: AssignElem ;
19
+ use crate :: data_traits:: IfOwnedCb ;
19
20
use crate :: dimension;
20
21
use crate :: dimension:: IntoDimension ;
21
22
use crate :: dimension:: {
@@ -1646,18 +1647,7 @@ where
1646
1647
}
1647
1648
let layout = self . layout_impl ( ) ;
1648
1649
if order == Order :: Automatic {
1649
- // the order of the conditionals is significant for preference
1650
- if layout. is ( Layout :: CORDER ) {
1651
- order = Order :: RowMajor ;
1652
- } else if layout. is ( Layout :: FORDER ) {
1653
- order = Order :: ColumnMajor ;
1654
- } else if layout. is ( Layout :: CPREFER ) {
1655
- order = Order :: RowMajor ;
1656
- } else if layout. is ( Layout :: FPREFER ) {
1657
- order = Order :: ColumnMajor ;
1658
- } else {
1659
- order = Order :: RowMajor ;
1660
- }
1650
+ order = preferred_order_for_layout ( layout) ;
1661
1651
}
1662
1652
1663
1653
unsafe {
@@ -1682,43 +1672,183 @@ where
1682
1672
}
1683
1673
}
1684
1674
1685
- /// Transform the array into `shape`; any shape with the same number of
1686
- /// elements is accepted, but the source array or view must be in standard
1687
- /// or column-major (Fortran) layout.
1675
+ /// Transform the array into `shape`; any shape with the same number of elements is accepted,
1676
+ /// but the source array or view must be in contiguous and stored in standard row-major (C) or
1677
+ /// column-major (Fortran) memory order.
1678
+ ///
1679
+ /// **Warning:** this method will automatically decide which ordering (row-major or
1680
+ /// column-major) to use for rearranging the elements. Use `as_shape` if more
1681
+ /// control is needed. Note that one-dimensional contiguous arrays will be regarded
1682
+ /// as row major.
1688
1683
///
1689
- /// **Errors** if the shapes don't have the same number of elements.<br>
1690
- /// **Errors** if the input array is not c- or f-contiguous.
1684
+ /// **Errors** if the new shape doesn't have the same number of elements as the array's current
1685
+ /// shape.<br>
1686
+ /// **Errors** if the input array is not C- or F-contiguous.
1691
1687
///
1692
1688
/// ```
1693
- /// use ndarray::{aview1, aview2} ;
1689
+ /// use ndarray::array ;
1694
1690
///
1695
1691
/// assert!(
1696
- /// aview1(& [1., 2., 3., 4.]).into_shape ((2, 2)).unwrap()
1697
- /// == aview2(& [[1., 2.],
1698
- /// [3., 4.]])
1692
+ /// array! [1., 2., 3., 4.].coerce_shape_c ((2, 2)).unwrap()
1693
+ /// == array! [[1., 2.],
1694
+ /// [3., 4.]]
1699
1695
/// );
1700
1696
/// ```
1701
- pub fn into_shape < E > ( self , shape : E ) -> Result < ArrayBase < S , E :: Dim > , ShapeError >
1697
+ #[ deprecated( note="Replaced by one of `to_shape`, `coerce_shape_c`, `coerce_shape_f` \
1698
+ and `into_shape_owned`.", since="0.15.0" ) ]
1699
+ pub fn into_shape_ < E > ( self , shape : E ) -> Result < ArrayBase < S , E :: Dim > , ShapeError >
1700
+ where
1701
+ E : IntoDimension ,
1702
+ {
1703
+ self . coerce_shape_with_order ( shape, Order :: Automatic )
1704
+ }
1705
+
1706
+ /// Transform the array into `shape`; any shape with the same number of elements is accepted,
1707
+ /// but the source array or view must be contiguous and stored in standard row-major (C) memory
1708
+ /// order.
1709
+ ///
1710
+ /// This method allows any array, view or raw view and never copies elements.
1711
+ ///
1712
+ /// **Errors** if the new shape doesn't have the same number of elements as the array's current
1713
+ /// shape.<br>
1714
+ /// **Errors** if the input array is not C-contiguous.
1715
+ ///
1716
+ /// ```
1717
+ /// use ndarray::array;
1718
+ ///
1719
+ /// assert!(
1720
+ /// array![1., 2., 3., 4.].coerce_shape_c((2, 2)).unwrap()
1721
+ /// == array![[1., 2.],
1722
+ /// [3., 4.]]
1723
+ /// );
1724
+ /// ```
1725
+ pub fn coerce_shape_c < E > ( self , shape : E ) -> Result < ArrayBase < S , E :: Dim > , ShapeError >
1726
+ where
1727
+ E : IntoDimension ,
1728
+ {
1729
+ self . coerce_shape_with_order ( shape, Order :: RowMajor )
1730
+ }
1731
+
1732
+ /// Transform the array into `shape`; any shape with the same number of elements is accepted,
1733
+ /// but the source array or view must be contiguous and stored in column-major (F) memory
1734
+ /// order.
1735
+ ///
1736
+ /// This method allows any array, view or raw view and never copies elements.
1737
+ ///
1738
+ /// **Errors** if the new shape doesn't have the same number of elements as the array's current
1739
+ /// shape.<br>
1740
+ /// **Errors** if the input array is not F-contiguous.
1741
+ ///
1742
+ /// ```
1743
+ /// use ndarray::array;
1744
+ ///
1745
+ /// assert!(
1746
+ /// array![1., 2., 3., 4.].coerce_shape_f((2, 2)).unwrap()
1747
+ /// == array![[1., 3.],
1748
+ /// [2., 4.]]
1749
+ /// );
1750
+ /// ```
1751
+ pub fn coerce_shape_f < E > ( self , shape : E ) -> Result < ArrayBase < S , E :: Dim > , ShapeError >
1752
+ where
1753
+ E : IntoDimension ,
1754
+ {
1755
+ self . coerce_shape_with_order ( shape, Order :: ColumnMajor )
1756
+ }
1757
+
1758
+ fn coerce_shape_with_order < E > ( self , shape : E , mut order : Order )
1759
+ -> Result < ArrayBase < S , E :: Dim > , ShapeError >
1702
1760
where
1703
1761
E : IntoDimension ,
1704
1762
{
1705
1763
let shape = shape. into_dimension ( ) ;
1706
1764
if size_of_shape_checked ( & shape) != Ok ( self . dim . size ( ) ) {
1707
1765
return Err ( error:: incompatible_shapes ( & self . dim , & shape) ) ;
1708
1766
}
1709
- // Check if contiguous, if not => copy all, else just adapt strides
1767
+
1768
+ let layout = self . layout_impl ( ) ;
1769
+ if order == Order :: Automatic {
1770
+ order = preferred_order_for_layout ( layout) ;
1771
+ }
1772
+
1773
+ // safe because: the number of elements is preserved and it's contiguous
1710
1774
unsafe {
1711
- // safe because arrays are contiguous and len is unchanged
1712
- if self . is_standard_layout ( ) {
1775
+ if layout. is ( Layout :: CORDER ) && order == Order :: RowMajor {
1713
1776
Ok ( self . with_strides_dim ( shape. default_strides ( ) , shape) )
1714
- } else if self . ndim ( ) > 1 && self . raw_view ( ) . reversed_axes ( ) . is_standard_layout ( ) {
1777
+ } else if layout . is ( Layout :: FORDER ) && order == Order :: ColumnMajor {
1715
1778
Ok ( self . with_strides_dim ( shape. fortran_strides ( ) , shape) )
1716
1779
} else {
1717
1780
Err ( error:: from_kind ( error:: ErrorKind :: IncompatibleLayout ) )
1718
1781
}
1719
1782
}
1720
1783
}
1721
1784
1785
+ /// Transform the array into `new_shape`; any shape with the same number of elements is
1786
+ /// accepted.
1787
+ ///
1788
+ /// `order` specifies the *logical* order in which the array is to be read and reshaped. The
1789
+ /// input array must be an owned array. It is updated and returned if possible, otherwise
1790
+ /// elements are copied to be rearranged for the new shape and the new array returned.
1791
+ ///
1792
+ /// **Panics** if shapes are incompatible.
1793
+ ///
1794
+ /// **Errors** if the new shape doesn't have the same number of elements as the array's current
1795
+ /// shape.
1796
+ ///
1797
+ /// ```
1798
+ /// use ndarray::array;
1799
+ /// use ndarray::Order;
1800
+ ///
1801
+ /// assert!(
1802
+ /// array![1., 2., 3., 4., 5., 6.].into_shape((2, 3)).unwrap()
1803
+ /// == array![[1., 2., 3.],
1804
+ /// [4., 5., 6.]]
1805
+ /// );
1806
+ ///
1807
+ /// assert!(
1808
+ /// array![1., 2., 3., 4., 5., 6.].into_shape(((2, 3), Order::ColumnMajor)).unwrap()
1809
+ /// == array![[1., 3., 5.],
1810
+ /// [2., 4., 6.]]
1811
+ /// );
1812
+ /// ```
1813
+ pub fn into_shape < E > ( self , new_shape : E ) -> Result < ArrayBase < S , E :: Dim > , ShapeError >
1814
+ where
1815
+ E : ShapeArg < StrideType = Contiguous > ,
1816
+ {
1817
+ let ( new_shape, order) = new_shape. into_shape_and_order ( Order :: RowMajor ) ;
1818
+ self . into_shape_order ( new_shape, order)
1819
+ }
1820
+
1821
+ fn into_shape_order < E > ( self , shape : E , mut order : Order )
1822
+ -> Result < ArrayBase < S , E > , ShapeError >
1823
+ where
1824
+ E : Dimension ,
1825
+ {
1826
+ if size_of_shape_checked ( & shape) != Ok ( self . dim . size ( ) ) {
1827
+ return Err ( error:: incompatible_shapes ( & self . dim , & shape) ) ;
1828
+ }
1829
+
1830
+ let layout = self . layout_impl ( ) ;
1831
+ if order == Order :: Automatic {
1832
+ order = preferred_order_for_layout ( layout) ;
1833
+ }
1834
+
1835
+ // safe because: the number of elements is preserved and it's contiguous
1836
+ unsafe {
1837
+ if layout. is ( Layout :: CORDER ) && order == Order :: RowMajor {
1838
+ Ok ( self . with_strides_dim ( shape. default_strides ( ) , shape) )
1839
+ } else if layout. is ( Layout :: FORDER ) && order == Order :: ColumnMajor {
1840
+ Ok ( self . with_strides_dim ( shape. fortran_strides ( ) , shape) )
1841
+ } else {
1842
+ // Try to adapt shape as `Array` if applicable
1843
+ if let Some ( res) = S :: map_if_owned ( self , IntoShapeOwnedCb { order, shape } ) {
1844
+ res
1845
+ } else {
1846
+ Err ( error:: from_kind ( error:: ErrorKind :: IncompatibleLayout ) )
1847
+ }
1848
+ }
1849
+ }
1850
+ }
1851
+
1722
1852
/// *Note: Reshape is for `ArcArray` only. Use `.into_shape()` for
1723
1853
/// other arrays and array views.*
1724
1854
///
@@ -2651,7 +2781,6 @@ where
2651
2781
}
2652
2782
}
2653
2783
2654
-
2655
2784
/// Transmute from A to B.
2656
2785
///
2657
2786
/// Like transmute, but does not have the compile-time size check which blocks
@@ -2667,3 +2796,58 @@ unsafe fn unlimited_transmute<A, B>(data: A) -> B {
2667
2796
}
2668
2797
2669
2798
type DimMaxOf < A , B > = <A as DimMax < B > >:: Output ;
2799
+
2800
+ #[ inline]
2801
+ fn preferred_order_for_layout ( layout : Layout ) -> Order {
2802
+ // the order of the conditionals is significant for preference
2803
+ if layout. is ( Layout :: CORDER ) {
2804
+ Order :: RowMajor
2805
+ } else if layout. is ( Layout :: FORDER ) {
2806
+ Order :: ColumnMajor
2807
+ } else if layout. is ( Layout :: CPREFER ) {
2808
+ Order :: RowMajor
2809
+ } else if layout. is ( Layout :: FPREFER ) {
2810
+ Order :: ColumnMajor
2811
+ } else {
2812
+ Order :: RowMajor
2813
+ }
2814
+ }
2815
+
2816
+ struct IntoShapeOwnedCb < E > {
2817
+ order : Order ,
2818
+ shape : E ,
2819
+ }
2820
+
2821
+ impl < S , D , E > IfOwnedCb < S , D > for IntoShapeOwnedCb < E >
2822
+ where
2823
+ S : RawData ,
2824
+ D : Dimension ,
2825
+ E : Dimension ,
2826
+ {
2827
+ type Output = Result < ArrayBase < S , E > , ShapeError > ;
2828
+ fn cb ( self , array : Array < S :: Elem , D > ) -> Self :: Output
2829
+ where
2830
+ S : DataOwned ,
2831
+ D : Dimension ,
2832
+ {
2833
+ let shape = self . shape ;
2834
+ let order = self . order ;
2835
+
2836
+ unsafe {
2837
+ let ( iter, shape) = match order {
2838
+ Order :: RowMajor => {
2839
+ let iter = array. into_iter ( ) ;
2840
+ ( iter, shape. set_f ( false ) )
2841
+ }
2842
+ Order :: ColumnMajor => {
2843
+ let iter = array. reversed_axes ( ) . into_iter ( ) ;
2844
+ ( iter, shape. set_f ( true ) )
2845
+ } ,
2846
+ /* order automatic ruled out */
2847
+ Order :: Automatic => unreachable ! ( ) ,
2848
+ } ;
2849
+ Ok ( ArrayBase :: from_shape_trusted_iter_unchecked (
2850
+ shape, iter, |x| x) )
2851
+ }
2852
+ }
2853
+ }
0 commit comments