Skip to content

Rank one (outer) product #427

Closed
Closed
@ghbrown

Description

@ghbrown

Description

A simple function to compute the rank one (a.k.a. outer) product of two vectors, which would return a matrix.

I believe the current way to do this (or at least the way I do) involves explicit looping or reshapeing and then matmul (even worse than looping probably). I just suggest the mathematics be hidden away from a user inside the function, so they can pass two true vectors in and it will return a matrix.

Rank one updates are sufficiently common that I think we should include a specific function to accommodate this. Here is my crack at a simple "column-major-optimized" version (I'd do speed tests comparing the various methods if we want this function):

function rop(u,v) result(mat)
    implicit none
    real, intent(in) :: u(:), v(:)
    real :: mat(size(u),size(v))
    integer :: col
    do col=1,size(v)
        mat(:,col) = v(col) * u
    end do
end function

Options/alternatives to a dedicated function:

  • this functionality may eventually be provided by a more general tensor product routine (like those below), so perhaps this would just be a holdover
  • something like this likely exists in BLAS somewhere in which case this function would be a wrapper for that if desired
  • there could also be a good reason (that I don't) know why this feature doesn't exist, hasn't been proposed, and shouldn't be implemented (perhaps like the fact it requires quadratic storage for a linear amount of data in which case it might be preferable to update all elements in a loop instead, who knows?)

Prior Art

Numpy does not provide a rank-one-product-specific function, but provides this functionality through multiple functions, including:

  • numpy.outer(u,v)
  • numpy.tensordot(u,v,axes=0)
  • numpy.einsum('i,j',u,v) or numpy.einsum('i,j->ij',a,a)
    given vectors u, v.

Relevant but separate discussion
Perhaps this is just a result of my field of interest, but I'd like to bring up the discussion of terminology for the number of array dimensions (only since it's relevant here):

  • I believe the current Fortran terminology is "rank", this is not optimal in my eyes because rank has a conflicting linear algebra definition (especially problematic since Fortran is commonly used for linear algebra); Python/Numpy also uses rank, but that doesn't make it "right"
    -"order", "mode", or "way" are my suggestions and what many people use as an alternative to rank in literature on multi-way arrays beyond matrices
  • "dimension" seems to make sense but is almost ubiquitously used to describe the length of a mode, so I would say it's out of the question

Metadata

Metadata

Assignees

No one assigned

    Labels

    ideaProposition of an idea and opening an issue to discuss it

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions