@@ -17,6 +17,7 @@ use std::mem::{size_of, ManuallyDrop};
17
17
use crate :: imp_prelude:: * ;
18
18
19
19
use crate :: argument_traits:: AssignElem ;
20
+ use crate :: data_traits:: DataMappable ;
20
21
use crate :: dimension;
21
22
use crate :: dimension:: broadcast:: co_broadcast;
22
23
use crate :: dimension:: reshape_dim;
@@ -2803,48 +2804,6 @@ where
2803
2804
self
2804
2805
}
2805
2806
2806
- /// Consume the array, call `f` by **v**alue on each element, and return an
2807
- /// owned array with the new values. Works for **any** `F: FnMut(A)->B`.
2808
- ///
2809
- /// If `A` and `B` are the same type then the map is performed by delegating
2810
- /// to [`mapv_into`] and then converting into an owned array. This avoids
2811
- /// unnecessary memory allocations in [`mapv`].
2812
- ///
2813
- /// If `A` and `B` are different types then a new array is allocated and the
2814
- /// map is performed as in [`mapv`].
2815
- ///
2816
- /// Elements are visited in arbitrary order.
2817
- ///
2818
- /// [`mapv_into`]: ArrayBase::mapv_into
2819
- /// [`mapv`]: ArrayBase::mapv
2820
- pub fn mapv_into_any < B , F > ( self , mut f : F ) -> Array < B , D >
2821
- where
2822
- S : DataMut ,
2823
- F : FnMut ( A ) -> B ,
2824
- A : Clone + ' static ,
2825
- B : ' static ,
2826
- {
2827
- if core:: any:: TypeId :: of :: < A > ( ) == core:: any:: TypeId :: of :: < B > ( ) {
2828
- // A and B are the same type.
2829
- // Wrap f in a closure of type FnMut(A) -> A .
2830
- let f = |a| {
2831
- let b = f ( a) ;
2832
- // Safe because A and B are the same type.
2833
- unsafe { unlimited_transmute :: < B , A > ( b) }
2834
- } ;
2835
- // Delegate to mapv_into() using the wrapped closure.
2836
- // Convert output to a uniquely owned array of type Array<A, D>.
2837
- let output = self . mapv_into ( f) . into_owned ( ) ;
2838
- // Change the return type from Array<A, D> to Array<B, D>.
2839
- // Again, safe because A and B are the same type.
2840
- unsafe { unlimited_transmute :: < Array < A , D > , Array < B , D > > ( output) }
2841
- } else {
2842
- // A and B are not the same type.
2843
- // Fallback to mapv().
2844
- self . mapv ( f)
2845
- }
2846
- }
2847
-
2848
2807
/// Modify the array in place by calling `f` by mutable reference on each element.
2849
2808
///
2850
2809
/// Elements are visited in arbitrary order.
@@ -3059,6 +3018,111 @@ where
3059
3018
}
3060
3019
}
3061
3020
3021
+ /// # Additional Mapping Methods
3022
+ impl < ' a , A , S , D > ArrayBase < S , D >
3023
+ where
3024
+ D : Dimension ,
3025
+ // Need 'static lifetime bounds for TypeId to work.
3026
+ // mapv() requires that A be Clone.
3027
+ A : Clone + ' a + ' static ,
3028
+ // Output is same memory representation as input, substituting B for A.
3029
+ S : Data < Elem = A > + DataMappable < ' a > ,
3030
+ {
3031
+ /// Consume the array, call `f` by **v**alue on each element, and return an
3032
+ /// owned array with the new values. Works for **any** `F: FnMut(A)->B`.
3033
+ ///
3034
+ /// If `A` and `B` are the same type then the map is performed by delegating
3035
+ /// to [`mapv_into`](`ArrayBase::mapv_into`) and then converting into an
3036
+ /// owned array. This avoids unnecessary memory allocations in
3037
+ /// [`mapv`](`ArrayBase::mapv`).
3038
+ ///
3039
+ /// If `A` and `B` are different types then a new array is allocated and the
3040
+ /// map is performed as in [`mapv`](`ArrayBase::mapv`).
3041
+ ///
3042
+ /// Elements are visited in arbitrary order.
3043
+ ///
3044
+ /// Example:
3045
+ ///
3046
+ /// ```rust
3047
+ /// # use ndarray::{array, Array};
3048
+ /// let a: Array<f32, _> = array![[1., 2., 3.]];
3049
+ /// let b = a.clone();
3050
+ /// // Same type, no new memory allocation.
3051
+ /// let a_plus_one = a.mapv_into_any(|a| a + 1.);
3052
+ /// // Different types, allocates new memory.
3053
+ /// let rounded = b.mapv_into_any(|a| a.round() as i32);
3054
+ /// ```
3055
+ ///
3056
+ /// The return data representation/type depends on the input type and is the
3057
+ /// same as the input type in most cases. See [`DataMappable`] for details.
3058
+ ///
3059
+ /// - [`OwnedRepr`](`crate::OwnedRepr`)/[`Array`] -> [`OwnedRepr`](`crate::OwnedRepr`)/[`Array`]
3060
+ /// - [`OwnedArcRepr`](`crate::OwnedArcRepr`)/[`ArcArray`] -> [`OwnedArcRepr`](`crate::OwnedArcRepr`)/[`ArcArray`]
3061
+ /// - [`CowRepr`](`crate::CowRepr`)/[`CowArray`] -> [`CowRepr`](`crate::CowRepr`)/[`CowArray`]
3062
+ /// - [`ViewRepr`](`crate::ViewRepr`)/[`ArrayView`] or [`ArrayViewMut`] -> [`OwnedRepr`](`crate::OwnedRepr`)/[`Array`]
3063
+ ///
3064
+ /// Mapping from `A` to a different type `B` will always require new memory
3065
+ /// to be allocated. Mapping when `A` and `B` are the same type may not need
3066
+ /// a new memory allocation depending on the input data representation/type.
3067
+ ///
3068
+ /// - [`OwnedRepr`](`crate::OwnedRepr`)/[`Array`]: No new memory allocation.
3069
+ /// - [`OwnedArcRepr`](`crate::OwnedArcRepr`)/[`ArcArray`]: No new memory allocated if data is uniquely owned.
3070
+ /// - [`CowRepr`](`crate::CowRepr`)/[`CowArray`]: No new memory allocated if data is uniquely owned.
3071
+ /// - [`ViewRepr`](`crate::ViewRepr`)/[`ArrayView`] or [`ArrayViewMut`]: Always requires new memory allocation.
3072
+ /// Consider using [`map_inplace`](`ArrayBase::map_inplace`) instead.
3073
+ ///
3074
+ /// Example:
3075
+ ///
3076
+ /// ```rust
3077
+ /// # use ndarray::{array, ArcArray};
3078
+ /// // Uniquely owned data, no new memory allocation.
3079
+ /// let a: ArcArray<f32, _> = array![[1., 2., 3.]].into_shared();
3080
+ /// let a_plus_one = a.mapv_into_any(|a| a + 1.);
3081
+ /// // Shared data, requires new memory allocation.
3082
+ /// let a: ArcArray<f32, _> = array![[1., 2., 3.]].into_shared();
3083
+ /// let b = a.clone(); // `a` is shared here
3084
+ /// let a_plus_one = a.mapv_into_any(|a| a + 1.); // new allocation
3085
+ /// ```
3086
+ ///
3087
+ /// See also:
3088
+ ///
3089
+ /// - [`map_inplace`](`ArrayBase::map_inplace`)
3090
+ /// - [`mapv_into`](`ArrayBase::mapv_into`)
3091
+ /// - [`mapv`](`ArrayBase::mapv`)
3092
+ pub fn mapv_into_any < B , F > ( self , mut f : F ) -> ArrayBase < <S as DataMappable < ' a > >:: Subst < B > , D >
3093
+ where
3094
+ // Need 'static lifetime bounds for TypeId to work.
3095
+ B : ' static ,
3096
+ // Mapping function maps from A to B.
3097
+ F : FnMut ( A ) -> B ,
3098
+ {
3099
+ if core:: any:: TypeId :: of :: < A > ( ) == core:: any:: TypeId :: of :: < B > ( ) {
3100
+ // A and B are the same type.
3101
+ // Wrap f in a closure of type FnMut(A) -> A .
3102
+ let f = |a| {
3103
+ let b = f ( a) ;
3104
+ // Safe because A and B are the same type.
3105
+ unsafe { unlimited_transmute :: < B , A > ( b) }
3106
+ } ;
3107
+ // Convert to a uniquely-owned data representation: Array<A, D>
3108
+ // This will require cloning the data if it is not uniquely owned.
3109
+ let input = self . into_owned ( ) ;
3110
+ // Delegate to mapv_into() to map from element type A to type A.
3111
+ let output = input. mapv_into ( f) ;
3112
+ // Convert to the output data representation, but still with data A.
3113
+ let output = <S as DataMappable >:: from_owned :: < A , D > ( output) ;
3114
+ // Transmute to the output representation to data B.
3115
+ // Safe because A and B are the same type,
3116
+ // and we are not changing the data representation.
3117
+ unsafe { unlimited_transmute :: < ArrayBase < <S as DataMappable >:: Subst < A > , D > , ArrayBase < <S as DataMappable >:: Subst < B > , D > > ( output) }
3118
+ } else {
3119
+ // A and B are not the same type.
3120
+ // Fallback to mapv().
3121
+ <S as DataMappable >:: from_owned :: < B , D > ( self . mapv ( f) )
3122
+ }
3123
+ }
3124
+ }
3125
+
3062
3126
/// Transmute from A to B.
3063
3127
///
3064
3128
/// Like transmute, but does not have the compile-time size check which blocks
0 commit comments