Numba and Numpy have different contiguity results when inverting a F-order array

Thanks and congrats to the team for the great work :slight_smile:

I am wondering if the following behavior is the expected one. In Numpy, when we invert an F-order array, it will be c-contiguous, e.g.

a = np.asfortranarray(np.random.rand(3, 3))
print(f'{a.flags}\n{np.linalg.inv(a).flags}')

gives

C_CONTIGUOUS : False
  F_CONTIGUOUS : True
  OWNDATA : True
  WRITEABLE : True
  ALIGNED : True
  WRITEBACKIFCOPY : False
  UPDATEIFCOPY : False

  C_CONTIGUOUS : True
  F_CONTIGUOUS : False
  OWNDATA : True
  WRITEABLE : True
  ALIGNED : True
  WRITEBACKIFCOPY : False
  UPDATEIFCOPY : False

So the returned array is c-contiguous. However, when we do the same inside a method compiled with Numba:

@njit
def foo(a):
    return np.linalg.inv(a)

a = np.asfortranarray(np.random.rand(3, 3))
print(foo(a).flags)

it gives:

  C_CONTIGUOUS : False
  F_CONTIGUOUS : True
  OWNDATA : False
  WRITEABLE : True
  ALIGNED : True
  WRITEBACKIFCOPY : False
  UPDATEIFCOPY : False

The array keeps being f-contiguous.

any help is highly appreciated!

Hi @javier

Below you can see how np.linalg.inv is implemented in Numba. They explicitly always return a Fortran array. Therefore, I think you can’t do anything but copy it to a C array afterwards. I don’t know the underlying Lapack function, but maybe it needs to have a Fortran ordered array and Numpy also just copies it after the transform if needed.

@overload(np.linalg.inv)
def inv_impl(a):
    ...
    def inv_impl(a):
        ...
        acpy = _copy_to_fortran_order(a)
        ...
        return acpy

    return inv_impl
1 Like

Hi @sschaer, thanks for the response! It definitely solves the question :slight_smile:

PD: How can I accept a response? Maybe because I’m a new user I can’t do it (I don’t find the button)?