# - Find CBLAS library
#
# This module finds a library that implements the CBLAS  interface.
#
# This module sets the following variables:
#  CBLAS_FOUND - set to true if a library implementing the CBLAS interface
#    is found
#  CBLAS_LINKER_FLAGS - uncached list of required linker flags (excluding -l
#    and -L).
#  CBLAS_LIBRARIES - uncached list of libraries (using full path name) to 
#    link against to use CBLAS
#  CBLAS_INCLUDE_DIR - path to includes
#  CBLAS_INCLUDE_FILE - the file to be included to use CBLAS
#
# The module also checks:
#  CBLA_VENDOR  if set checks only the specified vendor, if not set checks
#     all the possibilities
#
# Adapted from Torch5 build system and the standard
# FindBLAS.cmake from CMake 2.8

INCLUDE(CheckFunctionExists)
INCLUDE(CheckIncludeFile)

MACRO(CHECK_ALL_LIBRARIES LIBRARIES _prefix _name _flags _list _include _search_include _thread)
  # This macro checks for the existence of the combination of fortran libraries
  # given by _list.  If the combination is found, this macro checks (using the 
  # Check_Fortran_Function_Exists macro) whether can link against that library
  # combination using the name of a routine given by _name using the linker
  # flags given by _flags.  If the combination of libraries is found and passes
  # the link test, LIBRARIES is set to the list of complete library paths that
  # have been found.  Otherwise, LIBRARIES is set to FALSE.
  
  # N.B. _prefix is the prefix applied to the names of all cached variables that
  # are generated internally and marked advanced by this macro.

  SET(__list)
  FOREACH(_elem ${_list})
    IF(__list)
      SET(__list "${__list} - ${_elem}")
    ELSE(__list)
      SET(__list "${_elem}")
    ENDIF(__list)
  ENDFOREACH(_elem)
  MESSAGE(STATUS "Checking for [${__list}]")
  SET(_libraries_work TRUE)
  SET(${LIBRARIES})
  SET(_combined_name)
  SET(_paths)
  FOREACH(_library ${_list})
    SET(_combined_name ${_combined_name}_${_library})

    # did we find all the libraries in the _list until now?
    # (we stop at the first unfound one)
    IF(_libraries_work)      
      IF(APPLE) 
        FIND_LIBRARY(${_prefix}_${_library}_LIBRARY
          NAMES ${_library}
          PATHS ${CBLAS_LIBRARY_DIR}
          PATHS /usr/local/lib /usr/lib /usr/local/lib64 /usr/lib64
          PATHS ENV LIBRARY_PATH
          PATHS ENV DYLD_LIBRARY_PATH 
          )
      ELSE(APPLE)
        FIND_LIBRARY(${_prefix}_${_library}_LIBRARY
          NAMES ${_library}
          PATHS ${CBLAS_LIBRARY_DIR} ${CBLAS_DIR}/lib
          PATHS /usr/local/lib /usr/lib /usr/local/lib64 /usr/lib64
          PATHS ENV LIBRARY_PATH
          PATHS ENV LD_LIBRARY_PATH
          )
      ENDIF(APPLE)
      MARK_AS_ADVANCED(${_prefix}_${_library}_LIBRARY)
      IF(${_prefix}_${_library}_LIBRARY)
        GET_FILENAME_COMPONENT(_path ${${_prefix}_${_library}_LIBRARY} PATH)
        LIST(APPEND _paths ${_path}/../include ${_path}/../../include)
      ENDIF(${_prefix}_${_library}_LIBRARY)
      SET(${LIBRARIES} ${${LIBRARIES}} ${${_prefix}_${_library}_LIBRARY})
      SET(_libraries_work ${${_prefix}_${_library}_LIBRARY})
    ENDIF(_libraries_work)
  ENDFOREACH(_library ${_list})

  # Test include
  SET(_bug_search_include ${_search_include}) #CMAKE BUG!!! SHOULD NOT BE THAT
  IF(_bug_search_include)
    FIND_PATH(${_prefix}${_combined_name}_INCLUDE ${_include} ${_paths}
              PATHS ${CBLAS_INCLUDE_DIR} ${CBLAS_DIR}/include ENV INCLUDE)
    MARK_AS_ADVANCED(${_prefix}${_combined_name}_INCLUDE)
    IF(${_prefix}${_combined_name}_INCLUDE)
      MESSAGE(STATUS "Checking for [${__list}] -- includes found")
      SET(${_prefix}_INCLUDE_DIR ${${_prefix}${_combined_name}_INCLUDE})
      SET(${_prefix}_INCLUDE_FILE ${_include})
    ELSE(${_prefix}${_combined_name}_INCLUDE)
      MESSAGE(STATUS "Checking for [${__list}] -- includes not found")
      SET(_libraries_work FALSE)
    ENDIF(${_prefix}${_combined_name}_INCLUDE)
  ELSE(_bug_search_include)
    SET(${_prefix}_INCLUDE_DIR)
    SET(${_prefix}_INCLUDE_FILE ${_include})
  ENDIF(_bug_search_include)

  IF(_libraries_work)
    # Test this combination of libraries.
    SET(CMAKE_REQUIRED_LIBRARIES ${_flags} ${${LIBRARIES}} ${_thread})
    CHECK_FUNCTION_EXISTS(${_name} ${_prefix}${_combined_name}_WORKS)
    SET(CMAKE_REQUIRED_LIBRARIES)
    MARK_AS_ADVANCED(${_prefix}${_combined_name}_WORKS)
    SET(_libraries_work ${${_prefix}${_combined_name}_WORKS})

    IF(_libraries_work)
      MESSAGE(STATUS "Checking for [${__list}] -- libraries found")
    ENDIF(_libraries_work)

  ENDIF(_libraries_work)
  

  IF(NOT _libraries_work)
    SET(${LIBRARIES} FALSE)
  ENDIF(NOT _libraries_work)

