# Check for BLAS and LAPACK support
# =================================
if(PURE)
  set(MATH_DESC "Unthreaded BLAS/LAPACK link flags")
else()
  set(MATH_DESC "Threaded BLAS/LAPACK link flags")
endif()
if(MATH_LIBS)
  message(STATUS "Using user-defined MATH_LIBS=${MATH_LIBS}")
elseif(APPLE)
  set(MATH_LIBS "-framework vecLib" CACHE STRING ${MATH_DESC})
  message(STATUS "Using Apple vecLib framework.")
else()
  # Look for default BLAS and LAPACK
  if(REFERENCE_ROOT)
    message(STATUS "Searching REFERENCE_ROOT=${REFERENCE_ROOT} for math libs")
  endif()
  set(REFERENCE_REQUIRED LAPACK BLAS)
  find_library(BLAS_LIB NAMES blas PATHS ${REFERENCE_ROOT})
  find_library(LAPACK_LIB NAMES lapack reflapack PATHS ${REFERENCE_ROOT})
  set(REFERENCE_FOUND TRUE)
  foreach(NAME ${REFERENCE_REQUIRED})
    if(${NAME}_LIB)
      message(STATUS "Found ${NAME}_LIB: ${${NAME}_LIB}")
      list(APPEND MATH_LIBS ${${NAME}_LIB})
    else()
      message(STATUS "Could not find ${NAME}_LIB")
      set(MATH_LIBS "")
      set(REFERENCE_FOUND FALSE)
    endif()
  endforeach()
  if(REFERENCE_FOUND)
    message(WARNING "Using reference BLAS/LAPACK; performance will be poor")
  else()
    message(FATAL_ERROR "Could not find BLAS/LAPACK. Please specify MATH_LIBS")
  endif()
endif()
# Check the BLAS and LAPACK underscore conventions
set(CMAKE_REQUIRED_FLAGS "${MPI_C_COMPILE_FLAGS} ${MPI_C_LINK_FLAGS}")
set(CMAKE_REQUIRED_INCLUDES ${MPI_C_INCLUDE_PATH})
set(CMAKE_REQUIRED_LIBRARIES "${MATH_LIBS};${MPI_C_LIBRARIES}")
check_function_exists(daxpy  ELEM_HAVE_DAXPY)
check_function_exists(daxpy_ ELEM_HAVE_DAXPY_POST)
check_function_exists(dpotrf  ELEM_HAVE_DPOTRF)
check_function_exists(dpotrf_ ELEM_HAVE_DPOTRF_POST)
if(ELEM_HAVE_DAXPY)
  set(ELEM_BLAS_POST FALSE)
  set(ELEM_BLAS_DEFS "")
elseif(ELEM_HAVE_DAXPY_POST)
  set(ELEM_BLAS_POST TRUE)
  set(ELEM_BLAS_DEFS "-DBLAS_POST")
else()
  message(FATAL_ERROR "Could not determine BLAS format.")
endif()
if(ELEM_HAVE_DPOTRF)
  set(ELEM_LAPACK_POST FALSE)
  set(ELEM_LAPACK_DEFS "")
elseif(ELEM_HAVE_DPOTRF_POST)
  set(ELEM_LAPACK_POST TRUE)
  set(ELEM_LAPACK_DEFS "-DLAPACK_POST")
else()
  message(FATAL_ERROR "Could not determine LAPACK format.")
endif()
# Ensure that we have a relatively new version of LAPACK
if(ELEM_HAVE_DPOTRF)
  check_function_exists(dsyevr ELEM_HAVE_DSYEVR)
  if(NOT ELEM_HAVE_DSYEVR)
    message(FATAL_ERROR "LAPACK is missing dsyevr")
  endif()
else()
  check_function_exists(dsyevr_ ELEM_HAVE_DSYEVR_POST)
  if(NOT ELEM_HAVE_DSYEVR_POST)
    message(FATAL_ERROR "LAPACK is missing dsyevr_")
  endif()
endif()

# Check for libFLAME support
# ==========================
check_function_exists(FLA_Bsvd_v_opd_var1 ELEM_HAVE_FLA_BSVD)

# Check for ScaLAPACK support
# ===========================
# NOTE: pdsyngst was chosen because MKL's ScaLAPACK only defines pdsyngst_,
#       but not pdsyngst, despite defining both pdpotrf and pdpotrf_. 
check_function_exists(pdsyngst  ELEM_HAVE_PDSYNGST)
check_function_exists(pdsyngst_ ELEM_HAVE_PDSYNGST_POST)
check_function_exists(Csys2blacs_handle ELEM_HAVE_CSYS2BLACS)
if(ELEM_HAVE_PDSYNGST)
  check_function_exists(pdlaqr0 ELEM_HAVE_PDLAQR0)
  check_function_exists(pdlaqr1 ELEM_HAVE_PDLAQR1)
  if(NOT ELEM_HAVE_PDLAQR0 OR NOT ELEM_HAVE_PDLAQR1 OR 
     NOT ELEM_HAVE_CSYS2BLACS)
    message(STATUS "ScaLAPACK must support PDLAQR{0,1} and Csys2blacs_handle.")
    set(ELEM_HAVE_SCALAPACK FALSE)
  else()
    set(ELEM_HAVE_SCALAPACK TRUE)
  endif()
  set(ELEM_SCALAPACK_POST FALSE)
  set(ELEM_SCALAPACK_DEFS "")
elseif(ELEM_HAVE_PDSYNGST_POST)
  check_function_exists(pdlaqr0_ ELEM_HAVE_PDLAQR0_POST)
  check_function_exists(pdlaqr1_ ELEM_HAVE_PDLAQR1_POST)
  if(NOT ELEM_HAVE_PDLAQR0_POST OR NOT ELEM_HAVE_PDLAQR1_POST OR
     NOT ELEM_HAVE_CSYS2BLACS)
    message(STATUS "ScaLAPACK must support PDLAQR{0,1} and Csys2blacs_handle.")
  else()
    set(ELEM_HAVE_SCALAPACK TRUE)
  endif()
  set(ELEM_SCALAPACK_POST TRUE)
  set(ELEM_SCALAPACK_DEFS "-DBLAS_POST")
else()
  set(ELEM_HAVE_SCALAPACK FALSE)
  message(STATUS "ScaLAPACK was NOT detected.")
endif()
