├── .github └── workflows │ ├── ci_cmake.yml │ └── ci_meson.yml ├── .gitignore ├── CMakeLists.txt ├── LICENSE ├── README.md ├── archive ├── .appveyor.yml ├── .travis.yml ├── build.py ├── build_intel.bat ├── build_msvc.bat └── build_pgi.bat ├── build_atlas.sh ├── build_mkl.sh ├── c_src ├── CMakeLists.txt ├── example_gesvd.c └── meson.build ├── cmake └── Modules │ └── FindLAPACK.cmake ├── factory └── CMakeLists.txt ├── fortran_src ├── CMakeLists.txt ├── atlas_svd.f90 ├── blas_matmul.f90 ├── example_gesvd.f90 ├── lapack_svd.f90 └── meson.build ├── meson.build ├── meson_options.txt ├── subprojects └── lapack.wrap └── test_build.sh /.github/workflows/ci_cmake.yml: -------------------------------------------------------------------------------- 1 | name: ci_cmake 2 | 3 | on: 4 | push: 5 | paths: 6 | - "**.f90" 7 | - "**.F90" 8 | - "**.cmake" 9 | - "**/CMakeLists.txt" 10 | - ".github/workflows/ci_cmake.yml" 11 | 12 | jobs: 13 | 14 | linux: 15 | runs-on: ubuntu-latest 16 | steps: 17 | - uses: actions/checkout@v2 18 | 19 | - run: | 20 | sudo apt update -yq 21 | sudo apt install -yq --no-install-recommends gfortran liblapack-dev liblapacke-dev 22 | 23 | - run: cmake -B build 24 | - run: cmake --build build 25 | - run: ctest --test-dir build 26 | -------------------------------------------------------------------------------- /.github/workflows/ci_meson.yml: -------------------------------------------------------------------------------- 1 | name: ci_meson 2 | 3 | on: 4 | push: 5 | paths: 6 | - "**/meson.build" 7 | - ".github/workflows/ci_meson.yml" 8 | 9 | jobs: 10 | 11 | linux: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/checkout@v2 15 | - uses: actions/setup-python@v2 16 | with: 17 | python-version: '3.x' 18 | - run: pip install meson 19 | - run: | 20 | sudo apt update -yq 21 | sudo apt install -yq --no-install-recommends ninja-build gfortran liblapack-dev liblapacke-dev 22 | 23 | - run: meson setup build 24 | - run: meson compile -C build 25 | 26 | - run: meson test -C build -v 27 | 28 | windows: 29 | if: false 30 | runs-on: windows-latest 31 | steps: 32 | - uses: actions/checkout@v2 33 | - uses: actions/setup-python@v2 34 | with: 35 | python-version: '3.x' 36 | - run: | 37 | pip install meson ninja 38 | 39 | - run: meson setup build 40 | - run: meson compile -C build 41 | 42 | - run: meson test -C build -v 43 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .mypy_cache/ 2 | build/ 3 | CMakeCache.txt 4 | CMakeFiles 5 | CMakeScripts 6 | Testing 7 | Makefile 8 | cmake_install.cmake 9 | install_manifest.txt 10 | compile_commands.json 11 | CTestTestfile.cmake 12 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.19...3.21) 2 | 3 | project(lapack_demo LANGUAGES C) 4 | 5 | enable_testing() 6 | 7 | option(atlas "Atlas Lapack implementation") 8 | option(lapack95 "use Lapack95") 9 | option(USEOpenBLAS "OpenBLAS") 10 | 11 | # this ensures we use our clean FindLapack, instead of old factory FindLapack 12 | list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules) 13 | 14 | # if working Fortran compiler present, enable Fortran before searching for libraries 15 | include(CheckLanguage) 16 | check_language(Fortran) 17 | if(CMAKE_Fortran_COMPILER) 18 | enable_language(Fortran) 19 | endif() 20 | 21 | # Now we're ready to Find Lapack 22 | if(atlas) 23 | set(USEMKL 0) 24 | find_package(LAPACK COMPONENTS Atlas REQUIRED) 25 | set(atlas 1) 26 | elseif(USEMKL OR DEFINED ENV{MKLROOT}) 27 | set(USEMKL 1) 28 | if(lapack95) 29 | find_package(LAPACK COMPONENTS MKL LAPACK95 REQUIRED) 30 | else() 31 | find_package(LAPACK COMPONENTS MKL REQUIRED) 32 | endif() 33 | elseif(USEOpenBLAS) 34 | set(USEMKL 0) 35 | set(USEOpenBLAS 1) 36 | find_package(LAPACK COMPONENTS OpenBLAS REQUIRED) 37 | else() 38 | set(USEMKL 0) 39 | find_package(LAPACK COMPONENTS Netlib LAPACKE) # netlib -- apt install liblapacke-dev 40 | endif() 41 | 42 | # Last ditch fallback 43 | if(NOT LAPACK_FOUND) 44 | find_package(LAPACK) 45 | endif() 46 | 47 | # here are some exmaple programs using Lapack 48 | if(LAPACK_MKL_FOUND OR LAPACK_OpenBLAS_FOUND OR LAPACK_Atlas_FOUND OR LAPACK_LAPACKE_FOUND) 49 | add_subdirectory(c_src) 50 | endif() 51 | 52 | if(CMAKE_Fortran_COMPILER AND LAPACK_FOUND) 53 | add_subdirectory(fortran_src) 54 | endif() 55 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2019, Michael Hirsch, Ph.D. 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | * Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Lapack with Meson or CMake 2 | 3 | ![Actions Status](https://github.com/scivision/lapack-cmake-meson/workflows/ci_cmake/badge.svg) 4 | ![Actions Status](https://github.com/scivision/lapack-cmake-meson/workflows/ci_meson/badge.svg) 5 | 6 | A clean, modern 7 | [FindLAPACK.cmake](./cmake/Modules/FindLAPACK.cmake) 8 | with verified compatibility across a wide range of compilers, operating systems and Lapack vendors. 9 | Optionally, uses PkgConfig in CMake to make finding Lapack / LapackE more robust. 10 | 11 | 12 | ## CMake 13 | 14 | Here is a brief listing of known working configurations: 15 | 16 | Windows: 17 | 18 | Compiler | Lapack 19 | ---------|------- 20 | MSVC 15 2017 | Intel MKL 21 | PGI | Intel MKL 22 | 23 | 24 | Linux: 25 | 26 | Compiler | Lapack 27 | ---------|------- 28 | gcc + gfortran | Netlib Lapack 29 | gcc + gfortran | Intel MKL 30 | gcc + gfortran | Atlas 31 | gcc + gfortran | OpenBLAS 32 | Clang + gfortran | Netlib Lapack 33 | Clang + gfortran | Intel MKL 34 | Clang + gfortran | Atlas 35 | Clang + gfortran | OpenBLAS 36 | Clang + Flang | Netlib Lapack 37 | Clang + Flang | Intel MKL 38 | Clang + Flang | Atlas 39 | Clang + Flang | OpenBLAS 40 | 41 | ### Example 42 | 43 | This example is for SVD computation using LapackE from C. 44 | 45 | For most non-MSVC compilers (e.g. GNU, PGI, Clang, etc.): 46 | 47 | ```sh 48 | ctest -S setup.cmake -VV 49 | ``` 50 | 51 | If you have a Fortran compiler, a Fortran Lapack example will also be built and tested. 52 | 53 | 54 | For MSVC compilers, only the C example is built, and requires Intel MKL: 55 | 56 | ```sh 57 | cmake -G "Visual Studio 16 2019" -B build 58 | 59 | cmake --build build 60 | ``` 61 | 62 | ## Meson 63 | 64 | Lapack with Meson works with similar compiler configurations as CMake. 65 | 66 | ```sh 67 | meson build 68 | 69 | meson test -C build 70 | ``` 71 | 72 | to use MKL with Meson, do like 73 | 74 | ```sh 75 | meson build -DMKL_ROOT=$MKLROOT # linux 76 | ``` 77 | 78 | 79 | ## prereq 80 | 81 | * Linux: `apt install liblapacke-dev` 82 | * Mac: `brew install lapack` 83 | * Windows: compile [Lapack from source](https://github.com/Reference-LAPACK/lapack), or use [Windows Subsystem for Linux](https://docs.microsoft.com/en-us/windows/wsl/install-win10). 84 | 85 | 86 | ### Intel MKL 87 | 88 | Intel MKL is automatically detected by if 89 | [`MKLROOT` environment variable is set](https://software.intel.com/en-us/mkl-windows-developer-guide-checking-your-installation). 90 | This variable should be set BEFORE using CMake as proscribed by Intel for your operating system, typically by running `mklvars` script. 91 | Here I assume you've installed MKL as appropriate for the 92 | [MKL directory structure](https://software.intel.com/en-us/mkl-windows-developer-guide-high-level-directory-structure). 93 | 94 | The command used to activate Intel MKL for each Terminal / Command Prompt session is like: 95 | 96 | * Linux: `source ~/intel/mkl/bin/mklvars.sh intel64` 97 | * Mac: `source ~/intel/mkl/bin/mklvars.sh intel64` 98 | * Windows: `c:\"Program Files (x86)"\IntelSWTools\compilers_and_libraries\windows\mkl\bin\mklvars.bat intel64` 99 | 100 | You need to do this EVERY TIME you want to use MKL for the Terminal / Command Prompt, or run it automatically at startup. 101 | What we usually do is create a script in the home directory that simply runs that command when called. 102 | 103 | To verify 104 | [Intel MKL](https://software.intel.com/en-us/mkl) 105 | was used, run a program with `MKL_VERBOSE=1` like: 106 | 107 | * Mac / Linux: `MKL_VERBOSE=1 ./build/svd_c` 108 | * Windows: 109 | 110 | ```posh 111 | set MKL_VERBOSE=1 112 | 113 | build\c_src\Debug\svd_c 114 | ``` 115 | 116 | #### Windows 117 | 118 | * On Windows, MinGW is not supported with MKL at least through MKL 2019--you will get all kinds of errors. 119 | * Windows CMake systems that don't want to use MSVC must in general include `cmake -G "MinGW Makefiles"` along with their other options. 120 | This is true for anything CMake is used for on Windows where Visual Studio is not wanted. 121 | -------------------------------------------------------------------------------- /archive/.appveyor.yml: -------------------------------------------------------------------------------- 1 | image: 2 | - Visual Studio 2017 3 | - Ubuntu1804 4 | 5 | environment: 6 | MINGW_DIR: C:\mingw-w64\x86_64-7.2.0-posix-seh-rt_v5-rev1\mingw64\bin 7 | 8 | clone_depth: 25 9 | 10 | build: off 11 | 12 | init: 13 | - cmd: set PATH=%MINGW_DIR%;%PATH% 14 | 15 | install: 16 | - cd build 17 | - cmd: cmake -G "MinGW Makefiles" -DCMAKE_SH="CMAKE_SH-NOTFOUND" .. 18 | - sh: cmake .. 19 | 20 | - cmake --build . --target install 21 | 22 | test_script: ctest --output-on-failure 23 | -------------------------------------------------------------------------------- /archive/.travis.yml: -------------------------------------------------------------------------------- 1 | language: minimal 2 | group: travis_latest 3 | dist: xenial 4 | 5 | git: 6 | depth: 25 7 | quiet: true 8 | 9 | env: FC=gfortran-6 10 | 11 | addons: 12 | apt: 13 | sources: ubuntu-toolchain-r-test 14 | packages: 15 | - liblapacke-dev 16 | - gfortran-6 17 | 18 | matrix: 19 | include: 20 | - os: linux 21 | # - windows # needs gfortran, straightforward to add but already on appveyor 22 | # - os: osx 23 | # env: FC=gfortran 24 | # before_install: 25 | # - brew install gcc > /dev/null 26 | # - brew install lapack > /dev/null 27 | # lapackE is not in brew at this time 28 | 29 | install: 30 | - cd build 31 | 32 | - cmake .. 33 | 34 | - cmake --build . 35 | 36 | script: ctest --output-on-failure 37 | -------------------------------------------------------------------------------- /archive/build.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """ 3 | 4 | ## PGI 5 | 6 | We assume you're running from the PGI console on Windows, or otherwise have PATH set 7 | to PGI compilers in environment before running this script. 8 | 9 | 10 | ## Intel 11 | 12 | We assume you've already: 13 | 14 | * Windows: compilervars.bat intel64 15 | * Linux / Mac: source compilervars.sh intel64 16 | 17 | or otherwise set environment variable MKLROOT. 18 | This is how Numpy finds Intel MKL / compilers as well. 19 | 20 | ## MKL 21 | 22 | MSVC requires MKL too 23 | 24 | """ 25 | from pathlib import Path 26 | import os 27 | import shutil 28 | import subprocess 29 | from typing import Dict, List, Tuple 30 | from argparse import ArgumentParser 31 | 32 | MSVC = 'Visual Studio 15 2017' 33 | 34 | 35 | # %% function 36 | def do_build(build: Path, src: Path, 37 | compilers: Dict[str, str], 38 | args: List[str], 39 | wipe: bool = True, 40 | dotest: bool = True, 41 | install: str = None): 42 | """ 43 | attempts build with Meson or CMake 44 | TODO: Meson needs better Lapack finding 45 | """ 46 | # try: 47 | # meson_setup(build, src, compilers, args, wipe, dotest, install) 48 | # except (ImportError, FileNotFoundError, RuntimeError): 49 | # cmake_setup(build, src, compilers, args, wipe, dotest, install) 50 | 51 | cmake_setup(build, src, compilers, args, wipe, dotest, install) 52 | 53 | 54 | def _needs_wipe(fn: Path, wipe: bool) -> bool: 55 | if not fn.is_file(): 56 | return False 57 | 58 | with fn.open() as f: 59 | for line in f: 60 | if line.startswith('CMAKE_C_COMPILER:FILEPATH'): 61 | cc = line.split('/')[-1] 62 | if cc != compilers['CC']: 63 | wipe = True 64 | break 65 | elif line.startswith('CMAKE_GENERATOR:INTERNAL'): 66 | gen = line.split('=')[-1] 67 | if gen.startswith('Unix') and os.name == 'nt': 68 | wipe = True 69 | break 70 | elif gen.startswith(('MinGW', 'Visual')) and os.name != 'nt': 71 | wipe = True 72 | break 73 | elif gen.startswith('Visual') and compilers['CC'] != 'cl': 74 | wipe = True 75 | break 76 | 77 | return wipe 78 | 79 | 80 | def cmake_setup(build: Path, src: Path, compilers: Dict[str, str], 81 | args: List[str], 82 | wipe: bool = True, dotest: bool = True, 83 | install: str = None): 84 | """ 85 | attempt to build using CMake >= 3 86 | """ 87 | cmake_exe = shutil.which('cmake') 88 | if not cmake_exe: 89 | raise FileNotFoundError('CMake not available') 90 | 91 | if compilers['CC'] == 'cl': 92 | wopts = ['-G', MSVC, '-A', 'x64'] 93 | elif os.name == 'nt': 94 | wopts = ['-G', 'MinGW Makefiles', '-DCMAKE_SH="CMAKE_SH-NOTFOUND'] 95 | else: 96 | wopts = [] 97 | 98 | wopts += args 99 | 100 | if isinstance(install, str) and install.strip(): # path specified 101 | wopts.append('-DCMAKE_INSTALL_PREFIX:PATH='+str(Path(install).expanduser())) 102 | 103 | cachefile = build / 'CMakeCache.txt' 104 | 105 | wipe = _needs_wipe(cachefile, wipe) 106 | 107 | if wipe and cachefile.is_file(): 108 | cachefile.unlink() 109 | 110 | subprocess.check_call([cmake_exe] + wopts + [str(src)], 111 | cwd=build, env=os.environ.update(compilers)) 112 | 113 | ret = subprocess.run([cmake_exe, '--build', str(build)], 114 | stderr=subprocess.PIPE, 115 | universal_newlines=True) 116 | 117 | test_result(ret) 118 | if ret.returncode: 119 | return 120 | # %% test 121 | if dotest: 122 | ctest_exe = shutil.which('ctest') 123 | if not ctest_exe: 124 | raise FileNotFoundError('CTest not available') 125 | 126 | if compilers['CC'] == 'cl': 127 | subprocess.check_call([cmake_exe, '--build', str(build), '--target', 'RUN_TESTS']) 128 | else: 129 | subprocess.check_call([ctest_exe, '--output-on-failure'], cwd=build) 130 | # %% install 131 | if install is not None: # blank '' or ' ' etc. will use dfault install path 132 | subprocess.check_call([cmake_exe, '--build', str(build), '--target', 'install']) 133 | 134 | 135 | def meson_setup(build: Path, src: Path, compilers: Dict[str, str], 136 | args: List[str], 137 | wipe: bool = True, dotest: bool = True, 138 | install: str = None): 139 | """ 140 | attempt to build with Meson + Ninja 141 | """ 142 | 143 | meson_exe = [shutil.which('meson')] 144 | 145 | ninja_exe = shutil.which('ninja') 146 | 147 | if not meson_exe or not ninja_exe: 148 | raise FileNotFoundError('Meson or Ninja not available') 149 | 150 | build_ninja = build / 'build.ninja' 151 | 152 | meson_setup = meson_exe + ['setup'] + args 153 | 154 | if isinstance(install, str) and install.strip(): # path specified 155 | meson_setup.append('--prefix '+str(Path(install).expanduser())) 156 | 157 | if wipe and build_ninja.is_file(): 158 | meson_setup.append('--wipe') 159 | meson_setup += [str(build), str(src)] 160 | 161 | if wipe or not build_ninja.is_file(): 162 | subprocess.check_call(meson_setup, env=os.environ.update(compilers)) 163 | 164 | ret = subprocess.run([ninja_exe, '-C', str(build)], stderr=subprocess.PIPE, 165 | universal_newlines=True) 166 | 167 | test_result(ret) 168 | 169 | if dotest: 170 | if not ret.returncode: 171 | subprocess.check_call([meson_exe, 'test', '-C', str(build)]) # type: ignore # MyPy bug 172 | 173 | if install: 174 | if not ret.returncode: 175 | subprocess.check_call([meson_exe, 'install', '-C', str(build)]) # type: ignore # MyPy bug 176 | 177 | 178 | def test_result(ret: subprocess.CompletedProcess): 179 | if not ret.returncode: 180 | print('\nBuild Complete!') 181 | else: 182 | raise RuntimeError(ret.stderr) 183 | 184 | 185 | # %% compilers 186 | def clang_params(impl: str) -> Tuple[Dict[str, str], List[str]]: 187 | compilers = {'CC': 'clang', 'CXX': 'clang++', 'FC': 'flang'} 188 | 189 | if impl == 'atlas': 190 | args = ['-Datlas=1'] 191 | elif impl == 'mkl': 192 | args = ['-DUSEMKL=1'] 193 | elif impl == 'openblas': 194 | args = ['-DUSEOpenBLAS=1'] 195 | else: 196 | args = [] 197 | 198 | return compilers, args 199 | 200 | 201 | def gnu_params(impl: str) -> Tuple[Dict[str, str], List[str]]: 202 | compilers = {'FC': 'gfortran', 'CC': 'gcc', 'CXX': 'g++'} 203 | 204 | if impl == 'atlas': 205 | args = ['-Datlas=1'] 206 | elif impl == 'mkl': 207 | args = ['-DUSEMKL=1'] 208 | elif impl == 'openblas': 209 | args = ['-DUSEOpenBLAS=1'] 210 | else: 211 | args = [] 212 | 213 | return compilers, args 214 | 215 | 216 | def intel_params() -> Tuple[Dict[str, str], List[str]]: 217 | if not os.environ.get('MKLROOT'): 218 | raise EnvironmentError('must have set MKLROOT by running compilervars.bat or source compilervars.sh before this script.') 219 | 220 | # %% compiler variables 221 | compilers = {'FC': 'ifort'} 222 | if os.name == 'nt': 223 | compilers['CC'] = compilers['CXX'] = 'icl' 224 | else: 225 | compilers['CC'] = 'icc' 226 | compilers['CXX'] = 'icpc' 227 | 228 | args: List[str] = [] 229 | 230 | return compilers, args 231 | 232 | 233 | def msvc_params() -> Tuple[Dict[str, str], List[str]]: 234 | if not shutil.which('cl'): 235 | raise EnvironmentError('Must have PATH set to include MSVC cl.exe compiler bin directory') 236 | 237 | compilers = {'CC': 'cl', 'CXX': 'cl'} 238 | 239 | args: List[str] = [] 240 | 241 | return compilers, args 242 | 243 | 244 | def pgi_params(impl: str) -> Tuple[Dict[str, str], List[str]]: 245 | if not shutil.which('pgcc') or not shutil.which('pgfortran'): 246 | raise EnvironmentError('Must have PATH set to include PGI compiler bin directory') 247 | 248 | # %% compiler variables 249 | compilers = {'FC': 'pgfortran', 'CC': 'pgcc'} 250 | if os.name != 'nt': 251 | # pgc++ is not on Windows at this time 252 | compilers['CXX'] = 'pgc++' 253 | 254 | if impl == 'atlas': 255 | args = ['-Datlas=1'] 256 | elif impl == 'mkl': 257 | args = ['-DUSEMKL=1'] 258 | elif impl == 'openblas': 259 | args = ['-DUSEOpenBLAS=1'] 260 | else: 261 | args = [] 262 | 263 | return compilers, args 264 | 265 | 266 | if __name__ == '__main__': 267 | p = ArgumentParser() 268 | p.add_argument('vendor', help='compiler vendor [clang, gnu, intel, msvc, pgi]') 269 | p.add_argument('-wipe', help='wipe and rebuild from scratch', action='store_true') 270 | p.add_argument('-i', '--implementation', 271 | help='which LAPACK implementation') 272 | p.add_argument('-n', '--no-test', help='do not run self-test / example', action='store_false') 273 | p.add_argument('-install', help='specify directory to install to') 274 | a = p.parse_args() 275 | # Must have .resolve() to work in general regardless of invocation directory 276 | src = Path(__file__).parent.resolve() 277 | build = src / 'build' 278 | 279 | dotest = a.no_test 280 | 281 | if a.vendor == 'clang': 282 | compilers, args = clang_params(a.implementation) 283 | elif a.vendor in ('gnu', 'gcc'): 284 | compilers, args = gnu_params(a.implementation) 285 | elif a.vendor == 'intel': 286 | compilers, args = intel_params() 287 | elif a.vendor == 'msvc': 288 | compilers, args = msvc_params() 289 | elif a.vendor == 'pgi': 290 | compilers, args = pgi_params(a.implementation) 291 | else: 292 | raise ValueError('unknown compiler vendor {}'.format(a.vendor)) 293 | 294 | do_build(build, src, compilers, args, a.wipe, dotest, a.install) 295 | -------------------------------------------------------------------------------- /archive/build_intel.bat: -------------------------------------------------------------------------------- 1 | call C:\"Program Files (x86)"\IntelSWTools\compilers_and_libraries\windows\bin\compilervars.bat intel64 2 | 3 | cd build 4 | 5 | del CMakeCache.txt 6 | 7 | set FC=ifort 8 | set CC=icl 9 | 10 | cmake -G "MinGW Makefiles" .. 11 | 12 | cmake --build . 13 | 14 | set MKL_VERBOSE=1 15 | 16 | ctest -V -------------------------------------------------------------------------------- /archive/build_msvc.bat: -------------------------------------------------------------------------------- 1 | call c:\"Program Files (x86)"\IntelSWTools\compilers_and_libraries\windows\mkl\bin\mklvars.bat intel64 2 | 3 | cd build 4 | 5 | del CMakeCache.txt 6 | 7 | cmake -G "Visual Studio 15 2017" -A x64 .. 8 | 9 | cmake --build . 10 | 11 | set MKL_VERBOSE=1 12 | 13 | cmake --build . --target RUN_TESTS -------------------------------------------------------------------------------- /archive/build_pgi.bat: -------------------------------------------------------------------------------- 1 | call c:\"Program Files (x86)"\IntelSWTools\compilers_and_libraries\windows\mkl\bin\mklvars.bat intel64 2 | 3 | cd build 4 | 5 | del CMakeCache.txt 6 | 7 | set FC=pgfortran 8 | set CC=pgcc 9 | 10 | cmake -G "MinGW Makefiles" .. 11 | 12 | cmake --build . 13 | 14 | set MKL_VERBOSE=1 15 | 16 | ctest -V -------------------------------------------------------------------------------- /build_atlas.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | cc=$1 6 | fc=$2 7 | 8 | cd "${0%/*}" # change to directory of this script 9 | 10 | bindir=build 11 | 12 | rm -f $bindir/CMakeCache.txt 13 | 14 | CC=$cc FC=$fc cmake -Datlas=1 -B $bindir 15 | 16 | ctest -S setup.cmake -VV 17 | -------------------------------------------------------------------------------- /build_mkl.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | cc=$1 6 | fc=$2 7 | 8 | cd "${0%/*}" # change to directory of this script 9 | 10 | . ~/intel.sh # source mklvars.sh 11 | 12 | bindir=build 13 | 14 | rm -f $bindir/CMakeCache.txt 15 | 16 | CC=$cc FC=$fc cmake -B $bindir 17 | 18 | ctest -S setup.cmake -VV 19 | -------------------------------------------------------------------------------- /c_src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(need_gf GNU Clang) 2 | 3 | if(NOT USEMKL AND CMAKE_C_COMPILER_ID IN_LIST need_gf) 4 | list(APPEND LDFLAGS -lgfortran) 5 | endif() 6 | 7 | if(NOT WIN32) 8 | list(APPEND LDFLAGS m) 9 | endif() 10 | 11 | add_executable(svd_c example_gesvd.c) 12 | target_include_directories(svd_c PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) 13 | target_link_libraries(svd_c PRIVATE LAPACK::LAPACK) 14 | target_compile_definitions(svd_c PRIVATE USEMKL=${USEMKL} USEATLAS=${atlas} USEOpenBLAS=${USEOpenBLAS}) 15 | 16 | add_test(NAME C-SVD COMMAND svd_c) 17 | set_tests_properties(C-SVD PROPERTIES 18 | ENVIRONMENT MKL_VERBOSE=1) 19 | -------------------------------------------------------------------------------- /c_src/example_gesvd.c: -------------------------------------------------------------------------------- 1 | /* 2 | from http://www.netlib.org/lapack/explore-html/d5/df8/example___d_g_e_s_v__colmajor_8c_source.html 3 | 4 | LAPACKE_dgesv Example 5 | ===================== 6 | 7 | The program computes the solution to the system of linear 8 | equations with a square matrix A and multiple 9 | right-hand sides B, where A is the coefficient matrix 10 | and b is the right-hand side matrix: 11 | 12 | Description 13 | =========== 14 | 15 | The routine solves for X the system of linear equations A*X = B, 16 | where A is an n-by-n matrix, the columns of matrix B are individual 17 | right-hand sides, and the columns of X are the corresponding 18 | solutions. 19 | 20 | The LU decomposition with partial pivoting and row interchanges is 21 | used to factor A as A = P*L*U, where P is a permutation matrix, L 22 | is unit lower triangular, and U is upper triangular. The factored 23 | form of A is then used to solve the system of equations A*X = B. 24 | 25 | LAPACKE Interface 26 | ================= 27 | 28 | LAPACKE_dgesv (col-major, high-level) Example Program Results 29 | 30 | -- LAPACKE Example routine (version 3.7.0) -- 31 | -- LAPACK is a software package provided by Univ. of Tennessee, -- 32 | -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- 33 | December 2016 34 | 35 | */ 36 | /* Includes */ 37 | #include 38 | #include 39 | #include 40 | 41 | #if USEMKL == 1 42 | #include "mkl_lapacke.h" 43 | #elif USEATLAS == 1 44 | #include "cblas.h" 45 | #include "clapack.h" 46 | #elif USEOpenBLAS == 1 47 | #include "cblas.h" 48 | #else 49 | #include "lapacke.h" 50 | #endif 51 | 52 | /* Main program */ 53 | int main(int argc, char **argv) { 54 | 55 | /* Locals */ 56 | int n, nrhs, lda, ldb, info; 57 | int i, j; 58 | /* Local arrays */ 59 | double *A, *b; 60 | int *ipiv; 61 | 62 | /* Default Value */ 63 | n = 5; nrhs = 1; 64 | 65 | /* Arguments */ 66 | for( i = 1; i < argc; i++ ) { 67 | if( strcmp( argv[i], "-n" ) == 0 ) { 68 | n = atoi(argv[i+1]); 69 | i++; 70 | } 71 | if( strcmp( argv[i], "-nrhs" ) == 0 ) { 72 | nrhs = atoi(argv[i+1]); 73 | i++; 74 | } 75 | } 76 | 77 | /* Initialization */ 78 | lda=n, ldb=n; 79 | A = (double *)malloc(n*n*sizeof(double)) ; 80 | if (A==NULL){ printf("error of memory allocation\n"); return 1; } 81 | b = (double *)malloc(n*nrhs*sizeof(double)) ; 82 | if (b==NULL){ printf("error of memory allocation\n"); return 1; } 83 | ipiv = (int *)malloc(n*sizeof(int)) ; 84 | if (ipiv==NULL){ printf("error of memory allocation\n"); return 1; } 85 | 86 | for( i = 0; i < n; i++ ) { 87 | for( j = 0; j < n; j++ ) A[i+j*lda] = ((double) rand()) / ((double) RAND_MAX) - 0.5; 88 | } 89 | 90 | for(i=0;i 0 ) { 111 | printf( "The diagonal element of the triangular factor of A,\n" ); 112 | printf( "U(%i,%i) is zero, so that A is singular;\n", info, info ); 113 | printf( "the solution could not be computed.\n" ); 114 | return 1; 115 | } 116 | if (info < 0) return 1; 117 | /* Print solution */ 118 | // print_matrix_colmajor( "Solution", n, nrhs, b, ldb ); 119 | /* Print details of LU factorization */ 120 | // print_matrix_colmajor( "Details of LU factorization", n, n, A, lda ); 121 | /* Print pivot indices */ 122 | // print_vector( "Pivot indices", n, ipiv ); 123 | return 0; 124 | } /* End of LAPACKE_dgesv Example */ 125 | -------------------------------------------------------------------------------- /c_src/meson.build: -------------------------------------------------------------------------------- 1 | 2 | svd_c = executable('svd_c', 'example_gesvd.c', 3 | dependencies: lapacke_lib, 4 | c_args: ['-DUSEMKL=' + '@0@'.format(usemkl)]) 5 | 6 | test('C-SVD', svd_c, 7 | env: 'MKL_VERBOSE=1', timeout: 10) 8 | -------------------------------------------------------------------------------- /cmake/Modules/FindLAPACK.cmake: -------------------------------------------------------------------------------- 1 | # Distributed under the OSI-approved BSD 3-Clause License. See accompanying 2 | # file Copyright.txt or https://cmake.org/licensing for details. 3 | 4 | #[=======================================================================[.rst: 5 | 6 | FindLapack 7 | ---------- 8 | 9 | * Michael Hirsch, Ph.D. www.scivision.dev 10 | * David Eklund 11 | 12 | Let Michael know if there are more MKL / Lapack / compiler combination you want. 13 | Refer to https://software.intel.com/en-us/articles/intel-mkl-link-line-advisor 14 | 15 | Finds LAPACK libraries for C / C++ / Fortran. 16 | Works with Netlib Lapack / LapackE, Atlas and Intel MKL. 17 | Intel MKL relies on having environment variable MKLROOT set, typically by sourcing 18 | mklvars.sh beforehand. 19 | 20 | Why not the FindLapack.cmake built into CMake? It has a lot of old code for 21 | infrequently used Lapack libraries and is unreliable for me. 22 | 23 | Tested on Linux, MacOS and Windows with: 24 | * GCC / Gfortran 25 | * Clang / Flang 26 | * Intel (icc, ifort) 27 | * Cray 28 | 29 | 30 | Parameters 31 | ^^^^^^^^^^ 32 | 33 | COMPONENTS default to Netlib LAPACK / LapackE, otherwise: 34 | 35 | ``MKL`` 36 | Intel MKL for MSVC, ICL, ICC, GCC and PGCC -- sequential by default, or add TBB or MPI as well 37 | ``OpenMP`` 38 | Intel MPI with OpenMP threading addition to MKL 39 | ``TBB`` 40 | Intel MPI + TBB for MKL 41 | ``MKL64`` 42 | MKL only: 64-bit integers (default is 32-bit integers) 43 | 44 | ``LAPACKE`` 45 | Netlib LapackE for C / C++ 46 | ``Netlib`` 47 | Netlib Lapack for Fortran 48 | ``OpenBLAS`` 49 | OpenBLAS Lapack for Fortran 50 | 51 | ``LAPACK95`` 52 | get Lapack95 interfaces for MKL or Netlib (must also specify one of MKL, Netlib) 53 | 54 | 55 | Result Variables 56 | ^^^^^^^^^^^^^^^^ 57 | 58 | ``LAPACK_FOUND`` 59 | Lapack libraries were found 60 | ``LAPACK__FOUND`` 61 | LAPACK specified was found 62 | ``LAPACK_LIBRARIES`` 63 | Lapack library files (including BLAS 64 | ``LAPACK_INCLUDE_DIRS`` 65 | Lapack include directories (for C/C++) 66 | 67 | 68 | References 69 | ^^^^^^^^^^ 70 | 71 | * Pkg-Config and MKL: https://software.intel.com/en-us/articles/intel-math-kernel-library-intel-mkl-and-pkg-config-tool 72 | * MKL for Windows: https://software.intel.com/en-us/mkl-windows-developer-guide-static-libraries-in-the-lib-intel64-win-directory 73 | * MKL Windows directories: https://software.intel.com/en-us/mkl-windows-developer-guide-high-level-directory-structure 74 | * Atlas http://math-atlas.sourceforge.net/errata.html#LINK 75 | * MKL LAPACKE (C, C++): https://software.intel.com/en-us/mkl-linux-developer-guide-calling-lapack-blas-and-cblas-routines-from-c-c-language-environments 76 | #]=======================================================================] 77 | 78 | include(CheckSourceCompiles) 79 | 80 | # clear to avoid endless appending on subsequent calls 81 | set(LAPACK_LIBRARY) 82 | unset(LAPACK_INCLUDE_DIR) 83 | 84 | # ===== functions ========== 85 | 86 | function(atlas_libs) 87 | 88 | find_library(ATLAS_LIB 89 | NAMES atlas 90 | PATH_SUFFIXES atlas 91 | ) 92 | 93 | find_library(LAPACK_ATLAS 94 | NAMES ptlapack lapack_atlas lapack 95 | NAMES_PER_DIR 96 | PATH_SUFFIXES atlas 97 | ) 98 | 99 | find_library(BLAS_LIBRARY 100 | NAMES ptf77blas f77blas blas 101 | NAMES_PER_DIR 102 | PATH_SUFFIXES atlas 103 | ) 104 | 105 | # === C === 106 | find_library(BLAS_C_ATLAS 107 | NAMES ptcblas cblas 108 | NAMES_PER_DIR 109 | PATH_SUFFIXES atlas 110 | ) 111 | 112 | find_path(LAPACK_INCLUDE_DIR 113 | NAMES cblas-atlas.h cblas.h clapack.h 114 | ) 115 | 116 | #=========== 117 | if(LAPACK_ATLAS AND BLAS_C_ATLAS AND BLAS_LIBRARY AND ATLAS_LIB) 118 | set(LAPACK_Atlas_FOUND true PARENT_SCOPE) 119 | set(LAPACK_LIBRARY ${LAPACK_ATLAS} ${BLAS_C_ATLAS} ${BLAS_LIBRARY} ${ATLAS_LIB}) 120 | list(APPEND LAPACK_LIBRARY ${CMAKE_THREAD_LIBS_INIT}) 121 | endif() 122 | 123 | set(LAPACK_LIBRARY ${LAPACK_LIBRARY} PARENT_SCOPE) 124 | 125 | endfunction(atlas_libs) 126 | 127 | #======================= 128 | 129 | function(netlib_libs) 130 | 131 | if(LAPACK95 IN_LIST LAPACK_FIND_COMPONENTS) 132 | find_path(LAPACK95_INCLUDE_DIR 133 | NAMES f95_lapack.mod 134 | HINTS ${LAPACK95_ROOT} ENV LAPACK95_ROOT 135 | PATH_SUFFIXES include 136 | ) 137 | 138 | find_library(LAPACK95_LIBRARY 139 | NAMES lapack95 140 | HINTS ${LAPACK95_ROOT} ENV LAPACK95_ROOT 141 | ) 142 | 143 | if(NOT (LAPACK95_LIBRARY AND LAPACK95_INCLUDE_DIR)) 144 | return() 145 | endif() 146 | 147 | set(LAPACK95_LIBRARY ${LAPACK95_LIBRARY} PARENT_SCOPE) 148 | set(LAPACK_LAPACK95_FOUND true PARENT_SCOPE) 149 | endif(LAPACK95 IN_LIST LAPACK_FIND_COMPONENTS) 150 | 151 | find_library(LAPACK_LIBRARY 152 | NAMES lapack 153 | PATH_SUFFIXES lapack lapack/lib 154 | ) 155 | if(NOT LAPACK_LIBRARY) 156 | return() 157 | endif() 158 | 159 | if(LAPACKE IN_LIST LAPACK_FIND_COMPONENTS) 160 | 161 | find_library(LAPACKE_LIBRARY 162 | NAMES lapacke 163 | PATH_SUFFIXES lapack lapack/lib 164 | ) 165 | 166 | # lapack/include for Homebrew 167 | find_path(LAPACKE_INCLUDE_DIR 168 | NAMES lapacke.h 169 | PATH_SUFFIXES lapack lapack/include 170 | ) 171 | if(NOT (LAPACKE_LIBRARY AND LAPACKE_INCLUDE_DIR)) 172 | return() 173 | endif() 174 | 175 | set(LAPACK_LAPACKE_FOUND true PARENT_SCOPE) 176 | list(APPEND LAPACK_INCLUDE_DIR ${LAPACKE_INCLUDE_DIR}) 177 | list(APPEND LAPACK_LIBRARY ${LAPACKE_LIBRARY}) 178 | mark_as_advanced(LAPACKE_LIBRARY LAPACKE_INCLUDE_DIR) 179 | endif(LAPACKE IN_LIST LAPACK_FIND_COMPONENTS) 180 | 181 | # Netlib on Cygwin and others 182 | 183 | find_library(BLAS_LIBRARY 184 | NAMES refblas blas 185 | NAMES_PER_DIR 186 | PATH_SUFFIXES lapack lapack/lib blas 187 | ) 188 | 189 | if(NOT BLAS_LIBRARY) 190 | return() 191 | endif() 192 | 193 | list(APPEND LAPACK_LIBRARY ${BLAS_LIBRARY}) 194 | set(LAPACK_Netlib_FOUND true PARENT_SCOPE) 195 | 196 | list(APPEND LAPACK_LIBRARY ${CMAKE_THREAD_LIBS_INIT}) 197 | 198 | set(LAPACK_LIBRARY ${LAPACK_LIBRARY} PARENT_SCOPE) 199 | 200 | endfunction(netlib_libs) 201 | 202 | #=============================== 203 | function(openblas_libs) 204 | 205 | find_library(LAPACK_LIBRARY 206 | NAMES lapack 207 | PATH_SUFFIXES openblas 208 | ) 209 | 210 | find_library(BLAS_LIBRARY 211 | NAMES openblas blas 212 | NAMES_PER_DIR 213 | PATH_SUFFIXES openblas 214 | ) 215 | 216 | find_path(LAPACK_INCLUDE_DIR 217 | NAMES cblas-openblas.h cblas.h f77blas.h openblas_config.h 218 | ) 219 | 220 | if(NOT (LAPACK_LIBRARY AND BLAS_LIBRARY)) 221 | return() 222 | endif() 223 | 224 | list(APPEND LAPACK_LIBRARY ${BLAS_LIBRARY}) 225 | set(LAPACK_OpenBLAS_FOUND true PARENT_SCOPE) 226 | 227 | list(APPEND LAPACK_LIBRARY ${CMAKE_THREAD_LIBS_INIT}) 228 | 229 | set(LAPACK_LIBRARY ${LAPACK_LIBRARY} PARENT_SCOPE) 230 | 231 | endfunction(openblas_libs) 232 | 233 | #=============================== 234 | 235 | function(find_mkl_libs) 236 | # https://software.intel.com/en-us/articles/intel-mkl-link-line-advisor 237 | 238 | set(_mkl_libs ${ARGV}) 239 | if((UNIX AND NOT APPLE) AND CMAKE_Fortran_COMPILER_ID STREQUAL GNU) 240 | list(PREPEND _mkl_libs mkl_gf_${_mkl_bitflag}lp64) 241 | else() 242 | if(WIN32 AND BUILD_SHARED_LIBS) 243 | list(PREPEND _mkl_libs mkl_intel_${_mkl_bitflag}lp64_dll) 244 | else() 245 | list(PREPEND _mkl_libs mkl_intel_${_mkl_bitflag}lp64) 246 | endif() 247 | endif() 248 | 249 | foreach(s ${_mkl_libs}) 250 | find_library(LAPACK_${s}_LIBRARY 251 | NAMES ${s} 252 | PATHS ${MKLROOT} 253 | PATH_SUFFIXES lib lib/intel64 254 | NO_DEFAULT_PATH 255 | ) 256 | 257 | if(NOT LAPACK_${s}_LIBRARY) 258 | return() 259 | endif() 260 | 261 | list(APPEND LAPACK_LIBRARY ${LAPACK_${s}_LIBRARY}) 262 | endforeach() 263 | 264 | find_path(LAPACK_INCLUDE_DIR 265 | NAMES mkl_lapack.h 266 | HINTS ${MKLROOT} 267 | PATH_SUFFIXES include 268 | NO_DEFAULT_PATH 269 | ) 270 | 271 | if(NOT LAPACK_INCLUDE_DIR) 272 | return() 273 | endif() 274 | 275 | set(LAPACK_LIBRARY ${LAPACK_LIBRARY} PARENT_SCOPE) 276 | 277 | endfunction(find_mkl_libs) 278 | 279 | # ========== main program 280 | 281 | set(lapack_cray false) 282 | if(DEFINED ENV{CRAYPE_VERSION}) 283 | set(lapack_cray true) 284 | endif() 285 | 286 | if(NOT (lapack_cray 287 | OR OpenBLAS IN_LIST LAPACK_FIND_COMPONENTS 288 | OR Netlib IN_LIST LAPACK_FIND_COMPONENTS 289 | OR Atlas IN_LIST LAPACK_FIND_COMPONENTS 290 | OR MKL IN_LIST LAPACK_FIND_COMPONENTS)) 291 | if(DEFINED ENV{MKLROOT}) 292 | list(APPEND LAPACK_FIND_COMPONENTS MKL) 293 | else() 294 | list(APPEND LAPACK_FIND_COMPONENTS Netlib) 295 | endif() 296 | endif() 297 | 298 | find_package(Threads) 299 | 300 | # ==== generic MKL variables ==== 301 | 302 | if(MKL IN_LIST LAPACK_FIND_COMPONENTS) 303 | # we have to sanitize MKLROOT if it has Windows backslashes (\) otherwise it will break at build time 304 | # double-quotes are necessary per CMake to_cmake_path docs. 305 | file(TO_CMAKE_PATH "$ENV{MKLROOT}" MKLROOT) 306 | 307 | if(BUILD_SHARED_LIBS) 308 | set(_mkltype dynamic) 309 | else() 310 | set(_mkltype static) 311 | endif() 312 | 313 | if(MKL64 IN_LIST LAPACK_FIND_COMPONENTS) 314 | set(_mkl_bitflag i) 315 | else() 316 | set(_mkl_bitflag) 317 | endif() 318 | 319 | set(_mkl_libs) 320 | if(LAPACK95 IN_LIST LAPACK_FIND_COMPONENTS) 321 | find_mkl_libs(mkl_blas95_${_mkl_bitflag}lp64 mkl_lapack95_${_mkl_bitflag}lp64) 322 | if(LAPACK_LIBRARY) 323 | set(LAPACK95_LIBRARY ${LAPACK_LIBRARY}) 324 | set(LAPACK_LIBRARY) 325 | set(LAPACK95_INCLUDE_DIR ${LAPACK_INCLUDE_DIR}) 326 | set(LAPACK_LAPACK95_FOUND true) 327 | endif() 328 | endif() 329 | 330 | set(_tbb) 331 | if(TBB IN_LIST LAPACK_FIND_COMPONENTS) 332 | list(APPEND _mkl_libs mkl_tbb_thread mkl_core) 333 | set(_tbb tbb stdc++) 334 | elseif(OpenMP IN_LIST LAPACK_FIND_COMPONENTS) 335 | set(_mp iomp5) 336 | if(WIN32) 337 | set(_mp libiomp5md) 338 | endif() 339 | if(WIN32 AND BUILD_SHARED_LIBS) 340 | list(APPEND _mkl_libs mkl_intel_thread_dll mkl_core_dll ${_mp}) 341 | else() 342 | list(APPEND _mkl_libs mkl_intel_thread mkl_core ${_mp}) 343 | endif() 344 | else() 345 | if(WIN32 AND BUILD_SHARED_LIBS) 346 | list(APPEND _mkl_libs mkl_sequential_dll mkl_core_dll) 347 | else() 348 | list(APPEND _mkl_libs mkl_sequential mkl_core) 349 | endif() 350 | endif() 351 | 352 | find_mkl_libs(${_mkl_libs}) 353 | 354 | if(LAPACK_LIBRARY) 355 | 356 | if(NOT WIN32) 357 | list(APPEND LAPACK_LIBRARY ${_tbb} ${CMAKE_THREAD_LIBS_INIT} ${CMAKE_DL_LIBS} m) 358 | endif() 359 | 360 | set(LAPACK_MKL_FOUND true) 361 | 362 | if(MKL64 IN_LIST LAPACK_FIND_COMPONENTS) 363 | set(LAPACK_MKL64_FOUND true) 364 | endif() 365 | 366 | if(OpenMP IN_LIST LAPACK_FIND_COMPONENTS) 367 | set(LAPACK_OpenMP_FOUND true) 368 | endif() 369 | 370 | if(TBB IN_LIST LAPACK_FIND_COMPONENTS) 371 | set(LAPACK_TBB_FOUND true) 372 | endif() 373 | endif() 374 | 375 | elseif(Atlas IN_LIST LAPACK_FIND_COMPONENTS) 376 | atlas_libs() 377 | elseif(Netlib IN_LIST LAPACK_FIND_COMPONENTS) 378 | netlib_libs() 379 | elseif(OpenBLAS IN_LIST LAPACK_FIND_COMPONENTS) 380 | openblas_libs() 381 | elseif(lapack_cray) 382 | # LAPACK is implicitly part of Cray PE LibSci, use Cray compiler wrapper. 383 | endif() 384 | 385 | # -- verify library works 386 | 387 | function(lapack_check) 388 | 389 | get_property(enabled_langs GLOBAL PROPERTY ENABLED_LANGUAGES) 390 | if(NOT Fortran IN_LIST enabled_langs) 391 | set(LAPACK_links true PARENT_SCOPE) 392 | return() 393 | endif() 394 | 395 | set(CMAKE_REQUIRED_FLAGS) 396 | set(CMAKE_REQUIRED_LINK_OPTIONS) 397 | set(CMAKE_REQUIRED_INCLUDES) 398 | set(CMAKE_REQUIRED_LIBRARIES ${LAPACK_LIBRARY}) 399 | 400 | foreach(i s d) 401 | check_source_compiles(Fortran 402 | "program check_lapack 403 | implicit none (type, external) 404 | external :: ${i}isnan 405 | end program" LAPACK_${i}_links) 406 | 407 | if(LAPACK_${i}_links) 408 | set(LAPACK_${i}_FOUND true PARENT_SCOPE) 409 | set(LAPACK_links true) 410 | endif() 411 | 412 | endforeach() 413 | 414 | set(LAPACK_links ${LAPACK_links} PARENT_SCOPE) 415 | 416 | endfunction(lapack_check) 417 | 418 | # --- Check that Scalapack links 419 | 420 | if(lapack_cray OR LAPACK_LIBRARY) 421 | lapack_check() 422 | endif() 423 | 424 | 425 | include(FindPackageHandleStandardArgs) 426 | 427 | if(lapack_cray) 428 | find_package_handle_standard_args(LAPACK HANDLE_COMPONENTS 429 | REQUIRED_VARS LAPACK_links 430 | ) 431 | else() 432 | find_package_handle_standard_args(LAPACK HANDLE_COMPONENTS 433 | REQUIRED_VARS LAPACK_LIBRARY LAPACK_links 434 | ) 435 | endif() 436 | 437 | 438 | set(BLAS_LIBRARIES ${BLAS_LIBRARY}) 439 | set(LAPACK_LIBRARIES ${LAPACK_LIBRARY}) 440 | set(LAPACK_INCLUDE_DIRS ${LAPACK_INCLUDE_DIR}) 441 | 442 | if(LAPACK_FOUND) 443 | # need if _FOUND guard as can't overwrite imported target even if bad 444 | if(NOT TARGET BLAS::BLAS) 445 | add_library(BLAS::BLAS INTERFACE IMPORTED) 446 | set_target_properties(BLAS::BLAS PROPERTIES 447 | INTERFACE_LINK_LIBRARIES "${BLAS_LIBRARY}" 448 | ) 449 | endif() 450 | 451 | if(NOT TARGET LAPACK::LAPACK) 452 | add_library(LAPACK::LAPACK INTERFACE IMPORTED) 453 | set_target_properties(LAPACK::LAPACK PROPERTIES 454 | INTERFACE_LINK_LIBRARIES "${LAPACK_LIBRARY}" 455 | INTERFACE_INCLUDE_DIRECTORIES "${LAPACK_INCLUDE_DIR}" 456 | ) 457 | endif() 458 | 459 | if(LAPACK_LAPACK95_FOUND) 460 | set(LAPACK95_LIBRARIES ${LAPACK95_LIBRARY}) 461 | set(LAPACK95_INCLUDE_DIRS ${LAPACK95_INCLUDE_DIR}) 462 | 463 | if(NOT TARGET LAPACK::LAPACK95) 464 | add_library(LAPACK::LAPACK95 INTERFACE IMPORTED) 465 | set_target_properties(LAPACK::LAPACK95 PROPERTIES 466 | INTERFACE_LINK_LIBRARIES "${LAPACK95_LIBRARY}" 467 | INTERFACE_INCLUDE_DIRECTORIES "${LAPACK95_INCLUDE_DIR}" 468 | ) 469 | endif() 470 | endif() 471 | endif() 472 | 473 | mark_as_advanced(LAPACK_LIBRARY LAPACK_INCLUDE_DIR) 474 | -------------------------------------------------------------------------------- /factory/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # tests CMake's built-in FindBLAS 2 | cmake_minimum_required(VERSION 3.12) 3 | project(Lapack_OEM LANGUAGES C Fortran) 4 | 5 | if(CMAKE_Fortran_COMPILER_ID STREQUAL Intel) 6 | set(BLA_VENDOR Intel10_64lp) 7 | if(WIN32) 8 | file(TO_CMAKE_PATH "$ENV{MKLROOT}" MKLROOT) 9 | else() 10 | set(MKLROOT "$ENV{MKLROOT}") 11 | endif() 12 | endif() 13 | 14 | find_package(BLAS) 15 | find_package(LAPACK) 16 | -------------------------------------------------------------------------------- /fortran_src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | if(NOT CMAKE_Fortran_COMPILER) 2 | return() 3 | endif() 4 | 5 | set(noneed GNU Intel) 6 | 7 | if(NOT WIN32 AND NOT CMAKE_Fortran_COMPILER_ID IN_LIST noneed) 8 | list(APPEND LDFLAGS -lgfortran) 9 | endif() 10 | 11 | add_executable(svd_f example_gesvd.f90) 12 | if(atlas OR lapack95) 13 | target_sources(svd_f PRIVATE atlas_svd.f90) 14 | else() 15 | target_sources(svd_f PRIVATE lapack_svd.f90) 16 | endif() 17 | target_link_libraries(svd_f PRIVATE LAPACK::LAPACK) 18 | 19 | add_test(NAME Fortran-SVD COMMAND svd_f) 20 | set_tests_properties(Fortran-SVD PROPERTIES 21 | ENVIRONMENT MKL_VERBOSE=1) 22 | -------------------------------------------------------------------------------- /fortran_src/atlas_svd.f90: -------------------------------------------------------------------------------- 1 | submodule (demo_svd) atlas 2 | 3 | contains 4 | 5 | module procedure svd 6 | !! For lapack95 and atlas, the sgesv API is: 7 | !! sgesv( N, nrhs, a, lda, ipiv, b, ldb, info ) 8 | integer :: ipiv(N) 9 | real :: truthX(M), errmag(M) 10 | 11 | call sgesv(M, size(B,2), A, M, ipiv, B, M, info) 12 | 13 | truthX = [1., 2., 3.] 14 | 15 | errmag = abs(B(:,1)-truthX) 16 | if (any(errmag > 1e-3)) then 17 | print *,'estimated solution: ',B 18 | print *,'true input: ',truthX 19 | write(stderr,*) 'large error on singular values', errmag 20 | error stop 21 | endif 22 | 23 | end procedure svd 24 | 25 | end submodule atlas 26 | -------------------------------------------------------------------------------- /fortran_src/blas_matmul.f90: -------------------------------------------------------------------------------- 1 | submodule (demo_svd) atlas 2 | 3 | contains 4 | 5 | module procedure example 6 | 7 | integer :: i 8 | 9 | call sgemm('N','T',M,M,N,1._sp, A, M, A, M, 0._sp, U, M) 10 | 11 | ! U = matmul(A, transpose(A)) 12 | 13 | do i = 1,size(U,1) 14 | print "(/,10F7.3)", U(i,:) 15 | enddo 16 | 17 | end procedure example 18 | 19 | end submodule atlas 20 | -------------------------------------------------------------------------------- /fortran_src/example_gesvd.f90: -------------------------------------------------------------------------------- 1 | module demo_svd 2 | use, intrinsic :: iso_fortran_env, only: stderr=>error_unit, sp=>real32 3 | implicit none 4 | 5 | integer, parameter :: LRATIO=8 6 | integer, parameter :: M=3, N=3 7 | 8 | integer, parameter :: Lwork = LRATIO*M !at least 5M for sgesvd 9 | 10 | real(sp) :: U(M,M), VT(N,N) 11 | real(sp) :: S(N), SWORK(LRATIO*M) !this Swork is real 12 | 13 | interface 14 | module integer function svd(A, B) result(info) 15 | real(sp), intent(in) :: A(M, N), B(M, 1) 16 | end function svd 17 | end interface 18 | 19 | contains 20 | 21 | subroutine errchk(info) 22 | 23 | integer, intent(in) :: info 24 | 25 | if (info /= 0) then 26 | write(stderr,*) 'SGESVD return code', info 27 | if (info > 0) write(stderr,'(A,I3,A)') 'index #',info,' has sigma=0' 28 | stop 1 29 | endif 30 | 31 | end subroutine errchk 32 | 33 | end module demo_svd 34 | 35 | 36 | program demo 37 | ! FIXME not for PGI 18.10 38 | ! use, intrinsic :: iso_fortran_env, only: compiler_version 39 | use demo_svd 40 | implicit none 41 | 42 | integer :: info 43 | real(sp) :: A(M, N), B(M,1) 44 | 45 | ! print *,compiler_version() 46 | 47 | A = reshape([3., 1., 1., & 48 | sqrt(2.), 2., 0., & 49 | 0., 1., 1.], shape(A), order=[2,1]) 50 | 51 | B = reshape([8., 4.+sqrt(2.), 5.], shape(B), order=[2,1]) 52 | 53 | 54 | info = svd(A, B) 55 | 56 | call errchk(info) 57 | 58 | print *,'OK: Fortran SVD' 59 | 60 | end program 61 | -------------------------------------------------------------------------------- /fortran_src/lapack_svd.f90: -------------------------------------------------------------------------------- 1 | submodule (demo_svd) lapack 2 | 3 | contains 4 | 5 | module procedure svd 6 | real(sp) :: truthS(N), errmag(N) 7 | 8 | truthS = [3.97303, 1.46913, 1.02795] 9 | 10 | call sgesvd('A','N',M,N, A, M,S,U,M,VT, N, SWORK, LWORK, info) 11 | 12 | errmag = abs(s-truthS) 13 | if (any(errmag > 1e-3)) then 14 | print *,'estimated singular values: ',S 15 | print *,'true singular values: ',truthS 16 | write(stderr,*) 'large error on singular values', errmag 17 | error stop 18 | endif 19 | 20 | end procedure svd 21 | 22 | end submodule lapack 23 | -------------------------------------------------------------------------------- /fortran_src/meson.build: -------------------------------------------------------------------------------- 1 | 2 | if usemkl == 1 or lapack95_lib.found() 3 | f_src = files('atlas_svd.f90') 4 | else 5 | f_src = files('lapack_svd.f90') 6 | endif 7 | 8 | svd_f = executable('svd_f', 'example_gesvd.f90', f_src, 9 | dependencies: lapack_lib) 10 | 11 | test('Fortran-SVD', svd_f, 12 | env: 'MKL_VERBOSE=1', timeout: 10) 13 | -------------------------------------------------------------------------------- /meson.build: -------------------------------------------------------------------------------- 1 | project('lapack_demo', 'c', 2 | default_options : ['default_library=static', 'buildtype=release'], 3 | meson_version: '>= 0.52.1') 4 | 5 | cc = meson.get_compiler('c') 6 | 7 | mkl_root = get_option('MKL_ROOT') 8 | usemkl = 0 9 | if cc.get_id() == 'intel' or cc.get_id() == 'intel-cl' or mkl_root != '' 10 | usemkl = 1 11 | endif 12 | 13 | # issue with Meson--CMake alone works OK 14 | # lapack = dependency('lapack', method: 'cmake', cmake_module_path: 'cmake/Modules') 15 | if usemkl == 1 16 | c_code = '#include "mkl_lapacke.h"' 17 | lapacke_lib = [] 18 | foreach n: ['mkl_intel_lp64', 'mkl_sequential', 'mkl_core'] 19 | lapacke_lib += cc.find_library(n) 20 | endforeach 21 | else 22 | c_code = '#include "lapacke.h"' 23 | lapacke_lib = cc.find_library('lapacke', required: false, disabler: true) 24 | endif 25 | if not cc.links(c_code+''' 26 | int main(void) { return 0; }''', dependencies: lapacke_lib, name: 'LAPACKE') 27 | lapacke_lib = disabler() 28 | endif 29 | 30 | subdir('c_src') 31 | 32 | #=== Fortran (optional) 33 | 34 | if not add_languages('fortran', required: false) 35 | subdir_done() 36 | endif 37 | 38 | fc = meson.get_compiler('fortran') 39 | 40 | lapack_lib = disabler() 41 | lapack95_lib = disabler() 42 | if usemkl == 1 43 | lapack_lib = [] 44 | foreach n: ['mkl_blas95_lp64', 'mkl_lapack95_lp64', 'mkl_intel_lp64', 'mkl_sequential', 'mkl_core'] 45 | lapack_lib += fc.find_library(n) 46 | endforeach 47 | if not fc.links('print *,disnan(0.); end', dependencies: lapack_lib, name: 'LAPACK') 48 | lapack_lib = disabler() 49 | lapack95_lib = disabler() 50 | else 51 | lapack95_lib = lapack_lib 52 | endif 53 | else 54 | foreach n: ['lapack-netlib', 'lapack'] 55 | lapack_lib = fc.find_library(n, required: false, disabler: true) 56 | if fc.links('print *,disnan(0.); end', dependencies: lapack_lib, name: 'LAPACK') 57 | break 58 | else 59 | lapack_lib = disabler() 60 | endif 61 | endforeach 62 | 63 | lapack95_lib = fc.find_library('lapack95', required: false, disabler: true) 64 | if lapack95_lib.found() 65 | lapack_lib = [lapack95_lib, lapack_lib] 66 | endif 67 | endif 68 | 69 | if not lapack_lib.found() 70 | lapack_proj = subproject('lapack') 71 | lapack_lib = declare_dependency(link_with: lapack_proj.get_variable('lapack')) 72 | endif 73 | 74 | subdir('fortran_src') 75 | -------------------------------------------------------------------------------- /meson_options.txt: -------------------------------------------------------------------------------- 1 | option('MKL_ROOT', type: 'string', description: '-DMKL_ROOT=$MKLROOT') 2 | -------------------------------------------------------------------------------- /subprojects/lapack.wrap: -------------------------------------------------------------------------------- 1 | [wrap-git] 2 | directory = lapack 3 | url = https://github.com/scivision/lapack.git 4 | revision = head -------------------------------------------------------------------------------- /test_build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cd "${0%/*}" # change to directory of this script 4 | 5 | fc=$1 6 | 7 | bindir=build 8 | 9 | for cc in gcc clang pgcc icc icl 10 | do 11 | 12 | [[ $(which $cc) ]] || continue 13 | 14 | rm -f $bindir/CMakeCache.txt 15 | 16 | CC=$cc ctest -S setup.cmake -VV 17 | 18 | done 19 | 20 | rm -f $bindir/CMakeCache.txt 21 | --------------------------------------------------------------------------------