@@ -16,6 +16,7 @@ use crate::imp_prelude::*;
1616
1717use crate :: { arraytraits, DimMax } ;
1818use crate :: argument_traits:: AssignElem ;
19+ use crate :: data_traits:: IfOwnedCb ;
1920use crate :: dimension;
2021use crate :: dimension:: IntoDimension ;
2122use crate :: dimension:: {
@@ -1646,18 +1647,7 @@ where
16461647 }
16471648 let layout = self . layout_impl ( ) ;
16481649 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) ;
16611651 }
16621652
16631653 unsafe {
@@ -1682,43 +1672,183 @@ where
16821672 }
16831673 }
16841674
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.
16881683 ///
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.
16911687 ///
16921688 /// ```
1693- /// use ndarray::{aview1, aview2} ;
1689+ /// use ndarray::array ;
16941690 ///
16951691 /// 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.]]
16991695 /// );
17001696 /// ```
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 >
17021760 where
17031761 E : IntoDimension ,
17041762 {
17051763 let shape = shape. into_dimension ( ) ;
17061764 if size_of_shape_checked ( & shape) != Ok ( self . dim . size ( ) ) {
17071765 return Err ( error:: incompatible_shapes ( & self . dim , & shape) ) ;
17081766 }
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
17101774 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 {
17131776 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 {
17151778 Ok ( self . with_strides_dim ( shape. fortran_strides ( ) , shape) )
17161779 } else {
17171780 Err ( error:: from_kind ( error:: ErrorKind :: IncompatibleLayout ) )
17181781 }
17191782 }
17201783 }
17211784
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+
17221852 /// *Note: Reshape is for `ArcArray` only. Use `.into_shape()` for
17231853 /// other arrays and array views.*
17241854 ///
@@ -2651,7 +2781,6 @@ where
26512781 }
26522782}
26532783
2654-
26552784/// Transmute from A to B.
26562785///
26572786/// 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 {
26672796}
26682797
26692798type 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