ENDMACRO(CHECK_ALL_LIBRARIES)

SET(CBLAS_LINKER_FLAGS)
SET(CBLAS_LIBRARIES)

if ($ENV{CBLA_VENDOR} MATCHES ".+")
  set(CBLA_VENDOR $ENV{CBLA_VENDOR})
else ()
  if(NOT CBLA_VENDOR)
    set(CBLA_VENDOR "All")
  endif()
endif ()

IF (CBLA_VENDOR MATCHES "Intel*" OR CBLA_VENDOR STREQUAL "All")

  if (NOT WIN32)
    set(LM "-lm")
  endif ()

  if(BLAS_FIND_QUIETLY OR NOT BLAS_FIND_REQUIRED)
    find_package(Threads)
  else()
    find_package(Threads REQUIRED)
  endif()

  set(_LIBRARIES CBLAS_LIBRARIES)
  if (WIN32)
    list(APPEND CBLAS_SEARCH_LIBS
         "mkl_c_dll mkl_intel_thread_dll mkl_core_dll libguide40")
  else ()

    if (CBLA_VENDOR STREQUAL "Intel10_32" OR CBLA_VENDOR STREQUAL "All")
      list(APPEND CBLAS_SEARCH_LIBS
           "mkl_intel mkl_intel_thread mkl_core guide")
    endif ()

    if (CBLA_VENDOR STREQUAL "Intel10_64lp" OR CBLA_VENDOR STREQUAL "All")

      # old version
      list(APPEND CBLAS_SEARCH_LIBS
           "mkl_intel_lp64 mkl_intel_thread mkl_core guide")

      # mkl >= 10.3
      if (CMAKE_C_COMPILER MATCHES ".+gcc.*")
        list(APPEND CBLAS_SEARCH_LIBS
             "mkl_intel_lp64 mkl_gnu_thread mkl_core gomp")
      else ()
        list(APPEND CBLAS_SEARCH_LIBS
             "mkl_intel_lp64 mkl_intel_thread mkl_core iomp5")
      endif ()

      #older vesions of intel mkl libs
      if (BLA_VENDOR STREQUAL "Intel" OR BLA_VENDOR STREQUAL "All")
        list(APPEND CBLAS_SEARCH_LIBS
          "mkl")
        list(APPEND CBLAS_SEARCH_LIBS
          "mkl_ia32")
        list(APPEND CBLAS_SEARCH_LIBS
          "mkl_em64t")
      endif ()

    endif ()

    if (CBLA_VENDOR STREQUAL "Intel10_64lp_seq" OR CBLA_VENDOR STREQUAL "All")
      list(APPEND CBLAS_SEARCH_LIBS
           "mkl_intel_lp64 mkl_sequential mkl_core")
    endif ()

  endif()

  foreach (IT ${CBLAS_SEARCH_LIBS})
    string(REPLACE " " ";" SEARCH_LIBS ${IT})
    if (${_LIBRARIES})
    else ()
      CHECK_ALL_LIBRARIES(
        CBLAS_LIBRARIES
        CBLAS
        cblas_sgemm
        ""
        "${SEARCH_LIBS}"
        "mkl_cblas.h"
        TRUE
        "${CMAKE_THREAD_LIBS_INIT};${LM}"
      )
    endif ()
  endforeach ()
    
