@@ -161,9 +161,7 @@ def edge_weights_to_igraph_vector_t_view(
161161 When the input is `None`, the return value will also be `None`, which is
162162 interpreted by the C core of igraph as all edges having equal weight.
163163 """
164- return (
165- edge_weights_to_igraph_vector_t (weights , graph ) if weights is not None else None
166- )
164+ return iterable_to_igraph_vector_t_view (weights ) if weights is not None else None
167165
168166
169167def iterable_edge_indices_to_igraph_vector_int_t (
@@ -173,7 +171,7 @@ def iterable_edge_indices_to_igraph_vector_int_t(
173171 of edge IDs.
174172 """
175173 if isinstance (indices , np .ndarray ):
176- return numpy_array_to_igraph_vector_int_t (indices )
174+ return numpy_array_to_igraph_vector_int_t (indices , flatten = True )
177175
178176 result : _VectorInt = _VectorInt .create (0 )
179177 for index in indices :
@@ -199,16 +197,18 @@ def iterable_to_igraph_vector_bool_t_view(items: Iterable[Any]) -> _VectorBool:
199197 booleans based on their truth values, possibly creating a shallow view if
200198 the input is an appropriate NumPy array.
201199 """
202- # TODO(ntamas)
203- return iterable_to_igraph_vector_bool_t (items )
200+ if isinstance (items , np .ndarray ):
201+ return numpy_array_to_igraph_vector_bool_t_view (items )
202+ else :
203+ return iterable_to_igraph_vector_bool_t (items )
204204
205205
206206def iterable_to_igraph_vector_int_t (items : Iterable [int ]) -> _VectorInt :
207207 """Converts an iterable containing Python integers to an igraph vector of
208208 integers.
209209 """
210210 if isinstance (items , np .ndarray ):
211- return numpy_array_to_igraph_vector_int_t (items )
211+ return numpy_array_to_igraph_vector_int_t (items , flatten = True )
212212 else :
213213 result = _VectorInt .create (0 )
214214 for item in items :
@@ -221,27 +221,34 @@ def iterable_to_igraph_vector_int_t_view(items: Iterable[Any]) -> _VectorInt:
221221 integers, possibly creating a shallow view if the input is an appropriate
222222 NumPy array.
223223 """
224- # TODO(ntamas)
225- return iterable_to_igraph_vector_int_t (items )
224+ if isinstance (items , np .ndarray ):
225+ return numpy_array_to_igraph_vector_int_t_view (items , flatten = True )
226+ else :
227+ return iterable_to_igraph_vector_int_t (items )
226228
227229
228230def iterable_to_igraph_vector_t (items : Iterable [float ]) -> _Vector :
229231 """Converts an iterable containing Python integers or floats to an igraph
230232 vector of floats.
231233 """
232- result : _Vector = _Vector .create (0 )
233- for item in items :
234- igraph_vector_push_back (result , item )
235- return result
234+ if isinstance (items , np .ndarray ):
235+ return numpy_array_to_igraph_vector_t (items )
236+ else :
237+ result : _Vector = _Vector .create (0 )
238+ for item in items :
239+ igraph_vector_push_back (result , item )
240+ return result
236241
237242
238243def iterable_to_igraph_vector_t_view (items : Iterable [float ]) -> _Vector :
239244 """Converts an iterable containing Python integers or floats to an igraph
240245 vector of floats, possibly creating a shallow view if the input is an
241246 appropriate NumPy array.
242247 """
243- # TODO(ntamas)
244- return iterable_to_igraph_vector_t (items )
248+ if isinstance (items , np .ndarray ):
249+ return numpy_array_to_igraph_vector_t_view (items )
250+ else :
251+ return iterable_to_igraph_vector_t (items )
245252
246253
247254def iterable_vertex_indices_to_igraph_vector_int_t (
@@ -251,7 +258,7 @@ def iterable_vertex_indices_to_igraph_vector_int_t(
251258 of vertex IDs.
252259 """
253260 if isinstance (indices , np .ndarray ):
254- return numpy_array_to_igraph_vector_int_t (indices )
261+ return numpy_array_to_igraph_vector_int_t (indices , flatten = True )
255262
256263 result : _VectorInt = _VectorInt .create (0 )
257264 for index in indices :
@@ -322,15 +329,21 @@ def _ensure_matrix(items: Sequence[Sequence[Any]]) -> None:
322329
323330
324331def _force_into_1d_numpy_array (arr : np .ndarray , np_type , flatten : bool ) -> np .ndarray :
332+ """Ensures that the given NumPy array is one-dimensional and matches the
333+ given NumPy type, avoiding copies during the conversion if possible.
334+ """
325335 if len (arr .shape ) != 1 :
326336 if flatten :
327- arr = arr .reshape (( - 1 ,) )
337+ arr = arr .reshape (- 1 )
328338 else :
329339 raise TypeError ("NumPy array must be one-dimensional" )
330340 return np .ravel (arr .astype (np_type , order = "C" , casting = "safe" , copy = False ))
331341
332342
333343def _force_into_2d_numpy_array (arr : np .ndarray , np_type ) -> np .ndarray :
344+ """Ensures that the given NumPy array is two-dimensional and matches the
345+ given NumPy type, avoiding copies during the conversion if possible.
346+ """
334347 if len (arr .shape ) != 2 :
335348 raise TypeError ("NumPy array must be two-dimensional" )
336349 return arr .astype (np_type , order = "C" , casting = "safe" , copy = False )
@@ -365,31 +378,69 @@ def numpy_array_to_igraph_vector_bool_t(
365378) -> _VectorBool :
366379 """Converts a one-dimensional NumPy array to an igraph vector of booleans."""
367380 arr = _force_into_1d_numpy_array (arr , np_type_of_igraph_bool_t , flatten = flatten )
368- arr = np .ravel (
369- arr .astype (np_type_of_igraph_bool_t , order = "C" , casting = "safe" , copy = False )
370- )
371381 return _VectorBool .create_with (
372382 igraph_vector_bool_init_array ,
373383 arr .ctypes .data_as (POINTER (igraph_bool_t )),
374384 arr .shape [0 ],
375385 )
376386
377387
388+ def numpy_array_to_igraph_vector_bool_t_view (
389+ arr : np .ndarray , flatten : bool = False
390+ ) -> _VectorBool :
391+ """Provides a view into an existing one-dimensional NumPy array with an
392+ igraph boolean vector view if the data type and the layout of the NumPy
393+ array is suitable. If the NumPy array is not suitable, it will be copied
394+ into the appropriate layout and data type first and then a view will be
395+ provided into the copy.
396+ """
397+ arr = _force_into_1d_numpy_array (arr , np_type_of_igraph_real_t , flatten = flatten )
398+
399+ result = _VectorBool ()
400+ igraph_vector_bool_view (
401+ result , arr .ctypes .data_as (POINTER (igraph_bool_t )), arr .shape [0 ]
402+ )
403+
404+ # Destructor must not be called so we never mark result as initialized;
405+ # this is intentional
406+
407+ return result
408+
409+
378410def numpy_array_to_igraph_vector_int_t (
379411 arr : np .ndarray , flatten : bool = False
380412) -> _VectorInt :
381413 """Converts a one-dimensional NumPy array to an igraph vector of integers."""
382414 arr = _force_into_1d_numpy_array (arr , np_type_of_igraph_integer_t , flatten = flatten )
383- arr = np .ravel (
384- arr .astype (np_type_of_igraph_integer_t , order = "C" , casting = "safe" , copy = False )
385- )
386415 return _VectorInt .create_with (
387416 igraph_vector_int_init_array ,
388417 arr .ctypes .data_as (POINTER (igraph_integer_t )),
389418 arr .shape [0 ],
390419 )
391420
392421
422+ def numpy_array_to_igraph_vector_int_t_view (
423+ arr : np .ndarray , flatten : bool = False
424+ ) -> _VectorInt :
425+ """Provides a view into an existing one-dimensional NumPy array with an
426+ igraph integer vector view if the data type and the layout of the NumPy
427+ array is suitable. If the NumPy array is not suitable, it will be copied
428+ into the appropriate layout and data type first and then a view will be
429+ provided into the copy.
430+ """
431+ arr = _force_into_1d_numpy_array (arr , np_type_of_igraph_integer_t , flatten = flatten )
432+
433+ result = _VectorInt ()
434+ igraph_vector_int_view (
435+ result , arr .ctypes .data_as (POINTER (igraph_integer_t )), arr .shape [0 ]
436+ )
437+
438+ # Destructor must not be called so we never mark result as initialized;
439+ # this is intentional
440+
441+ return result
442+
443+
393444def numpy_array_to_igraph_vector_t (arr : np .ndarray , flatten : bool = False ) -> _Vector :
394445 """Converts a one-dimensional NumPy array to an igraph vector of reals."""
395446 arr = _force_into_1d_numpy_array (arr , np_type_of_igraph_real_t , flatten = flatten )
@@ -400,6 +451,26 @@ def numpy_array_to_igraph_vector_t(arr: np.ndarray, flatten: bool = False) -> _V
400451 )
401452
402453
454+ def numpy_array_to_igraph_vector_t_view (
455+ arr : np .ndarray , flatten : bool = False
456+ ) -> _Vector :
457+ """Provides a view into an existing one-dimensional NumPy array with an
458+ igraph floating-point vector view if the data type and the layout of the NumPy
459+ array is suitable. If the NumPy array is not suitable, it will be copied
460+ into the appropriate layout and data type first and then a view will be
461+ provided into the copy.
462+ """
463+ arr = _force_into_1d_numpy_array (arr , np_type_of_igraph_real_t , flatten = flatten )
464+
465+ result = _Vector ()
466+ igraph_vector_view (result , arr .ctypes .data_as (POINTER (igraph_real_t )), arr .shape [0 ])
467+
468+ # Destructor must not be called so we never mark result as initialized;
469+ # this is intentional
470+
471+ return result
472+
473+
403474def vertexlike_to_igraph_integer_t (vertex : VertexLike ) -> igraph_integer_t :
404475 """Converts a vertex-like object to an igraph integer."""
405476 if isinstance (vertex , int ) and vertex >= 0 :
0 commit comments