pax_global_header 0000666 0000000 0000000 00000000064 13572470056 0014523 g ustar 00root root 0000000 0000000 52 comment=0a02ef603df8005e301df7547fbdf924d859c173
SpFFT-0.9.10/ 0000775 0000000 0000000 00000000000 13572470056 0012534 5 ustar 00root root 0000000 0000000 SpFFT-0.9.10/.clang-format 0000664 0000000 0000000 00000000077 13572470056 0015113 0 ustar 00root root 0000000 0000000 BasedOnStyle: Google
ColumnLimit: 100
AccessModifierOffset: -2
SpFFT-0.9.10/CI/ 0000775 0000000 0000000 00000000000 13572470056 0013027 5 ustar 00root root 0000000 0000000 SpFFT-0.9.10/CI/azure_templates/ 0000775 0000000 0000000 00000000000 13572470056 0016233 5 ustar 00root root 0000000 0000000 SpFFT-0.9.10/CI/azure_templates/ubuntu_build_test.yml 0000664 0000000 0000000 00000003727 13572470056 0022527 0 ustar 00root root 0000000 0000000 parameters:
# job config
job_name: 'Ubuntu_GCC'
run_mpi_tests: false
run_local_tests: false
#cmake parameters
cm_mpi: 'ON'
cm_omp: 'ON'
cm_single_precision: 'OFF'
cm_gpu_backend: 'OFF'
jobs:
- job: ${{ parameters.job_name }}
pool:
vmImage: 'ubuntu-latest'
container: adhocman/master:ubuntu_18_04_cuda_9
strategy:
matrix:
Release:
BUILD_TYPE: 'RELEASE'
Debug:
BUILD_TYPE: 'DEBUG'
maxParallel: 2
variables:
SPFFT_MPI: ${{ parameters.cm_mpi }}
SPFFT_OMP: ${{ parameters.cm_omp }}
SPFFT_SINGLE_PRECISION: ${{ parameters.cm_single_precision }}
SPFFT_GPU_BACKEND: ${{ parameters.cm_gpu_backend }}
steps:
- script: |
mkdir -p build
cd build
CUDACXX=/usr/local/cuda-9.0/bin/nvcc /opt/cmake-3.11.0/bin/cmake .. -DCMAKE_BUILD_TYPE=${BUILD_TYPE} -DSPFFT_BUILD_TESTS=OFF -DSPFFT_MPI=${SPFFT_MPI} -DSPFFT_OMP=${SPFFT_OMP} -DSPFFT_SINGLE_PRECISION=${SPFFT_SINGLE_PRECISION} -DSPFFT_GPU_BACKEND=${SPFFT_GPU_BACKEND}
make VERBOSE=1
displayName: 'Build library'
- script: |
cd build
mkdir -p install_dir
INSTALL_DIR=$(pwd)/install_dir
/opt/cmake-3.11.0/bin/cmake .. -DCMAKE_INSTALL_PREFIX=${INSTALL_DIR}
make VERBOSE=1 install
test -f ${INSTALL_DIR}/lib/libspfft.so
test -f ${INSTALL_DIR}/include/spfft/spfft.hpp
test -f ${INSTALL_DIR}/include/spfft/spfft.h
displayName: 'Install library'
- script: |
mkdir -p build
cd build
/opt/cmake-3.11.0/bin/cmake .. -DSPFFT_BUILD_TESTS=ON
make VERBOSE=1
displayName: 'Build tests'
- script: |
export OMP_NUM_THREADS=2
./build/tests/run_local_tests
displayName: 'Run local tests'
condition: and(succeeded(), eq('${{ parameters.run_local_tests }}', 'true'))
- script: |
export OMP_NUM_THREADS=2
mpirun -n 2 ./build/tests/run_mpi_tests
displayName: 'Run MPI tests'
condition: and(succeeded(), eq('${{ parameters.run_mpi_tests }}', 'true'))
SpFFT-0.9.10/CMakeLists.txt 0000664 0000000 0000000 00000014375 13572470056 0015306 0 ustar 00root root 0000000 0000000 cmake_minimum_required(VERSION 3.11 FATAL_ERROR) # 3.11 to avoid issues with OpenMP + CUDA
project(SpFFT LANGUAGES CXX VERSION 0.9.10)
set(SPFFT_SO_VERSION 0)
set(SPFFT_VERSION ${PROJECT_VERSION})
# allow {module}_ROOT variables to be set
if(POLICY CMP0074)
cmake_policy(SET CMP0074 NEW)
endif()
# use INTERFACE_LINK_LIBRARIES property if available
if(POLICY CMP0022)
cmake_policy(SET CMP0022 NEW)
endif()
# set default build type to RELEASE
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Build type" FORCE)
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS
"Debug" "Release" "MinSizeRel" "RelWithDebInfo"
)
endif()
# set language and standard
set(CMAKE_CXX_STANDARD 11)
#add local module path
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${PROJECT_SOURCE_DIR}/cmake/modules)
# Options
option(SPFFT_STATIC "Compile as static library" OFF)
option(SPFFT_OMP "Compile with OpenMP support" ON)
option(SPFFT_MPI "Compile with MPI support" ON)
option(SPFFT_GPU_DIRECT "Compile with GPU direct (GPU aware MPI) support." OFF)
option(SPFFT_BUILD_TESTS "Build tests" OFF)
option(SPFFT_SINGLE_PRECISION "Enable single precision support" OFF)
option(SPFFT_INSTALL "Enable CMake install commands" ON)
option(SPFFT_FORTRAN "Compile fortran module" OFF)
set(SPFFT_GPU_BACKEND "OFF" CACHE STRING "GPU backend")
set_property(CACHE SPFFT_GPU_BACKEND PROPERTY STRINGS
"OFF" "CUDA" "ROCM"
)
# Get GNU standard install prefixes
include(GNUInstallDirs)
# set preferred library type
if (SPFFT_STATIC)
# prefer static over dynamic libraries with the find_library() command by changing the order
set(CMAKE_FIND_LIBRARY_SUFFIXES_SAVE ${CMAKE_FIND_LIBRARY_SUFFIXES})
if(APPLE)
set(CMAKE_FIND_LIBRARY_SUFFIXES .a .tbd .dylib .so)
elseif(UNIX)
set(CMAKE_FIND_LIBRARY_SUFFIXES .a .so)
endif()
set(SPFFT_LIBRARY_TYPE STATIC)
else()
set(SPFFT_LIBRARY_TYPE SHARED)
endif()
set(SPFFT_DEFINITIONS)
set(SPFFT_EXTERNAL_COMPILE_OPTIONS)
set(SPFFT_LIBS)
set(SPFFT_EXTERNAL_LIBS)
set(SPFFT_INTERFACE_LIBS)
set(SPFFT_INTERFACE_INCLUDE_DIRS)
set(SPFFT_INCLUDE_DIRS)
set(SPFFT_EXTERNAL_INCLUDE_DIRS)
set(SPFFT_EXTERNAL_PKG_PACKAGES)
# Options combination check
set(SPFFT_CUDA OFF)
set(SPFFT_ROCM OFF)
if(SPFFT_GPU_BACKEND)
if(SPFFT_GPU_BACKEND STREQUAL "CUDA")
set(SPFFT_CUDA ON)
elseif(SPFFT_GPU_BACKEND STREQUAL "ROCM")
set(SPFFT_ROCM ON)
else()
message(FATAL_ERROR "Invalid GPU backend option")
endif()
endif()
mark_as_advanced(SPFFT_CUDA SPFFT_ROCM)
# Hide symbols by default if tests are not build
if(NOT SPFFT_BUILD_TESTS)
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
set(CMAKE_VISIBILITY_INLINES_HIDDEN 1)
else()
# disable visibility macros if tests are build
list(APPEND SPFFT_DEFINITIONS -DSPFFT_STATIC_DEFINE)
set(CMAKE_CXX_VISIBILITY_PRESET default)
set(CMAKE_VISIBILITY_INLINES_HIDDEN 0)
endif()
# Fortran
if(SPFFT_FORTRAN)
enable_language(Fortran)
endif()
# CUDA
if(SPFFT_CUDA)
enable_language(CUDA)
find_library(CUDA_CUDART_LIBRARY cudart PATHS ${CMAKE_CUDA_IMPLICIT_LINK_DIRECTORIES})
find_library(CUDA_CUFFT_LIBRARY cufft PATHS ${CMAKE_CUDA_IMPLICIT_LINK_DIRECTORIES})
list(APPEND SPFFT_EXTERNAL_LIBS ${CUDA_CUDART_LIBRARY} ${CUDA_CUFFT_LIBRARY})
list(APPEND SPFFT_EXTERNAL_INCLUDE_DIRS ${CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES})
endif()
# ROCM
if(SPFFT_ROCM)
find_package(ROCM REQUIRED COMPONENTS rocfft)
list(APPEND SPFFT_EXTERNAL_INCLUDE_DIRS ${ROCM_INCLUDE_DIRS})
list(APPEND SPFFT_EXTERNAL_LIBS ${ROCM_LIBRARIES})
list(APPEND SPFFT_EXTERNAL_COMPILE_OPTIONS ${ROCM_DEFINITIONS})
endif()
if(SPFFT_MPI)
find_package(MPI COMPONENTS CXX REQUIRED)
list(APPEND SPFFT_EXTERNAL_LIBS MPI::MPI_CXX)
# always add MPI to interface libraries, because mpi.h is included in public header files
if(SPFFT_STATIC)
list(APPEND SPFFT_INTERFACE_LIBS ${MPI_CXX_LIBRARIES})
endif()
list(APPEND SPFFT_INTERFACE_INCLUDE_DIRS ${MPI_CXX_INCLUDE_DIRS})
endif()
if(SPFFT_OMP)
find_package(OpenMP COMPONENTS CXX REQUIRED)
list(APPEND SPFFT_EXTERNAL_LIBS OpenMP::OpenMP_CXX)
if(SPFFT_STATIC)
list(APPEND SPFFT_INTERFACE_LIBS ${OpenMP_CXX_LIBRARIES})
endif()
endif()
if(SPFFT_GPU_DIRECT)
message(STATUS "GPU Direct support enabled: Additional environment variables might have to be set before execution. (e.g \"export MPICH_RDMA_ENABLED_CUDA=1\")")
endif()
# Use MKL if available, otherwise require FFTW3
if(UNIX AND NOT APPLE)
# prefer static MKL in Linux. Together with "-Wl,--exclude-libs,ALL",
# symbols are not visible for linking afterwards and no conflicts with other MKL versions of other libraries should exist.
set(_TMP_SAVE ${CMAKE_FIND_LIBRARY_SUFFIXES})
set(CMAKE_FIND_LIBRARY_SUFFIXES .a .so)
endif()
find_package(MKLSequential)
if(UNIX AND NOT APPLE)
set(CMAKE_FIND_LIBRARY_SUFFIXES ${_TMP_SAVE})
unset(_TMP_SAVE)
endif()
if(MKLSequential_FOUND)
list(APPEND SPFFT_EXTERNAL_LIBS MKL::Sequential)
if(SPFFT_STATIC)
list(APPEND SPFFT_INTERFACE_LIBS ${MKLSequential_LIBRARIES})
endif()
list(APPEND SPFFT_EXTERNAL_PKG_PACKAGES mkl-dynamic-lp64-seq)
else()
find_package(FFTW REQUIRED)
list(APPEND SPFFT_EXTERNAL_LIBS FFTW::FFTW)
if(SPFFT_STATIC)
list(APPEND SPFFT_INTERFACE_LIBS ${FFTW_LIBRARIES})
endif()
if(SPFFT_SINGLE_PRECISION AND NOT FFTW_FLOAT_FOUND)
message(FATAL_ERROR "FFTW library with single precision support NOT FOUND. Disable SPFFT_SINGLE_PRECISION or provide path to library.")
endif()
list(APPEND SPFFT_EXTERNAL_PKG_PACKAGES fftw3)
endif()
if(SPFFT_BUILD_TESTS)
# enable timing with testing
set(SPFFT_TIMING ON)
endif()
# generate config.h
configure_file(include/spfft/config.h.in ${PROJECT_BINARY_DIR}/spfft/config.h)
list(APPEND SPFFT_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/src)
list(APPEND SPFFT_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/include)
list(APPEND SPFFT_INCLUDE_DIRS ${PROJECT_BINARY_DIR})
list(APPEND SPFFT_EXTERNAL_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/ext)
#############################################################################
# All include dirs and definitions must be set before sub-directory is added!
#############################################################################
add_subdirectory(src)
list(APPEND SPFFT_LIBS spfft)
# add tests for developement
if(SPFFT_BUILD_TESTS)
add_subdirectory(tests)
endif()
# reset cmake library suffixes
if(SPFFT_STATIC)
set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES_SAVE})
endif()
SpFFT-0.9.10/LICENSE 0000664 0000000 0000000 00000002715 13572470056 0013546 0 ustar 00root root 0000000 0000000 Copyright (c) 2019 ETH Zurich, Simon Frasch
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
SpFFT-0.9.10/README.md 0000664 0000000 0000000 00000015560 13572470056 0014022 0 ustar 00root root 0000000 0000000 [](https://dev.azure.com/zeadreamplay/SpFFT/_build/latest?definitionId=3&branchName=master)
[](https://spfft.readthedocs.io/en/latest/?badge=latest)
[](https://raw.githubusercontent.com/eth-cscs/SpFFT/master/LICENSE)
# SpFFT
SpFFT - A 3D FFT library for sparse frequency domain data written in C++ with support for MPI, OpenMP, CUDA and ROCm.
It was originally intended for transforms of data with spherical cutoff in frequency domain, as required by some computational material science codes.
For distributed computations, SpFFT uses a slab decomposition in space domain and pencil decomposition in frequency domain (all sparse data within a pencil must be on one rank).
***Fig. 1:*** Illustration of a transform, where data on each MPI rank is identified by color.
### Design Goals
- Sparse frequency domain input
- Reuse of pre-allocated memory
- Support of negative indexing for frequency domain data
- Unified interface for calculations on CPUs and GPUs
- Support of Complex-To-Real and Real-To-Complex transforms, where the full hermitian symmetry property is utilized.
- C++, C and Fortran interfaces
- Parallelization and acceleration are optional
### Interface Design
To allow for pre-allocation and reuse of memory, the design is based on two classes:
- **Grid**: Allocates memory for transforms up to a given size in each dimension.
- **Transform**: Is associated with a *Grid* and can have any size up to the *Grid* dimensions. A *Transform* holds a counted reference to the underlying *Grid*. Therefore, *Transforms* created with the same *Grid* share memory, which is only freed, once the *Grid* and all associated *Transforms* are destroyed.
The user provides memory for storing sparse frequency domain data, while a *Transform* provides memory for space domain data. This implies, that executing a *Transform* will override the space domain data of all other *Transforms* associated with the same *Grid*.
## Documentation
Documentation can be found [here](https://spfft.readthedocs.io/en/latest/).
## Requirements
- C++ Compiler with C++11 support. Supported compilers are:
- GCC 6 and later
- Clang 5 and later
- ICC 18.0 and later
- CMake 3.11 and later
- Library providing a FFTW 3.x interface (FFTW3 or Intel MKL)
- For multi-threading: OpenMP support by the compiler
- For compilation with GPU support:
- CUDA 9.0 and later for Nvidia hardware
- ROCm 2.6 and later for AMD hardware
## Installation
The build system follows the standard CMake workflow. Example:
```console
mkdir build
cd build
cmake .. -DSPFFT_OMP=ON -DSPFFT_MPI=ON -DSPFFT_GPU_BACKEND=CUDA -DSPFFT_SINGLE_PRECISION=OFF -DCMAKE_INSTALL_PREFIX=/usr/local
make -j8 install
```
### CMake options
| Option | Default | Description |
|------------------------|---------|--------------------------------------------------|
| SPFFT_MPI | ON | Enable MPI support |
| SPFFT_OMP | ON | Enable multi-threading with OpenMP |
| SPFFT_GPU_BACKEND | OFF | Select GPU backend. Can be OFF, CUDA or ROCM |
| SPFFT_GPU_DIRECT | OFF | Use GPU aware MPI with GPUDirect |
| SPFFT_SINGLE_PRECISION | OFF | Enable single precision support |
| SPFFT_STATIC | OFF | Build as static library |
| SPFFT_BUILD_TESTS | OFF | Build test executables for developement purposes |
| SPFFT_INSTALL | ON | Add library to install target |
| SPFFT_FORTRAN | OFF | Build Fortran interface module |
## Examples
Further exmples for C++, C and Fortran can be found in the "examples" folder.
```cpp
#include
#include
#include
#include "spfft/spfft.hpp"
int main(int argc, char** argv) {
const int dimX = 2;
const int dimY = 2;
const int dimZ = 2;
std::cout << "Dimensions: x = " << dimX << ", y = " << dimY << ", z = " << dimZ << std::endl
<< std::endl;
// Use default OpenMP value
const int numThreads = -1;
// use all elements in this example.
const int numFrequencyElements = dimX * dimY * dimZ;
// Slice length in space domain. Equivalent to dimZ for non-distributed case.
const int localZLength = dimZ;
// interleaved complex numbers
std::vector frequencyElements;
frequencyElements.reserve(2 * numFrequencyElements);
// indices of frequency elements
std::vector indices;
indices.reserve(dimX * dimY * dimZ * 3);
// initialize frequency domain values and indices
double initValue = 0.0;
for (int xIndex = 0; xIndex < dimX; ++xIndex) {
for (int yIndex = 0; yIndex < dimY; ++yIndex) {
for (int zIndex = 0; zIndex < dimZ; ++zIndex) {
// init with interleaved complex numbers
frequencyElements.emplace_back(initValue);
frequencyElements.emplace_back(-initValue);
// add index triplet for value
indices.emplace_back(xIndex);
indices.emplace_back(yIndex);
indices.emplace_back(zIndex);
initValue += 1.0;
}
}
}
std::cout << "Input:" << std::endl;
for (int i = 0; i < numFrequencyElements; ++i) {
std::cout << frequencyElements[2 * i] << ", " << frequencyElements[2 * i + 1] << std::endl;
}
// create local Grid. For distributed computations, a MPI Communicator has to be provided
spfft::Grid grid(dimX, dimY, dimZ, dimX * dimY, SPFFT_PU_HOST, numThreads);
// create transform
spfft::Transform transform =
grid.create_transform(SPFFT_PU_HOST, SPFFT_TRANS_C2C, dimX, dimY, dimZ, localZLength,
numFrequencyElements, SPFFT_INDEX_TRIPLETS, indices.data());
// Get pointer to space domain data. Alignment fullfills requirements for std::complex.
// Can also be read as std::complex elements (guaranteed by the standard to be binary compatible
// since C++11).
double* spaceDomain = transform.space_domain_data(SPFFT_PU_HOST);
// transform backward
transform.backward(frequencyElements.data(), SPFFT_PU_HOST);
std::cout << std::endl << "After backward transform:" << std::endl;
for (int i = 0; i < transform.local_slice_size(); ++i) {
std::cout << spaceDomain[2 * i] << ", " << spaceDomain[2 * i + 1] << std::endl;
}
// transform forward
transform.forward(SPFFT_PU_HOST, frequencyElements.data(), SPFFT_NO_SCALING);
std::cout << std::endl << "After forward transform (without scaling):" << std::endl;
for (int i = 0; i < numFrequencyElements; ++i) {
std::cout << frequencyElements[2 * i] << ", " << frequencyElements[2 * i + 1] << std::endl;
}
return 0;
}
```
SpFFT-0.9.10/azure-pipelines.yml 0000664 0000000 0000000 00000003254 13572470056 0016377 0 ustar 00root root 0000000 0000000 #######################
# Linux
#######################
jobs:
# CUDA build
- template: CI/azure_templates/ubuntu_build_test.yml
parameters:
job_name: "Ubuntu_GCC_CUDA"
run_mpi_tests: false
run_local_tests: false
cm_mpi: 'ON'
cm_omp: 'ON'
cm_single_precision: 'ON'
cm_gpu_backend: 'CUDA'
# buld and test without MPI and OpenMP
- template: CI/azure_templates/ubuntu_build_test.yml
parameters:
job_name: "Ubuntu_GCC_no_parallel"
run_mpi_tests: false
run_local_tests: true
cm_mpi: 'OFF'
cm_omp: 'OFF'
cm_single_precision: 'OFF'
cm_gpu_backend: 'OFF'
# buld and test with full parallelization
- template: CI/azure_templates/ubuntu_build_test.yml
parameters:
job_name: "Ubuntu_GCC_parallel"
run_mpi_tests: true
run_local_tests: true
cm_mpi: 'ON'
cm_omp: 'ON'
cm_single_precision: 'OFF'
cm_gpu_backend: 'OFF'
#######################
# macOS
#######################
- job: macOS_Clang
pool:
vmImage: 'macOS-10.14'
steps:
- script: |
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
displayName: 'Install Homebrew'
- script: |
brew install fftw
brew install open-mpi
displayName: 'Install dependencies'
# Apple Clang does not support OpenMP
- script: |
mkdir -p build
cd build
cmake .. -DCMAKE_BUILD_TYPE=${BUILD_TYPE} -DSPFFT_BUILD_TESTS=ON -DSPFFT_MPI=ON -DSPFFT_OMP=OFF
make VERBOSE=1
displayName: 'Build'
- script: |
./build/tests/run_local_tests
displayName: 'Run local tests'
- script: |
mpirun -n 2 ./build/tests/run_mpi_tests
displayName: 'Run MPI tests'
SpFFT-0.9.10/cmake/ 0000775 0000000 0000000 00000000000 13572470056 0013614 5 ustar 00root root 0000000 0000000 SpFFT-0.9.10/cmake/SpFFT.pc.in 0000664 0000000 0000000 00000000536 13572470056 0015473 0 ustar 00root root 0000000 0000000 prefix=@CMAKE_INSTALL_PREFIX@
libdir=${prefix}/@CMAKE_INSTALL_LIBDIR@
includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@
external_packages=
Name: SpFFT
Description: Sparse 3D FFT library with MPI, OpenMP, CUDA and ROCm support
Version: @PROJECT_VERSION@
Libs: -L${libdir} -lspfft
Cflags: -I${includedir}
Requires.private: @SPFFT_EXTERNAL_PKG_PACKAGES@
SpFFT-0.9.10/cmake/SpFFTConfig.cmake 0000664 0000000 0000000 00000000313 13572470056 0016663 0 ustar 00root root 0000000 0000000
if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/SpFFTSharedConfig.cmake")
include("${CMAKE_CURRENT_LIST_DIR}/SpFFTSharedConfig.cmake")
else()
include("${CMAKE_CURRENT_LIST_DIR}/SpFFTStaticConfig.cmake")
endif()
SpFFT-0.9.10/cmake/SpFFTConfigVersion.cmake 0000664 0000000 0000000 00000000370 13572470056 0020234 0 ustar 00root root 0000000 0000000
# Prefer shared library
if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/SpFFTSharedConfigVersion.cmake")
include("${CMAKE_CURRENT_LIST_DIR}/SpFFTSharedConfigVersion.cmake")
else()
include("${CMAKE_CURRENT_LIST_DIR}/SpFFTStaticConfigVersion.cmake")
endif()
SpFFT-0.9.10/cmake/SpFFTSharedConfig.cmake 0000664 0000000 0000000 00000000667 13572470056 0020026 0 ustar 00root root 0000000 0000000 # options used for building library
set(SPFFT_OMP @SPFFT_OMP@)
set(SPFFT_MPI @SPFFT_MPI@)
set(SPFFT_STATIC @SPFFT_STATIC@)
set(SPFFT_GPU_DIRECT @SPFFT_GPU_DIRECT@)
set(SPFFT_SINGLE_PRECISION @SPFFT_SINGLE_PRECISION@)
set(SPFFT_GPU_BACKEND @SPFFT_GPU_BACKEND@)
# add version of package
include("${CMAKE_CURRENT_LIST_DIR}/SpFFTSharedConfigVersion.cmake")
# add library target
include("${CMAKE_CURRENT_LIST_DIR}/SpFFTSharedTargets.cmake")
SpFFT-0.9.10/cmake/SpFFTStaticConfig.cmake 0000664 0000000 0000000 00000000667 13572470056 0020047 0 ustar 00root root 0000000 0000000 # options used for building library
set(SPFFT_OMP @SPFFT_OMP@)
set(SPFFT_MPI @SPFFT_MPI@)
set(SPFFT_STATIC @SPFFT_STATIC@)
set(SPFFT_GPU_DIRECT @SPFFT_GPU_DIRECT@)
set(SPFFT_SINGLE_PRECISION @SPFFT_SINGLE_PRECISION@)
set(SPFFT_GPU_BACKEND @SPFFT_GPU_BACKEND@)
# add version of package
include("${CMAKE_CURRENT_LIST_DIR}/SpFFTStaticConfigVersion.cmake")
# add library target
include("${CMAKE_CURRENT_LIST_DIR}/SpFFTStaticTargets.cmake")
SpFFT-0.9.10/cmake/SpFFTTargets.cmake 0000664 0000000 0000000 00000000346 13572470056 0017075 0 ustar 00root root 0000000 0000000
# Prefer shared library
if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/SpFFTSharedTargets.cmake")
include("${CMAKE_CURRENT_LIST_DIR}/SpFFTSharedTargets.cmake")
else()
include("${CMAKE_CURRENT_LIST_DIR}/SpFFTStaticTargets.cmake")
endif()
SpFFT-0.9.10/cmake/modules/ 0000775 0000000 0000000 00000000000 13572470056 0015264 5 ustar 00root root 0000000 0000000 SpFFT-0.9.10/cmake/modules/FindFFTW.cmake 0000664 0000000 0000000 00000007362 13572470056 0017645 0 ustar 00root root 0000000 0000000 # Copyright (c) 2019 ETH Zurich, Simon Frasch
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# 3. Neither the name of the copyright holder nor the names of its contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#.rst:
# FindFFTW
# -----------
#
# This module searches for the fftw3 library.
#
# The following variables are set
#
# ::
#
# FFTW_FOUND - True if double precision fftw library is found
# FFTW_FLOAT_FOUND - True if single precision fftw library is found
# FFTW_LIBRARIES - The required libraries
# FFTW_INCLUDE_DIRS - The required include directory
#
# The following import target is created
#
# ::
#
# FFTW::FFTW
# set paths to look for library
set(_FFTW_PATHS ${FFTW_ROOT} $ENV{FFTW_ROOT})
set(_FFTW_INCLUDE_PATHS)
set(_FFTW_DEFAULT_PATH_SWITCH)
if(_FFTW_PATHS)
# disable default paths if ROOT is set
set(_FFTW_DEFAULT_PATH_SWITCH NO_DEFAULT_PATH)
else()
# try to detect location with pkgconfig
find_package(PkgConfig QUIET)
if(PKG_CONFIG_FOUND)
pkg_check_modules(PKG_FFTW QUIET "fftw3")
endif()
set(_FFTW_PATHS ${PKG_FFTW_LIBRARY_DIRS})
set(_FFTW_INCLUDE_PATHS ${PKG_FFTW_INCLUDE_DIRS})
endif()
find_library(
FFTW_LIBRARIES
NAMES "fftw3"
HINTS ${_FFTW_PATHS}
PATH_SUFFIXES "lib" "lib64"
${_FFTW_DEFAULT_PATH_SWITCH}
)
find_library(
_FFTW_FLOAT_LIBRARY
NAMES "fftw3f"
HINTS ${_FFTW_PATHS}
PATH_SUFFIXES "lib" "lib64"
${_FFTW_DEFAULT_PATH_SWITCH}
)
find_path(FFTW_INCLUDE_DIRS
NAMES "fftw3.h"
HINTS ${_FFTW_PATHS} ${_FFTW_INCLUDE_PATHS}
PATH_SUFFIXES "include" "include/fftw"
${_FFTW_DEFAULT_PATH_SWITCH}
)
# check if found
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(FFTW REQUIRED_VARS FFTW_INCLUDE_DIRS FFTW_LIBRARIES )
# check if single precision library found
if(_FFTW_FLOAT_LIBRARY AND FFTW_FOUND)
list(APPEND FFTW_LIBRARIES ${_FFTW_FLOAT_LIBRARY})
set(FFTW_FLOAT_FOUND TRUE)
else()
set(FFTW_FLOAT_FOUND FALSE)
endif()
# add target to link against
if(FFTW_FOUND)
if(NOT TARGET FFTW::FFTW)
add_library(FFTW::FFTW INTERFACE IMPORTED)
endif()
set_property(TARGET FFTW::FFTW PROPERTY INTERFACE_LINK_LIBRARIES ${FFTW_LIBRARIES})
set_property(TARGET FFTW::FFTW PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${FFTW_INCLUDE_DIRS})
endif()
# prevent clutter in cache
MARK_AS_ADVANCED(FFTW_FOUND FFTW_LIBRARIES FFTW_INCLUDE_DIRS pkgcfg_lib_PKG_FFTW_fftw3 _FFTW_FLOAT_LIBRARY)
SpFFT-0.9.10/cmake/modules/FindMKLSequential.cmake 0000664 0000000 0000000 00000013133 13572470056 0021546 0 ustar 00root root 0000000 0000000 # Copyright (c) 2019 ETH Zurich, Simon Frasch
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# 3. Neither the name of the copyright holder nor the names of its contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#.rst:
# FindMKLSequential
# -----------
#
# This module searches for the sequential 32-bit integer MKL library.
# Only looks for static libraries by default.
#
#
# The following variables are set
#
# ::
#
# MKLSequential_FOUND - True if double precision fftw library is found
# MKLSequential_LIBRARIES - The required libraries
# MKLSequential_INCLUDE_DIRS - The required include directory
# MKLSequential_FFTW_INCLUDE_DIRS - The required fftw interface include directory
#
# The following import target is created
#
# ::
#
# MKL::Sequential
# set paths to look for MKL
set(_MKLSequential_PATHS ${MKLSequential_ROOT} $ENV{MKLROOT})
set(_MKLSequential_INCLUDE_PATHS)
set(_MKLSequential_DEFAULT_PATH_SWITCH)
if(_MKLSequential_PATHS)
# do not look at any default paths if a custom path was set
set(_MKLSequential_DEFAULT_PATH_SWITCH NO_DEFAULT_PATH)
else()
# try to detect location with pkgconfig
if(NOT MKLSequential_ROOT)
find_package(PkgConfig QUIET)
if(PKG_CONFIG_FOUND)
# look for dynmic module, such that a -L flag can be parsed
pkg_check_modules(PKG_MKL QUIET "mkl-dynamic-lp64-seq")
set(_MKLSequential_PATHS ${PKG_MKL_LIBRARY_DIRS})
set(_MKLSequential_INCLUDE_PATHS ${PKG_MKL_INCLUDE_DIRS})
endif()
endif()
endif()
# find all MKL libraries / include directories
find_library(
_MKLSequential_INT_LIB
NAMES "mkl_intel_lp64"
HINTS ${_MKLSequential_PATHS}
PATH_SUFFIXES "intel64_lin" "intel64" "lib/intel64_lin" "lib/intel64"
${_MKLSequential_DEFAULT_PATH_SWITCH}
)
find_library(
_MKLSequential_SEQ_LIB
NAMES "mkl_sequential"
HINTS ${_MKLSequential_PATHS}
PATH_SUFFIXES "intel64_lin" "intel64" "lib/intel64_lin" "lib/intel64"
${_MKLSequential_DEFAULT_PATH_SWITCH}
)
find_library(
_MKLSequential_CORE_LIB
NAMES "mkl_core"
HINTS ${_MKLSequential_PATHS}
PATH_SUFFIXES "intel64_lin" "intel64" "lib/intel64_lin" "lib/intel64"
${_MKLSequential_DEFAULT_PATH_SWITCH}
)
find_path(MKLSequential_INCLUDE_DIRS
NAMES "mkl.h"
HINTS ${_MKLSequential_PATHS} ${_MKLSequential_INCLUDE_PATHS}
PATH_SUFFIXES "include"
${_MKLSequential_DEFAULT_PATH_SWITCH}
)
find_path(MKLSequential_FFTW_INCLUDE_DIRS
NAMES "fftw3.h"
HINTS ${_MKLSequential_PATHS} ${_MKLSequential_INCLUDE_PATHS}
PATH_SUFFIXES "include" "include/fftw" "fftw"
${_MKLSequential_DEFAULT_PATH_SWITCH}
)
# check if found
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(MKLSequential REQUIRED_VARS _MKLSequential_INT_LIB
_MKLSequential_SEQ_LIB _MKLSequential_CORE_LIB MKLSequential_INCLUDE_DIRS MKLSequential_FFTW_INCLUDE_DIRS)
# add target to link against
if(MKLSequential_FOUND)
# libries have inter-dependencies, therefore use link group on Linux
if(UNIX AND NOT APPLE)
set(MKLSequential_LIBRARIES "-Wl,--start-group" ${_MKLSequential_INT_LIB} ${_MKLSequential_SEQ_LIB} ${_MKLSequential_CORE_LIB} "-Wl,--end-group")
else()
set(MKLSequential_LIBRARIES ${_MKLSequential_INT_LIB} ${_MKLSequential_SEQ_LIB} ${_MKLSequential_CORE_LIB})
endif()
# external libries required on unix
if(UNIX)
list(APPEND MKLSequential_LIBRARIES -lpthread -lm -ldl)
endif()
# create interface target
if(NOT TARGET MKL::Sequential)
add_library(MKL::Sequential INTERFACE IMPORTED)
endif()
set_property(TARGET MKL::Sequential PROPERTY INTERFACE_LINK_LIBRARIES ${MKLSequential_LIBRARIES})
set_property(TARGET MKL::Sequential PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${MKLSequential_INCLUDE_DIRS} ${MKLSequential_FFTW_INCLUDE_DIRS})
endif()
# prevent clutter in gui
MARK_AS_ADVANCED(MKLSequential_FOUND MKLSequential_LIBRARIES MKLSequential_INCLUDE_DIRS
_MKLSequential_INT_LIB _MKLSequential_SEQ_LIB _MKLSequential_CORE_LIB MKLSequential_FFTW_INCLUDE_DIRS
_MKLSequential_DEFAULT_PATH_SWITCH _MKLSequential_PATHS)
MARK_AS_ADVANCED(pkgcfg_lib_PKG_MKL_dl pkgcfg_lib_PKG_MKL_m pkgcfg_lib_PKG_MKL_mkl_core
pkgcfg_lib_PKG_MKL_mkl_sequential pkgcfg_lib_PKG_MKL_mkl_intel_lp64 pkgcfg_lib_PKG_MKL_pthread)
SpFFT-0.9.10/cmake/modules/FindROCM.cmake 0000664 0000000 0000000 00000046622 13572470056 0017641 0 ustar 00root root 0000000 0000000 # - Find the ROCM library
#
# Usage:
# find_package(ROCM [REQUIRED] [QUIET] COMPONENTS [components ...] )
#
# Compnents available:
# - hipblas
# - hipsparse
# - rocfft
# - rocblas
# - rocsparse
#
# Commands made available:
# rocm_hip_add_library( [STATIC | SHARED] [FLAGS] [OUTPUT_DIR] [INCLUDE_DIRS] )
# --- Compiles source files into an imported library with hipcc. No global defitions or include directories are taken into account.
#
# The following variables can be set for compilation:
# ROCM_HIPCC_FLAGS ----------------- Flags passed on to hipcc compiler
# ROCM_HIPCC_FLAGS_DEBUG ----------- Flags passed on to hipcc compiler in DEBUG mode
# ROCM_HIPCC_FLAGS_RELEASE --------- Flags passed on to hipcc compiler in RELEASE mode
# ROCM_HIPCC_FLAGS_RELWITHDEBINFO -- Flags passed on to hipcc compiler in RELWITHDEBINFO mode
# ROCM_HIPCC_FLAGS_MINSIZEREL ------ Flags passed on to hipcc compiler in MINSIZEREL mode
#
# The following variables can be set to specify a search location
# ROCM_ROOT ------------ if set, the libraries are exclusively searched under this path
# _ROOT ------ if set, search for component specific libraries at given path. Takes precedence over ROCM_ROOT
#
# The following variables are generated:
# ROCM_FOUND ------------------- true if ROCM is found on the system
# ROCM_LIBRARIES --------------- full path to ROCM
# ROCM_INCLUDE_DIRS ------------ ROCM include directories
# ROCM_DEFINITIONS ------------- ROCM definitions
# ROCM_HCC_EXECUTABLE ---------- ROCM HCC compiler
# ROCM_HCC-CONFIG_EXECUTABLE --- ROCM HCC config
# ROCM_HIPCC_EXECUTABLE -------- HIPCC compiler
# ROCM_HIPCONFIG_EXECUTABLE ---- hip config
# ROCM_HIPIFY-PERL_EXECUTABLE -- hipify
# ROCM_HIP_PLATFORM ------------ Platform identifier: "hcc" or "nvcc"
#
set(ROCM_HIPCC_FLAGS "" CACHE STRING "Flags for HIPCC Compiler")
set(ROCM_HIPCC_FLAGS_DEBUG "-g" CACHE STRING "Debug flags for HIPCC Compiler")
set(ROCM_HIPCC_FLAGS_RELEASE "-O3 -DNDEBUG" CACHE STRING "Release flags for HIPCC Compiler")
set(ROCM_HIPCC_FLAGS_RELWITHDEBINFO "-O2 -g -DNDEBUG" CACHE STRING "Release with debug flags for HIPCC Compiler")
set(ROCM_HIPCC_FLAGS_MINSIZEREL "-Os -DNDEBUG" CACHE STRING "Minimum size flags for HIPCC Compiler")
#If environment variable ROCM_ROOT is specified
if(NOT ROCM_ROOT AND ENV{ROCM_ROOT})
file(TO_CMAKE_PATH "$ENV{ROCM_ROOT}" ROCM_ROOT)
set(ROCM_ROOT "${ROCM_ROOT}" CACHE PATH "Root directory for ROCM installation.")
endif()
set(ROCM_FOUND FALSE)
set(ROCM_LIBRARIES)
set(ROCM_INCLUDE_DIRS)
set(ROCM_DEFINITIONS)
unset(ROCM_HCC_EXECUTABLE)
unset(ROCM_HCC-CONFIG_EXECUTABLE)
unset(ROCM_HIPCC_EXECUTABLE)
unset(ROCM_HIPCONFIG_EXECUTABLE)
unset(ROCM_HIPFIY-PERL-EXECUTABLE)
unset(ROCM_HIP_PLATFORM)
include(FindPackageHandleStandardArgs)
# Finds libraries and include path for rocm modules
# IN:
# - module_name: name of a module (e.g. hcc)
# - following arguments: name of libraries required
# OUT:
# - ROCM_LIBRARIES: Appends to list of libraries
# - ROCM_INCLUDE_DIRS: Appends to include dirs
function(find_rcm_module module_name)
# convert module name to upper case for consistent variable naming
string(TOUPPER ${module_name} MODULE_NAME_UPPER)
if(DEFINED ${MODULE_NAME_UPPER}_ROOT)
set(ROOT_DIR ${${MODULE_NAME_UPPER}_ROOT})
elseif(DEFINED ROCM_ROOT)
set(ROOT_DIR ${ROCM_ROOT})
endif()
# get abosolute path to avoid issues with tilde
if(ROOT_DIR)
get_filename_component(ROOT_DIR ${ROOT_DIR} ABSOLUTE)
endif()
# remove module name from input arguments
set(LIBRARY_NAMES ${ARGV})
list(REMOVE_AT LIBRARY_NAMES 0)
if(${ROCM_FIND_REQUIRED})
set(ROCM_${MODULE_NAME_UPPER}_FIND_REQUIRED TRUE)
else()
set(ROCM_${MODULE_NAME_UPPER}_FIND_REQUIRED FALSE)
endif()
if(${ROCM_FIND_QUIETLY})
set(ROCM_${MODULE_NAME_UPPER}_FIND_QUIETLY TRUE)
else()
set(ROCM_${MODULE_NAME_UPPER}_FIND_QUIETLY FALSE)
endif()
set(ROCM_LIBRARIES_${MODULE_NAME_UPPER})
if(ROOT_DIR)
# find libraries
foreach(library_name IN LISTS LIBRARY_NAMES)
find_library(
ROCM_LIBRARIES_${library_name}
NAMES ${library_name}
PATHS ${ROOT_DIR}
PATH_SUFFIXES "lib" "${module_name}/lib"
NO_DEFAULT_PATH
)
find_package_handle_standard_args(ROCM_${MODULE_NAME_UPPER} FAIL_MESSAGE
"For ROCM module ${module_name}, library ${library_name} could not be found. Please specify ROCM_ROOT or ${MODULE_NAME_UPPER}_ROOT."
REQUIRED_VARS ROCM_LIBRARIES_${library_name})
if(ROCM_LIBRARIES_${library_name})
list(APPEND ROCM_LIBRARIES_${MODULE_NAME_UPPER} ${ROCM_LIBRARIES_${library_name}})
mark_as_advanced(ROCM_LIBRARIES_${library_name})
endif()
endforeach()
# find include directory
find_path(
ROCM_INCLUDE_DIRS_${MODULE_NAME_UPPER}
NAMES ${module_name}/include
PATHS ${ROOT_DIR} ${ROOT_DIR}/..
NO_DEFAULT_PATH
)
# set include directory for module if found
if(ROCM_INCLUDE_DIRS_${MODULE_NAME_UPPER})
set(ROCM_INCLUDE_DIRS_${MODULE_NAME_UPPER} ${ROCM_INCLUDE_DIRS_${MODULE_NAME_UPPER}}/${module_name}/include)
endif()
else()
foreach(library_name IN LISTS LIBRARY_NAMES)
find_library(
ROCM_LIBRARIES_${library_name}
NAMES ${library_name}
PATHS /opt/rocm
PATH_SUFFIXES "lib" "lib64" "${module_name}/lib" "rocm/${module_name}/lib"
)
find_package_handle_standard_args(ROCM_${MODULE_NAME_UPPER} FAIL_MESSAGE
"For ROCM module ${module_name}, library ${library_name} could not be found. Please specify ROCM_ROOT or ${MODULE_NAME_UPPER}_ROOT."
REQUIRED_VARS ROCM_LIBRARIES_${library_name})
if(ROCM_LIBRARIES_${library_name})
list(APPEND ROCM_LIBRARIES_${MODULE_NAME_UPPER} ${ROCM_LIBRARIES_${library_name}})
mark_as_advanced(ROCM_LIBRARIES_${library_name})
endif()
endforeach()
# find include directory
find_path(
ROCM_INCLUDE_DIRS_${MODULE_NAME_UPPER}
NAMES ${module_name}/include
PATHS /opt/rocm/
)
# set include directory for module if found
if(ROCM_INCLUDE_DIRS_${MODULE_NAME_UPPER})
set(ROCM_INCLUDE_DIRS_${MODULE_NAME_UPPER} ${ROCM_INCLUDE_DIRS_${MODULE_NAME_UPPER}}/${module_name}/include)
endif()
endif()
# check if all required parts found
find_package_handle_standard_args(ROCM_${MODULE_NAME_UPPER} FAIL_MESSAGE
"ROCM module ${module_name} could not be found. Please specify ROCM_ROOT or ${MODULE_NAME_UPPER}_ROOT."
REQUIRED_VARS ROCM_INCLUDE_DIRS_${MODULE_NAME_UPPER})
if(ROCM_INCLUDE_DIRS_${MODULE_NAME_UPPER})
mark_as_advanced(ROCM_INCLUDE_DIRS_${MODULE_NAME_UPPER})
endif()
# set global variables
if(ROCM_LIBRARIES_${MODULE_NAME_UPPER})
set(ROCM_LIBRARIES ${ROCM_LIBRARIES} ${ROCM_LIBRARIES_${MODULE_NAME_UPPER}} PARENT_SCOPE)
endif()
if(ROCM_INCLUDE_DIRS_${MODULE_NAME_UPPER})
set(ROCM_INCLUDE_DIRS ${ROCM_INCLUDE_DIRS} ${ROCM_INCLUDE_DIRS_${MODULE_NAME_UPPER}} PARENT_SCOPE)
endif()
endfunction()
# Finds executables of rocm modules
# IN:
# - module_name: name of a module (e.g. hcc)
# - executable_name: name of the executable (e.g. hcc)
# OUT:
# - ROCM_${executable_name}_EXECUTABLE: Path to executable
function(find_rocm_executable module_name executable_name)
string(TOUPPER ${module_name} MODULE_NAME_UPPER)
string(TOUPPER ${executable_name} EXECUTABLE_NAME_UPPER)
unset(ROCM_${EXECUTABLE_NAME_UPPER}_EXECUTABLE PARENT_SCOPE)
if(DEFINED ${MODULE_NAME_UPPER}_ROOT)
set(ROOT_DIR ${${MODULE_NAME_UPPER}_ROOT})
elseif(DEFINED ROCM_ROOT)
set(ROOT_DIR ${ROCM_ROOT})
endif()
# get abosolute path to avoid issues with tilde
if(ROOT_DIR)
get_filename_component(ROOT_DIR ${ROOT_DIR} ABSOLUTE)
endif()
if(ROOT_DIR)
find_file(
ROCM_${EXECUTABLE_NAME_UPPER}_EXECUTABLE
NAMES ${executable_name}
PATHS ${ROOT_DIR}
PATH_SUFFIXES "bin" "${module_name}/bin"
NO_DEFAULT_PATH
)
else()
find_file(
ROCM_${EXECUTABLE_NAME_UPPER}_EXECUTABLE
NAMES ${executable_name}
PATHS "/opt/rocm"
PATH_SUFFIXES "bin" "${module_name}/bin"
)
endif()
set(ROCM_${EXECUTABLE_NAME_UPPER} ROCM_${EXECUTABLE_NAME_UPPER} PARENT_SCOPE)
if(${ROCM_FIND_REQUIRED})
set(ROCM_${MODULE_NAME_UPPER}_${EXECUTABLE_NAME_UPPER}_FIND_REQUIRED TRUE)
else()
set(ROCM_${MODULE_NAME_UPPER}_${EXECUTABLE_NAME_UPPER}_FIND_REQUIRED FALSE)
endif()
if(${ROCM_FIND_QUIETLY})
set(ROCM_${MODULE_NAME_UPPER}_${EXECUTABLE_NAME_UPPER}_FIND_QUIETLY TRUE)
else()
set(ROCM_${MODULE_NAME_UPPER}_${EXECUTABLE_NAME_UPPER}_FIND_QUIETLY FALSE)
endif()
find_package_handle_standard_args(ROCM FAIL_MESSAGE
"ROCM_${MODULE_NAME_UPPER}_${EXECUTABLE_NAME_UPPER} ${executable_name} executable could not be found. Please specify ROCM_ROOT or ${MODULE_NAME_UPPER}_ROOT."
REQUIRED_VARS ROCM_${EXECUTABLE_NAME_UPPER}_EXECUTABLE)
if(ROCM_${EXECUTABLE_NAME_UPPER}_EXECUTABLE)
set(ROCM_${EXECUTABLE_NAME_UPPER}_EXECUTABLE ${ROCM_${EXECUTABLE_NAME_UPPER}_EXECUTABLE} PARENT_SCOPE)
mark_as_advanced(ROCM_${EXECUTABLE_NAME_UPPER}_EXECUTABLE)
endif()
endfunction()
# find compilers
find_rocm_executable(hcc hcc)
find_rocm_executable(hip hipcc)
if(ROCM_HIPCC_EXECUTABLE AND ROCM_HCC_EXECUTABLE)
set(ROCM_FOUND TRUE)
else()
set(ROCM_FOUND FALSE)
return()
endif()
# find other executables and libraries
find_rocm_executable(hcc hcc-config)
find_rocm_executable(hip hipconfig)
find_rocm_executable(hip hipify-perl)
find_rcm_module(hcc LTO mcwamp mcwamp_cpu mcwamp_hsa hc_am)
find_rcm_module(hip hip_hcc)
find_rcm_module(rocm hsa-runtime64)
# parse hip config
execute_process(COMMAND ${ROCM_HIPCONFIG_EXECUTABLE} -P OUTPUT_VARIABLE ROCM_HIP_PLATFORM RESULT_VARIABLE RESULT_VALUE)
if(NOT ${RESULT_VALUE} EQUAL 0)
message(FATAL_ERROR "Error parsing platform identifier from hipconfig! Code: ${RESULT_VALUE}")
endif()
if(NOT ROCM_HIP_PLATFORM)
message(FATAL_ERROR "Empty platform identifier from hipconfig!")
endif()
# set definitions
if("${ROCM_HIP_PLATFORM}" STREQUAL "hcc")
set(ROCM_DEFINITIONS -D__HIP_PLATFORM_HCC__)
elseif("${ROCM_HIP_PLATFORM}" STREQUAL "nvcc")
set(ROCM_DEFINITIONS -D__HIP_PLATFORM_NVCC__)
else()
message(FATAL_ERROR "Could not parse platform identifier from hipconfig! Value: ${ROCM_HIP_PLATFORM}")
endif()
# find libraries for each specified components
foreach(module_name IN LISTS ROCM_FIND_COMPONENTS)
# set required libaries for each module
if("${module_name}" STREQUAL "hipblas")
find_rcm_module(hipblas hipblas)
elseif("${module_name}" STREQUAL "hipsparse")
find_rcm_module(hipsparse hipsparse)
elseif("${module_name}" STREQUAL "rocblas")
find_rcm_module(rocblas rocblas)
elseif("${module_name}" STREQUAL "rocsparse")
find_rcm_module(rocsparse rocsparse)
elseif("${module_name}" STREQUAL "rocfft")
find_rcm_module(rocfft rocfft rocfft-device)
else()
message(FATAL_ERROR "Unrecognized component \"${module_name}\" in FindROCM module!")
endif()
endforeach()
# Generates library compiled with hipcc
# Usage:
# rocm_hip_add_library( [STATIC | SHARED] [FLAGS] [OUTPUT_DIR] [INCLUDE_DIRS] )
macro(rocm_add_library)
cmake_parse_arguments(
ROCM_ARG
"SHARED;STATIC"
"OUTPUT_DIR"
"FLAGS;INCLUDE_DIRS"
${ARGN}
)
# allow either STATIC or SHARED
if(ROCM_ARG_SHARED AND ROCM_ARG_STATIC)
message(FATAL_ERROR "rocm_hip_add_library: library cannot by both static and shared!")
endif()
# default to SHARED
if(NOT (ROCM_ARG_SHARED OR ROCM_ARG_STATIC))
set(ROCM_ARG_SHARED TRUE)
endif()
# default to current binary output directory
if(NOT ROCM_ARG_OUTPUT_DIR)
set(ROCM_ARG_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR})
endif()
# parse positional arguments
list(LENGTH ROCM_ARG_UNPARSED_ARGUMENTS NARGS)
if(${NARGS} LESS 2)
message(FATAL_ERROR "rocm_hip_add_library: Not enough arguments!")
endif()
list(GET ROCM_ARG_UNPARSED_ARGUMENTS 0 ROCM_ARG_NAME)
list(REMOVE_AT ROCM_ARG_UNPARSED_ARGUMENTS 0)
set(ROCM_ARG_SOURCES ${ROCM_ARG_UNPARSED_ARGUMENTS})
# generate include flags
set(_ROCM_FULL_PATH_INCLUDE_FLAGS)
foreach(_rocm_iternal_dir IN LISTS ROCM_ARG_INCLUDE_DIRS)
if(NOT IS_ABSOLUTE ${_rocm_iternal_dir})
get_filename_component(_rocm_iternal_dir ${_rocm_iternal_dir} ABSOLUTE)
endif()
list(APPEND _ROCM_FULL_PATH_INCLUDE_FLAGS -I${_rocm_iternal_dir})
endforeach()
# generate full path to source files
unset(_ROCM_SOURCES)
foreach(source IN LISTS ROCM_ARG_SOURCES)
if(NOT IS_ABSOLUTE ${source})
get_filename_component(source ${source} ABSOLUTE)
endif()
set(_ROCM_SOURCES ${_ROCM_SOURCES} ${source})
endforeach()
get_filename_component(ROCM_ARG_OUTPUT_DIR ${ROCM_ARG_OUTPUT_DIR} ABSOLUTE)
# generate flags to use
set(_ROCM_STD_FLAGS ${ROCM_ARG_FLAGS} ${ROCM_HIPCC_FLAGS})
if(_ROCM_STD_FLAGS)
list(FILTER _ROCM_STD_FLAGS INCLUDE REGEX -std=)
endif()
set(_ROCM_FLAGS ${ROCM_ARG_FLAGS})
if(CMAKE_CXX_STANDARD AND NOT _ROCM_STD_FLAGS)
list(APPEND _ROCM_FLAGS -std=c++${CMAKE_CXX_STANDARD})
endif()
if(CMAKE_BUILD_TYPE)
string(TOUPPER ${CMAKE_BUILD_TYPE} _ROCM_BUILD_TYPE_UPPER)
list(APPEND _ROCM_FLAGS ${ROCM_HIPCC_FLAGS_${_ROCM_BUILD_TYPE_UPPER}})
endif()
if(NOT ROCM_HIPCC_EXECUTABLE)
message(FATAL_ERROR "HIPCC executable not found!")
endif()
if(ROCM_ARG_SHARED)
set(_ROCM_FLAGS ${_ROCM_FLAGS} -fPIC)
endif()
# compile all files to .o
set(_ROCM_OBJS)
set(_ROCM_OBJ_TARGETS)
foreach(_rocm_file IN LISTS _ROCM_SOURCES)
# create output directory for .o file
get_filename_component(_ROCM_CURRENT_DIR ${_rocm_file} DIRECTORY)
file(RELATIVE_PATH _ROCM_CURRENT_DIR "${CMAKE_CURRENT_SOURCE_DIR}" ${_ROCM_CURRENT_DIR})
set(_ROCM_OBJ_OUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${ROCM_ARG_NAME}.dir/${_ROCM_CURRENT_DIR}")
file(MAKE_DIRECTORY ${_ROCM_OBJ_OUT_DIR})
# set .o name and path
get_filename_component(_ROCM_FILE_NAME_ONLY ${_rocm_file} NAME)
set(_ROCM_OBJ_FILE ${_ROCM_OBJ_OUT_DIR}/${_ROCM_FILE_NAME_ONLY}.o)
list(APPEND _ROCM_OBJS ${_ROCM_OBJ_FILE})
list(APPEND _ROCM_OBJ_TARGETS HIP_TARGET_${_ROCM_FILE_NAME_ONLY})
# compile .o file
add_custom_target(HIP_TARGET_${_ROCM_FILE_NAME_ONLY} COMMAND ${ROCM_HIPCC_EXECUTABLE} -c ${_rocm_file} -o ${_ROCM_OBJ_FILE} ${_ROCM_FLAGS} ${_ROCM_FULL_PATH_INCLUDE_FLAGS}
WORKING_DIRECTORY ${_ROCM_OBJ_OUT_DIR} SOURCES ${_rocm_file})
endforeach()
# compile shared library
if(ROCM_ARG_SHARED)
add_custom_target(HIP_TARGET_${ROCM_ARG_NAME} COMMAND ${ROCM_HIPCC_EXECUTABLE} ${_ROCM_OBJS} -fPIC --shared -o ${ROCM_ARG_OUTPUT_DIR}/lib${ROCM_ARG_NAME}.so
${_ROCM_FLAGS} ${_ROCM_FULL_PATH_INCLUDE_FLAGS}
WORKING_DIRECTORY ${ROCM_ARG_OUTPUT_DIR})
add_library(${ROCM_ARG_NAME} INTERFACE)
target_link_libraries(${ROCM_ARG_NAME} INTERFACE ${ROCM_ARG_OUTPUT_DIR}/lib${ROCM_ARG_NAME}.so)
# add depencies
add_dependencies(${ROCM_ARG_NAME} HIP_TARGET_${ROCM_ARG_NAME})
foreach(_rocm_target IN LISTS _ROCM_OBJ_TARGETS)
add_dependencies(HIP_TARGET_${ROCM_ARG_NAME} ${_rocm_target})
endforeach()
endif()
# static library
if(ROCM_ARG_STATIC)
# create library from object files
add_library(${ROCM_ARG_NAME} ${_ROCM_OBJS})
set_target_properties(${ROCM_ARG_NAME} PROPERTIES LINKER_LANGUAGE CXX)
set_source_files_properties(
${_ROCM_OBJS}
PROPERTIES
EXTERNAL_OBJECT true
GENERATED true
)
# add dependencies
foreach(_rocm_target IN LISTS _ROCM_OBJ_TARGETS)
add_dependencies(${ROCM_ARG_NAME} ${_rocm_target})
endforeach()
endif()
endmacro()
# Generates compiled objects
# Usage:
# rocm_hip_add_library( [FLAGS] [INCLUDE_DIRS] )
macro(rocm_generate_objects)
cmake_parse_arguments(
ROCM_ARG
"" # options
"" # single value args
"FLAGS;INCLUDE_DIRS" # multi value args
${ARGN}
)
set(ROCM_ARG_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR})
# parse positional arguments
list(LENGTH ROCM_ARG_UNPARSED_ARGUMENTS NARGS)
if(${NARGS} LESS 3)
message(FATAL_ERROR "rocm_hip_add_library: Not enough arguments!")
endif()
list(GET ROCM_ARG_UNPARSED_ARGUMENTS 0 ROCM_ARG_OBJECT_VAR)
list(REMOVE_AT ROCM_ARG_UNPARSED_ARGUMENTS 0)
list(GET ROCM_ARG_UNPARSED_ARGUMENTS 0 ROCM_ARG_TARGETS_VAR)
list(REMOVE_AT ROCM_ARG_UNPARSED_ARGUMENTS 0)
set(ROCM_ARG_SOURCES ${ROCM_ARG_UNPARSED_ARGUMENTS})
# generate include flags
set(_ROCM_FULL_PATH_INCLUDE_FLAGS)
foreach(_rocm_iternal_dir IN LISTS ROCM_ARG_INCLUDE_DIRS)
if(NOT IS_ABSOLUTE ${_rocm_iternal_dir})
get_filename_component(_rocm_iternal_dir ${_rocm_iternal_dir} ABSOLUTE)
endif()
list(APPEND _ROCM_FULL_PATH_INCLUDE_FLAGS -I${_rocm_iternal_dir})
endforeach()
# generate full path to source files
unset(_ROCM_SOURCES)
foreach(source IN LISTS ROCM_ARG_SOURCES)
if(NOT IS_ABSOLUTE ${source})
get_filename_component(source ${source} ABSOLUTE)
endif()
set(_ROCM_SOURCES ${_ROCM_SOURCES} ${source})
endforeach()
get_filename_component(ROCM_ARG_OUTPUT_DIR ${ROCM_ARG_OUTPUT_DIR} ABSOLUTE)
# generate flags to use
set(_ROCM_STD_FLAGS ${ROCM_ARG_FLAGS} ${ROCM_HIPCC_FLAGS})
if(_ROCM_STD_FLAGS)
list(FILTER _ROCM_STD_FLAGS INCLUDE REGEX -std=)
endif()
set(_ROCM_FLAGS ${ROCM_ARG_FLAGS})
if(CMAKE_CXX_STANDARD AND NOT _ROCM_STD_FLAGS)
list(APPEND _ROCM_FLAGS -std=c++${CMAKE_CXX_STANDARD})
endif()
if(CMAKE_BUILD_TYPE)
string(TOUPPER ${CMAKE_BUILD_TYPE} _ROCM_BUILD_TYPE_UPPER)
list(APPEND _ROCM_FLAGS ${ROCM_HIPCC_FLAGS_${_ROCM_BUILD_TYPE_UPPER}})
endif()
if(NOT ROCM_HIPCC_EXECUTABLE)
message(FATAL_ERROR "HIPCC executable not found!")
endif()
# compile all files to .o
set(_ROCM_OBJS)
set(_ROCM_OBJ_TARGETS)
foreach(_rocm_file IN LISTS _ROCM_SOURCES)
get_filename_component(_ROCM_FILE_NAME_ONLY ${_rocm_file} NAME)
set(_ROCM_TARGET_NAME hip_target_${_ROCM_FILE_NAME_ONLY})
# create output directory for .o file
get_filename_component(_ROCM_CURRENT_DIR ${_rocm_file} DIRECTORY)
file(RELATIVE_PATH _ROCM_CURRENT_DIR "${CMAKE_CURRENT_SOURCE_DIR}" ${_ROCM_CURRENT_DIR})
set(_ROCM_OBJ_OUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${_ROCM_TARGET_NAME}.dir")
file(MAKE_DIRECTORY ${_ROCM_OBJ_OUT_DIR})
# set .o name and path
set(_ROCM_OBJ_FILE ${_ROCM_OBJ_OUT_DIR}/${_ROCM_FILE_NAME_ONLY}.o)
list(APPEND _ROCM_OBJS ${_ROCM_OBJ_FILE})
list(APPEND _ROCM_OBJ_TARGETS ${_ROCM_TARGET_NAME})
# compile .o file
add_custom_target(${_ROCM_TARGET_NAME} ALL
COMMAND ${ROCM_HIPCC_EXECUTABLE} -c ${_rocm_file} -o ${_ROCM_OBJ_FILE} ${_ROCM_FLAGS} ${_ROCM_FULL_PATH_INCLUDE_FLAGS}
WORKING_DIRECTORY ${_ROCM_OBJ_OUT_DIR} SOURCES ${_rocm_file})
endforeach()
set_source_files_properties(
${_ROCM_OBJS}
PROPERTIES
EXTERNAL_OBJECT true
GENERATED true
)
# set input variable to object files
set(${ROCM_ARG_OBJECT_VAR} ${_ROCM_OBJS})
# set targets for dependency management
set(${ROCM_ARG_TARGETS_VAR} ${_ROCM_OBJ_TARGETS})
endmacro()
SpFFT-0.9.10/docs/ 0000775 0000000 0000000 00000000000 13572470056 0013464 5 ustar 00root root 0000000 0000000 SpFFT-0.9.10/docs/Doxyfile 0000664 0000000 0000000 00000000754 13572470056 0015200 0 ustar 00root root 0000000 0000000 PROJECT_NAME = "SpFFT"
XML_OUTPUT = xml
INPUT = ../include
INCLUDE_PATH = ../include ../src
GENERATE_LATEX = NO
GENERATE_MAN = NO
GENERATE_RTF = NO
CASE_SENSE_NAMES = NO
GENERATE_HTML = NO
GENERATE_XML = YES
RECURSIVE = YES
QUIET = YES
JAVADOC_AUTOBRIEF = YES
WARN_IF_UNDOCUMENTED = NO
MACRO_EXPANSION = YES
PREDEFINED = "SPFFT_MPI" "SPFFT_SINGLE_PRECISION" "SPFFT_EXPORT"
EXTRACT_PRIVATE = NO
EXTRACT_ALL = YES
SpFFT-0.9.10/docs/Makefile 0000664 0000000 0000000 00000001111 13572470056 0015116 0 ustar 00root root 0000000 0000000 # Minimal makefile for Sphinx documentation
#
# You can set these variables from the command line.
SPHINXOPTS =
SPHINXBUILD = sphinx-build
SOURCEDIR = source
BUILDDIR = build
# Put it first so that "make" without argument is like "make help".
help:
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
.PHONY: help Makefile
# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
SpFFT-0.9.10/docs/images/ 0000775 0000000 0000000 00000000000 13572470056 0014731 5 ustar 00root root 0000000 0000000 SpFFT-0.9.10/docs/images/sparse_to_dense.png 0000664 0000000 0000000 00000673373 13572470056 0020637 0 ustar 00root root 0000000 0000000 ‰PNG
IHDR G à Æ?tç IDATxœì½iו&vÎÍ|KU¡ªX(öX\RâÒØÝl¥&ÕÓmК–4#ù'<žð8¶Ãa›ø1?<Ï8¢Óh·ž^"O[t4G¢$R$(‘D$ ‚ ö°Ôþ–¼Ç‘¯^fž»ä{¯°UÀùB"^eÞ¼yïÍíœï~ç\@ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @0ï€rÉ·9ðá‡.oذaéäääâ©©©ËõzýÔ~ô£‰Û}`@ ×"Âõì³}½Ai«¦hs]×?ª×ßýÿã‘!æ&„Ü–ˆ?XÏ>ûl¹T*(
ÛµÖwOMMõV«Õ œ¯V«'”R#âѱ±±ñ}ûöMË"@ h…ØÆÜóÄ?훪ݧ•þø¢"¢i:4Y©þZ)|=BúYý2^üç/ÿÕ¨¨@07 äˆà¶ÃSO=UZ¹rå†z½þm&¢žx*•
T«UÐZ7†#õ8"ž€CµZíÈG}têÈ‘#¹k@ ÿ÷ïý·=zñ…ˆêÛúw Õ¢d7Ŷeì|‘¨Ñy <H{±¦^{é½£¿Ù3¼o\T øü äˆàvzî¹çzëõúZ"ú ¬ÓZwó¾OOOCVKÉD4…ˆ§ƒ ˆ‰’C pîïþîïbò„ä.@ ¸ý°{çÎpÙÊMCeUÿ}€#Ä ŠgÚÎ¥¿1',&K" «
ð ½¢4¼Ráð§kמ߽{·ß(7BŽnilß¾½°iÓ¦…Åbq³Rê! Xªµ.ùú“#±z¤CT´Öç
…ÂI":BDŸž={vìÉ'Ÿ¬<ÿüó$„‰@ Á‹óð®®þõ½«C ' éÛ°jd²œ¬ôoN–x+K€`áo@áϦuíM:]>÷7õC{÷îÄÆn„Ürˆc=wìØ®Y³fy__ßýDt".Š··ê«VÓ)QÑ("^@ÄkµÚÇ—.]:µ|ùòÉ_|±Q™|È@ æ79ëy¤üû+ïº[uEÿY¤é¥6ĺNx4HØ«Éï~ƒ±E¢Qч Ÿ×"zí7gN¼÷ú•+—ž~úéH&ä‚!G·BäêÕ«]<òÈR ¸G)µjU'}ŒÉ‘X=rPAÄsDt´Z~\.—/þæ7¿«V«Õ‡~¸ºgÏžHî:@ ‚¹Ý»w«}/¼PüúôvõÞUPøuü Ä ˜2„³>'+&M´ÎH’øoŸŠ“£›ÿÄebœ«$ÎIr4ü)z}J×>þ·¯½vA+5Yß¿Mn)àÚ!äˆ`^#þ`íÙ³§{ÅŠCƒƒƒ+Êåòzõ¥T_§¤H‚HŽ€R*V Äl~%V•(¥NÑÅJ¥rêÀ—ŠÅâØôôô¸%@ s»ví
N½óÎà?Ýò•õÑÂú=_F€/Ç!ÚÆTHBn$JþÛ†¯lƒÁ,ÌÆ8676@5¡1<èã:ÕÞû?ùÖ± êçB¢—&…,f!Gó¸}ûö0Ã…ƒƒƒ«ïTJFÄ%DÔuýé”i-÷sÄeY2©µ¾¢”QJ]¸|ùòùóçÏŸÃpdãÆcB”@ |>ˆ'Ýö¿ôR¹°úë+ï~ Z@¨ ·#àèçùBlÄ$FlI²éX“í½ á’!^5J–À$ÝK€ .Òi 8
¤Oúé±>*
ŸTÇÇÏï®Êm%´†#‚yƒøƒõÃþ°T*•V¬]»v ¬j"}D^o?n”r$!O’$‡H‰¿fqRø„ñŠ7/^¼xfjjê8 œ]´hÑå—_~Y–@ ¸ÉˆU"+.Ôz7,,ÞÓÕ]|2Äp; ~.K³Qˆ˜ÈŒ”ô€æ5ä*OÌøj&"Œ"i–KÃnRr$;¬Q5b€Fàh:Z©U|pþÂþ*DLLOŸø‹Ÿÿ|Lî)À…#‚98ŸÈc=¶`åÊ•K¥Ò}M•È (Ì6t¦fKŽ´StrLB Åa¤P×ZÇËÀ™8©+ œˆ&ccc"@ ¸qˆmÌÿýÉ?ê^Pz|AwéQáƒ8+‘ ˜9‘EpXh®Òk„½ð\"Æo`™WY]
‚$ÝÇ88-’P%”*N¬£fVlj`G è,QtàÐ…ï†îtu]ú?öì™’ÛJ rD0‡+EŽ?ÞS©T¾†áCˆ¸ ÊíV¹V´[¦2ÄG~ØÇ´*“„ßĪ’ b²$V\€sÕjõHÇN:uAˆ@ ‚kÃî;Ãî¡¡EÝPxbA©ð-Tø¢ê£æ¤ZÄ…½
XˆLR†Mxeå)S‰ WwXä p5ŠEœØçãudd2Ö$Û–IÕ)D5h*— èhøp¢Z{]!¾ñƒCÃG^Ú¿Rn+Áí
!GsÛ·o/lÞ¼ym-‹_TJ-ÓZ—nv;;]Ê×Cf8ûìšvÇ€'ü†ÕEñ¿AÄÿNQ¬(9DD.¼ðÂ7&‹¬@ Á-ŒÿkçwÊÑòê’ ‹O!Ò?Q¨¶@¥Lu±y
g»•4Õ “ëX–sœzãM*%\œ\¬IÝŒ”1ê1¢pX²W°öSBÈ4ˆÒ€¤téK
á=Mz/èúš¬T>~îÅGe©`Áí!Gs;wîׯ_¿"Š¢íJ©{¢(ü,ÛÖ)9³HÊÚ‰
ÅWÖG¦Xÿ6’»ÆŠ"úOLLL|ò£ýhb–Ý@ ¸¥ñ'OýW¥Þ…c÷
ÿ ý"®Õ3Ü€ÓíV¹Dìü É`$Mõ®JFØŒ™2Äd`ÐH´
é±F:l–3ÂhÐLâš’%ÄR–`Zon/‰""¸‚ˆÒIÓ~U›~ãÿæo.ÊS"¸Õ!äˆàsÇSO=UZ¹råšZ¶ƒˆb¿f•ìêÆÀGŽøˆ è€È€¤GŸR„ïóÕÅÁÛÓÌY¯€s”ˆ>ššš:vüøñ«Ã’™\ ÁmŠÿâÑG{[·éAEúð÷aI2-“«²p˜v¶(Ïûܹâ$ ‘EH —'1Ó¬f‰WyN¦Záíà¡@ÀÂkMJ£M*U«˜}aýÈvÖ èüœH½ Þxuäô©ï¿ô’„ßn99"ø\ÐX*mÿþrÿªB¡ð%õæ8É*Ï'òy‘#>åG^°Hvá2à!=|j¾ÏW·ç<¤”ºJDljè°R*ÎU2 Õ[·ÒóÏ?O"‘@p+"^yæ&õÕû+Ûëß…¿ÛH²Úð÷1ÍÁá£1Í£ÄmxHÿ6äVØ0¥Hü¯nÖo[µFÒV¦!FT$¹K8Ab¦A¦IêD‡øpÕ"YÞoƒ4jö“2¢EéS ¸_E¾ZVåOþåû?›X·n~ñŵؘ‚ù!GŸbâcÛ¶m…žõëׯ‹Ó‹ â†8#ø\¸
œÉ#EÀ£êÈC«Ðš>55uúwÞ[¼xqu×®]u!K@ ÌgÄ“nßÿþ÷ËÿzÛ“ƒÓKèQúˆÁN"êÏ“v>éæ[fדIÀ¥‚E°¸I\yJI¾Ï!Xx»šû%òW§±—öeį)kcúƒ&Ù“äWñ5PèDð"¾E„oÑôÿæÿ}å,ôÂä¦M›ª{÷îÄÆÌ'9"¸©ˆ ‘Ç<8yòd÷C=´¨P(Ü [ãåx?‹$«³A§ää+6œ²"íh£2ÉC^Ì\ˆˆ."âE":EÑ©±±±‘C‡Æ±}ûöÕoÈ`
@ ÜDĄțù—…cµÚÂÿ~ûÎuº¿FˆÛ¨7=s–¥ÔQ‰ˆ•ÿcF-¢sVŽÉ–äõ®>Ó¡:%SŒ¤µš [íœ"‰¹
MŠÖ$'dz²ÿ;=—±êN–ß$k
Uð(!Q¿Ô5øÍÑKg>ù³wß=W.—'>\¢D0×!äˆà¦ &EvìØÑÕßß?´xñâÅbqRêN"Z !|a3í“#ÓÓÙÂ/yÄD«Ð»ŒïØNÔ"vY»žfR×8ë¥XQBD'=z¶Z^ÕZÝÿýõ={öD7i¸@ f˜ùÉ_ü‡þon¹cÏ"u¯xD𬂲MT³´¹¯¥ºƒogd0‚À$E2²Ä^ÌÆQs¤ä†Ê”'VVß’ÂÀˆ“<;Ú»p‹,¬ö
=I+Z/fÿÌÜ(¤u¨.#ècj?éê;?<ðáGÇ.Ÿ…óC Õ=’O0!äˆà†"&E{ì±åryÕ’%K6†a¸ –"¢7tf.$