ENDIF()

# Apple CBLAS library?
IF (CBLA_VENDOR STREQUAL "Apple" OR CBLA_VENDOR STREQUAL "All")

  IF(NOT CBLAS_LIBRARIES)
    CHECK_ALL_LIBRARIES(
      CBLAS_LIBRARIES
      CBLAS
      cblas_dgemm
      ""
      "Accelerate"
      "Accelerate/Accelerate.h"
      FALSE
      ""
      )
  ENDIF(NOT CBLAS_LIBRARIES)

  # CBLAS in vecLib?
  IF( NOT CBLAS_LIBRARIES )
    CHECK_ALL_LIBRARIES(
      CBLAS_LIBRARIES
      CBLAS
      cblas_dgemm
      ""
      "vecLib"
      "vecLib/vecLib.h"
      FALSE
      ""
      )
  ENDIF( NOT CBLAS_LIBRARIES )
    
ENDIF ()

# CBLAS in ATLAS library? (http://math-atlas.sourceforge.net/)
IF (CBLA_VENDOR STREQUAL "Goto" OR CBLA_VENDOR STREQUAL "All")
  IF(NOT CBLAS_LIBRARIES)
    CHECK_ALL_LIBRARIES(
      CBLAS_LIBRARIES
      CBLAS
      cblas_dgemm
      ""
      "cblas;f77blas;atlas"
      "cblas.h"
      TRUE
      ""
      )
  ENDIF(NOT CBLAS_LIBRARIES)
ENDIF()

# CBLAS in Goto?
IF (CBLA_VENDOR STREQUAL "Goto" OR CBLA_VENDOR STREQUAL "All")
  IF(NOT CBLAS_LIBRARIES)
    CHECK_ALL_LIBRARIES(
      CBLAS_LIBRARIES
      CBLAS
      cblas_dgemm
      ""
      "goto2"
      "cblas.h"
      TRUE
      ""
      )
  ENDIF(NOT CBLAS_LIBRARIES)
ENDIF()

# CBLAS in OpenBLAS?
IF (CBLA_VENDOR STREQUAL "Goto" OR CBLA_VENDOR STREQUAL "All")
  IF(NOT CBLAS_LIBRARIES)
    CHECK_ALL_LIBRARIES(
      CBLAS_LIBRARIES
      CBLAS
      cblas_dgemm
      ""
      "openblas"
      "cblas.h"
      TRUE
      ""
      )
  ENDIF(NOT CBLAS_LIBRARIES)
ENDIF()

# CBLAS in generic libcblas?
IF (CBLA_VENDOR STREQUAL "Generic" OR CBLA_VENDOR STREQUAL "All")
  IF(NOT CBLAS_LIBRARIES)
    CHECK_ALL_LIBRARIES(
      CBLAS_LIBRARIES
      CBLAS
      cblas_dgemm
      ""
      "cblas"
      "cblas.h"
      TRUE
      ""
      )
  ENDIF(NOT CBLAS_LIBRARIES)
ENDIF()

IF(CBLAS_LIBRARIES)
  SET(CBLAS_FOUND TRUE)
ELSE(CBLAS_LIBRARIES)
  SET(CBLAS_FOUND FALSE)
ENDIF(CBLAS_LIBRARIES)

IF(NOT CBLAS_FOUND AND CBLAS_FIND_REQUIRED)
  MESSAGE(FATAL_ERROR "CBLAS library not found. Please specify library  location")
ENDIF(NOT CBLAS_FOUND AND CBLAS_FIND_REQUIRED)

IF(NOT CBLAS_FIND_QUIETLY)
  IF(CBLAS_FOUND)
    MESSAGE(STATUS "CBLAS library found")
  ELSE(CBLAS_FOUND)
    MESSAGE(STATUS "CBLAS library not found. Please specify library location")
  ENDIF(CBLAS_FOUND)
ENDIF(NOT CBLAS_FIND_QUIETLY)
