Predict memory layout of ufunc output
In a = np.zeros((3,2),order='F')
case, a.reshape(2,3)
creates a copy, not a view. That's why assignment fails, not the memory layout itself.
Look at same shape array:
In [123]: a = np.arange(6).reshape(3,2) In [124]: a Out[124]: array([[0, 1], [2, 3], [4, 5]])In [125]: a.reshape(2,3) Out[125]: array([[0, 1, 2], [3, 4, 5]])In [127]: a.reshape(2,3)[:,0] Out[127]: array([0, 3])
In [125] the values still flow in order C.
and an order F array:
In [128]: b = np.arange(6).reshape(3,2, order='F') In [129]: b Out[129]: array([[0, 3], # values flow in order F [1, 4], [2, 5]])In [130]: b.reshape(2,3) Out[130]: array([[0, 3, 1], # values are jumbled [4, 2, 5]])In [131]: b.reshape(2,3)[:,0] Out[131]: array([0, 4])
If I keep order F in the shape:
In [132]: b.reshape(2,3, order='F') Out[132]: array([[0, 2, 4], # values still flow in order F [1, 3, 5]])In [133]: b.reshape(2,3, order='F')[:,0] Out[133]: array([0, 1])
Confirm with assignment:
In [135]: a.reshape(2,3)[:,0]=10 In [136]: a Out[136]: array([[10, 1], [ 2, 10], [ 4, 5]])
not assignment:
In [137]: b.reshape(2,3)[:,0]=10 In [138]: b Out[138]: array([[0, 3], [1, 4], [2, 5]])
but here assignment works:
In [139]: b.reshape(2,3, order='F')[:,0]=10 In [140]: b Out[140]: array([[10, 3], [10, 4], [ 2, 5]])
Or we can use order A
to preserve order:
In [143]: b.reshape(2,3, order='A')[:,0] Out[143]: array([10, 10])In [144]: b.reshape(2,3, order='A')[:,0] = 20 In [145]: b Out[145]: array([[20, 3], [20, 4], [ 2, 5]])
ufunc order
Suspecting that ufunc
are (mostly) implemented with nditer
(C version), I checked np.nditer` docs - order can be specified in several places. And the tutorial demonstrates order effect on the iteration.
I don't see order
documented for ufunc
, but, it is accepted by the kwargs
.
In [171]: c = np.arange(8).reshape(2,2,2) In [172]: d = c.transpose(1,0,2) In [173]: d.strides Out[173]: (16, 32, 8)In [174]: np.multiply(d,d,order='K').strides Out[174]: (16, 32, 8)In [175]: np.multiply(d,d,order='C').strides Out[175]: (32, 16, 8)In [176]: np.multiply(d,d,order='F').strides Out[176]: (8, 16, 32)