44use std:: fmt:: Display ;
55use std:: fmt:: Formatter ;
66
7+ use smallvec:: SmallVec ;
78use vortex_error:: VortexExpect ;
89use vortex_error:: VortexResult ;
910use vortex_error:: vortex_bail;
@@ -15,6 +16,7 @@ use crate::array::Array;
1516use crate :: array:: ArrayParts ;
1617use crate :: array:: TypedArrayRef ;
1718use crate :: arrays:: ScalarFn ;
19+ use crate :: dtype:: DType ;
1820use crate :: scalar_fn:: ScalarFnRef ;
1921
2022// ScalarFnArray has a variable number of slots (one per child)
@@ -74,9 +76,13 @@ impl<T: TypedArrayRef<ScalarFn>> ScalarFnArrayExt for T {}
7476
7577impl Array < ScalarFn > {
7678 /// Create a new ScalarFnArray from a scalar function and its children.
77- pub fn try_new ( scalar_fn : ScalarFnRef , children : Vec < ArrayRef > ) -> VortexResult < Self > {
78- let len = Self :: infer_len ( & children) ?;
79- Self :: try_new_with_len ( scalar_fn, children, len)
79+ pub fn try_new (
80+ scalar_fn : ScalarFnRef ,
81+ children : impl IntoIterator < Item = ArrayRef > ,
82+ ) -> VortexResult < Self > {
83+ let slots: ArraySlots = children. into_iter ( ) . map ( Some ) . collect ( ) ;
84+ let len = Self :: infer_len ( & slots) ?;
85+ Self :: try_new_from_slots ( scalar_fn, slots, len)
8086 }
8187
8288 /// Create a new ScalarFnArray from a scalar function, children, and an explicit length.
@@ -85,37 +91,61 @@ impl Array<ScalarFn> {
8591 /// child array to infer the length from.
8692 pub fn try_new_with_len (
8793 scalar_fn : ScalarFnRef ,
88- children : Vec < ArrayRef > ,
94+ children : impl IntoIterator < Item = ArrayRef > ,
95+ len : usize ,
96+ ) -> VortexResult < Self > {
97+ let slots: ArraySlots = children. into_iter ( ) . map ( Some ) . collect ( ) ;
98+ Self :: try_new_from_slots ( scalar_fn, slots, len)
99+ }
100+
101+ #[ inline]
102+ fn try_new_from_slots (
103+ scalar_fn : ScalarFnRef ,
104+ slots : ArraySlots ,
89105 len : usize ,
90106 ) -> VortexResult < Self > {
91- Self :: validate_arity ( & scalar_fn, children . len ( ) ) ?;
92- Self :: validate_children_len ( & children , len) ?;
107+ Self :: validate_arity ( & scalar_fn, slots . len ( ) ) ?;
108+ Self :: validate_children_len ( & slots , len) ?;
93109
94- let arg_dtypes: Vec < _ > = children . iter ( ) . map ( |c| c . dtype ( ) . clone ( ) ) . collect ( ) ;
110+ let arg_dtypes = Self :: arg_dtypes ( & slots ) ;
95111 let dtype = scalar_fn. return_dtype ( & arg_dtypes) ?;
96- let data = ScalarFnData {
97- scalar_fn : scalar_fn. clone ( ) ,
98- } ;
112+
113+ Ok ( unsafe { Self :: new_from_validated_slots ( scalar_fn, dtype, slots, len) } )
114+ }
115+
116+ /// # Safety
117+ /// The caller must ensure arity and child lengths were validated and
118+ /// "dtype" is scalar function's return dtype.
119+ #[ inline]
120+ unsafe fn new_from_validated_slots (
121+ scalar_fn : ScalarFnRef ,
122+ dtype : DType ,
123+ slots : ArraySlots ,
124+ len : usize ,
125+ ) -> Self {
99126 let vtable = ScalarFn { id : scalar_fn. id ( ) } ;
127+ let data = ScalarFnData { scalar_fn } ;
128+ unsafe { Array :: from_parts_unchecked ( ArrayParts :: new ( vtable, dtype, len, data, slots) ) }
129+ }
100130
101- Ok ( unsafe {
102- Array :: from_parts_unchecked ( ArrayParts :: new (
103- vtable,
104- dtype,
105- len,
106- data,
107- children. into_iter ( ) . map ( Some ) . collect :: < ArraySlots > ( ) ,
108- ) )
109- } )
131+ #[ inline]
132+ fn arg_dtypes ( slots : & [ Option < ArrayRef > ] ) -> SmallVec < [ DType ; 4 ] > {
133+ let mut arg_dtypes = SmallVec :: with_capacity ( slots. len ( ) ) ;
134+ for child in slots. iter ( ) . flatten ( ) {
135+ arg_dtypes. push ( child. dtype ( ) . clone ( ) ) ;
136+ }
137+ arg_dtypes
110138 }
111139
112- fn infer_len ( children : & [ ArrayRef ] ) -> VortexResult < usize > {
113- let Some ( child) = children. first ( ) else {
140+ #[ inline]
141+ fn infer_len ( slots : & [ Option < ArrayRef > ] ) -> VortexResult < usize > {
142+ let Some ( child) = slots. first ( ) . and_then ( Option :: as_ref) else {
114143 vortex_bail ! ( "ScalarFnArray length cannot be inferred without children" ) ;
115144 } ;
116145 Ok ( child. len ( ) )
117146 }
118147
148+ #[ inline]
119149 fn validate_arity ( scalar_fn : & ScalarFnRef , child_count : usize ) -> VortexResult < ( ) > {
120150 let arity = scalar_fn. signature ( ) . arity ( ) ;
121151 vortex_ensure ! (
@@ -125,11 +155,14 @@ impl Array<ScalarFn> {
125155 Ok ( ( ) )
126156 }
127157
128- fn validate_children_len ( children : & [ ArrayRef ] , len : usize ) -> VortexResult < ( ) > {
129- vortex_ensure ! (
130- children. iter( ) . all( |c| c. len( ) == len) ,
131- "ScalarFnArray must have children equal to the array length"
132- ) ;
158+ #[ inline]
159+ fn validate_children_len ( slots : & [ Option < ArrayRef > ] , len : usize ) -> VortexResult < ( ) > {
160+ for child in slots. iter ( ) . flatten ( ) {
161+ vortex_ensure ! (
162+ child. len( ) == len,
163+ "ScalarFnArray must have children equal to the array length"
164+ ) ;
165+ }
133166 Ok ( ( ) )
134167 }
135168}
0 commit comments