[Numpy-discussion] np.asfortranarray: unnecessary copying?

Anne Archibald aarchiba at physics.mcgill.ca
Fri Jul 30 14:33:16 EDT 2010


This seems to me to be a bug, or rather, two bugs. 1D arrays are
automatically Fortran-ordered, so isfortran should return True for
them (incidentally, the documentation should be edited to indicate
that the data must also be contiguous in memory). Whether or not this
change is made, there's no point in asfortranarray making a copy of a
1D array, since the copy isn't any more Fortran-ordered than the input
array.

Another kind of iffy case is axes of length one. These should not
affect C/Fortran order, since the length of their strides doesn't
matter, but they do; if you use newaxis to add an axis to an array,
it's still just as C/Fortran ordered as it was, but np.isfortran
reports False. (Is there a np.isc or equivalent function?)

Incidentally, there is a subtle misconception in your example code:
when reshaping an array, the order='F' has a different meaning. It has
nothing direct to do with the memory layout; what it does is define
the logical arrangement of elements used while reshaping the array.
The array returned will be in C order if a copy must be made, or in
whatever arbitrarily-strided order is necessary if the reshape can be
done without a copy. As it happens, in your example, the latter case
occurs and works out to Fortran order.

Anne

On 30 July 2010 13:50, Kurt Smith <kwmsmith at gmail.com> wrote:
> What are the rules for when 'np.asarray' and 'np.asfortranarray' make a copy?
>
> This makes sense to me:
>
> In [3]: carr = np.arange(3)
>
> In [6]: carr2 = np.asarray(carr)
>
> In [8]: carr2[0] = 1
>
> In [9]: carr
> Out[9]: array([1, 1, 2])
>
> No copy is made.
>
> But doing the same with a fortran array makes a copy:
>
> In [10]: farr = np.arange(3).copy('F')
>
> In [12]: farr2 = np.asfortranarray(farr)
>
> In [13]: farr2[0] = 1
>
> In [14]: farr
> Out[14]: array([0, 1, 2])
>
> Could it be a 1D thing, since it's both C contiguous & F contiguous?
>
> Here's a 2D example:
>
> In [15]: f2D = np.arange(10).reshape((2,5), order='F')
>
> In [17]: f2D2 = np.asfortranarray(f2D)
>
> In [19]: f2D2[0,0] = 10
>
> In [20]: f2D
> Out[20]:
> array([[10,  2,  4,  6,  8],
>       [ 1,  3,  5,  7,  9]])
>
> So it looks like np.asfortranarray makes an unnecessary copy if the
> array is simultaneously 1D, C contiguous and F contiguous.
>
> Coercing the array with np.atleast_2d() makes asfortranarry behave.
>
> Looking further, np.isfortran always returns false if the array is 1D,
> even if it's Fortran contiguous (and np.isfortran is documented as
> such).
>
> What is the rationale here?  Is it a 'column' vs. 'row' thing?
>
> Kurt
> _______________________________________________
> NumPy-Discussion mailing list
> NumPy-Discussion at scipy.org
> http://mail.scipy.org/mailman/listinfo/numpy-discussion
>



More information about the NumPy-Discussion mailing list