Before someone closes the question, yes, there are many questions that seem similar, but so far I haven't found one with this exact weird problem that seems to go away only sometimes.
I had an odd Fortran error while trying to make a module for linear regression.
The module is named "LSQregression" and the main program "LSQAdvertising". Compiling it using the following gfortran command works:
gfortran ../LSQregression.f90 LinearAdvertising.f90 -llapack -o LinAd
However, I'd like to be able to turn my module into a .o file and link it with whatever program I may need instead of compiling again every time. So I tried to do that:
gfortran -c ../LSQregression.f90
And then link it with my program file like that:
gfortran ../LSQregression.o LinearAdvertising.f90 -llapack -o LinAd
I also tried also turning the program into a .o file. Neither works, they both return the following error:
/usr/bin/ld: /tmp/ccf7T1aj.o: in function `MAIN__':
LinearAdvertising.f90:(.text+0x1f8b): undefined reference to `__lsqregression_MOD_lsqestimate_simple'
collect2: error: ld returned 1 exit status
It refers to the following function in the module that is being called here inside the program:
print *, LSQestimate(test,LSQbeta(inputs,sales,(/1,2/)) )
The function itself is defined as part of an interface:
interface LSQestimate
     procedure LSQestimate_simple, LSQestimate_using
  end interface LSQestimate
 real(8) function LSQestimate_simple(X, beta)
    implicit none
    real(8), dimension(:,:) :: X, beta
    real(8)                 :: boundary, Y
    integer                 :: i, Xlen, betalen
    Xlen    = size(X, 1)
    betalen = size(beta, 1)
    if (Xlen + 1 .ne. betalen) stop "incompatible beta and X"
    Y = beta(1,1)
    do i = 1, Xlen
       Y = Y + beta(i+1, 1)*X(i,1)
    end do
    LSQestimate_simple = Y
    
  end function LSQestimate_simple
It's very odd because I've done the same thing with another function and it seems to work fine, and the problem only happens when I turn the module into a .o file first, and goes away if I try to directly compile the .f90 file... I can't figure out why one works and the other doesn't.
EDIT: Someone told me to do nm ../LSQregression.o | grep -i regression . I have no idea what that does but I did it so here are the results if it helps at all:
0000000000002768 T __lsqregression_MOD_inv
0000000000000b85 T __lsqregression_MOD_lsqbeta_simple
000000000000035c T __lsqregression_MOD_lsqbeta_using
0000000000000000 T __lsqregression_MOD_lsqdecision
Oddly enough the name of the function in question doesn't even appear here.
EDIT 2: Decided to post the entire code of the module:
module LSQregression
  implicit none
  public  :: LSQbeta, LSQestimate
  interface LSQbeta
     procedure LSQbeta_simple, LSQbeta_using
  end interface LSQbeta
  interface LSQestimate
     procedure LSQestimate_simple, LSQestimate_using
  end interface LSQestimate
  
  
  
  
contains
  
  function inv(A) result(Ainv)
    implicit none
    real(8), dimension(:,:), intent(in)     :: A
    real(8), dimension(size(A,1),size(A,2)) :: Ainv
    real(8), dimension(size(A,1)) :: work  ! work array for LAPACK
    integer, dimension(size(A,1)) :: ipiv   ! pivot indices
    integer :: n, info
    ! External procedures defined in LAPACK
    external DGETRF
    external DGETRI
    ! Store A in Ainv to prevent it from being overwritten by LAPACK
    Ainv = A
    n = size(A,1)
    ! DGETRF computes an LU factorization of a general M-by-N matrix A
    ! using partial pivoting with row interchanges.
    call DGETRF(n, n, Ainv, n, ipiv, info)
    if (info /= 0) then
       stop 'Matrix is numerically singular!'
    end if
    ! DGETRI computes the inverse of a matrix using the LU factorization
    ! computed by DGETRF.
    call DGETRI(n, Ainv, n, ipiv, work, n, info)
    
    if (info /= 0) then
       stop 'Matrix inversion failed!'
    end if
  end function inv
  
  !----------------------------------------------------------------------
  
  function LSQbeta_simple(Xold, Y) result(beta)
    real(8), dimension(:,:)                          :: Xold, Y
    real(8), dimension(size(Xold,1), size(Xold,2)+1) :: X
    real(8), dimension(:,:), allocatable             :: beta, XTX, IXTX, pinv
    integer                                          :: rowsX, colsX, rowsY, colsY,i
    rowsX = size(X(:,1))
    colsX = size(X(1,:))
    rowsY = size(Y(:,1))
    colsY = size(Y(1,:))
    if (colsY .ne. 1)     stop 'Inappropriate y'
    if (rowsY .ne. rowsX) stop "Y and X rows don't match"
    
    !---X-ify-----------
    X(:,1) = 1.0     !includes 1 in the first column
    
    do i = 2, colsX
       X(:,i) = Xold(:,i-1)
    end do
    !--------------------
   
    allocate(XTX(colsX,colsX))
    allocate(IXTX(colsX,colsX))
    allocate(pinv(colsX,rowsY))
    allocate(beta(colsX,1))
    XTX   = matmul(transpose(X),X)
    IXTX  = inv(XTX)
    pinv  = matmul(IXTX, transpose(X))
    beta  = matmul(pinv, Y)
    deallocate(pinv)
    deallocate(XTX)
    deallocate(IXTX)
    return
    
    deallocate(beta)
    
  end function LSQbeta_simple
  !--------------------------------------------
  
  function LSQbeta_using(Xold, Y, indexes) result(beta)
    implicit none
    real(8), dimension(:,:)                        :: Xold, Y
    integer, dimension(:)                          :: indexes
    real(8), dimension(size(indexes)+1,1)          :: beta
    real(8), dimension(size(Xold,1),size(indexes)) :: X
    integer                                        :: indLen,i
    indLen = size(indexes) 
    
    do i = 1, indLen
       X(:,i) = Xold(:,indexes(i))
    end do
    beta = LSQbeta_simple(X,Y)
    
  end function LSQbeta_using
  real(8) function LSQestimate_simple(X, beta)
    implicit none
    real(8), dimension(:,:) :: X, beta
    real(8)                 :: boundary, Y
    integer                 :: i, Xlen, betalen
    Xlen    = size(X, 1)
    betalen = size(beta, 1)
    if (Xlen + 1 .ne. betalen) stop "incompatible beta and X"
    Y = beta(1,1)
    do i = 1, Xlen
       Y = Y + beta(i+1, 1)*X(i,1)
    end do
    LSQestimate_simple = Y
    
  end function LSQestimate_simple
  real(8) function LSQestimate_using()
    LSQestimate_using = 1.0D0
  end function LSQestimate_using
  
  
  logical function LSQdecision(X, beta, boundary)
    implicit none
    real(8), dimension(:,:) :: X, beta
    real(8)                 :: boundary
    
    LSQdecision = LSQestimate(X, beta) > boundary
    
  end function LSQdecision
  
  
end module LSQregression
