##*****************************************************************************
##                              INTEL CONFIDENTIAL
## Copyright(C) 2006-2010 Intel Corporation. All Rights Reserved.
## The source code contained  or  described herein and all documents related to
## the source code ("Material") are owned by Intel Corporation or its suppliers
## or licensors.  Title to the  Material remains with  Intel Corporation or its
## suppliers and licensors. The Material contains trade secrets and proprietary
## and  confidential  information of  Intel or its suppliers and licensors. The
## Material  is  protected  by  worldwide  copyright  and trade secret laws and
## treaty  provisions. No part of the Material may be used, copied, reproduced,
## modified, published, uploaded, posted, transmitted, distributed or disclosed
## in any way without Intel's prior express written permission.
## No license  under any  patent, copyright, trade secret or other intellectual
## property right is granted to or conferred upon you by disclosure or delivery
## of the Materials,  either expressly, by implication, inducement, estoppel or
## otherwise.  Any  license  under  such  intellectual property  rights must be
## express and approved by Intel in writing.
##
##*****************************************************************************
## Content:
##      Build and run examples using FFTW3 Fortran wrappers to Intel MKL.
##*****************************************************************************

## Usage examples:
##
## make lib64 compiler=gnu
##        Build and run all examples using MKL for Intel(R) Itanium(R)-based
##        applications and GNU gfortran compiler.
##
## make libem64t function=complex_1d_double_ex1 threading=sequential
##        Build and run one example using MKL for Intel(R) EM64T
##        processor family applications with sequential layer.

help:
	@echo "Usage: make {lib32|lib64|libem64t} [option...]"
	@echo "Options:"
	@echo ""
	@echo " function=<name>"
	@echo "        Run only the specified example. Please see file"
	@echo "        fftw3xf.lst for the list of functions."
	@echo ""
	@echo " compiler=gnu|pgi|intel"
	@echo "        Build examples using GNU gfortran, PGI pgf95, or"
	@echo "        Intel(R) Fortran compiler ifort. Default value: intel."
	@echo "        Note: GNU g77 compiler is not supported in these examples."
	@echo ""
	@echo " interface=ilp64|lp64"
	@echo "        For libem64t and lib64, use ILP64 MKL interface layer"
	@echo "        (i.e. default INTEGER is INTEGER*8)."
	@echo "        Default value: lp64."
	@echo ""
	@echo " threading=sequential|parallel"
	@echo "        Build examples using parallel or sequential MKL."
	@echo "        Default value: parallel."
	@echo ""
	@echo " parallel=gnu|pgi|intel"
	@echo "        For threading=parallel, select MKL parallel layer."
	@echo "        Default value depends on <compiler>."
	@echo ""
	@echo " omp=guide|gomp|pgmp|iomp5"
	@echo "        For threading=parallel, select system OpenMP library:"
	@echo "          iomp5|guide for compiler=intel,"
	@echo "          iomp5|gomp  for compiler=gnu,"
	@echo "          pgmp  for compiler=pgi."
	@echo "        Default value depends on <parallel>."
	@echo ""
	@echo " wraplib=yes|no"
	@echo "        Build and use standalone FFTW3 wrappers library."
	@echo "        The library will be built with respective C compiler"
	@echo "        and put into <resdir>."
	@echo "        Default value: no, that is use integrated wrappers."
	@echo ""
	@echo " resdir=<path>"
	@echo "        Use <path> for building the examples."
	@echo "        Default value: ./_results."
	@echo ""
	@echo " MKLROOT=<path>"
	@echo "        Locate MKL libraries relative to <path>."
	@echo "        Default value: ../.., unless defined in environment"

##-----------------------------------------------------------------------------
## Default values

include fftw3xf.lst
function = $(DFT)
compiler = intel
interface = lp64
threading = parallel
parallel = $(_parallel_$(compiler))
omp = $(_omp_$(parallel))
wraplib = no
resdir = ./_results
MKLROOT ?= ../..

_parallel_intel = intel
_parallel_gnu = gnu
_parallel_pgi = pgi

_omp_intel = iomp5
_omp_gnu = iomp5
_omp_pgi = pgmp

##-----------------------------------------------------------------------------
## Main targets

lib32:
	$(MAKE) lib _IA=32

libem64t:
	$(MAKE) lib _IA=em64t

lib64:
	$(MAKE) lib _IA=64

ifdef _IA
##-----------------------------------------------------------------------------
## Supporting _macros

_FC_intel = ifort
_FC_gnu = gfortran
_FC_pgi = pgf95
FC = $(firstword $(_FC_$(compiler)) ifort)

ifneq ($(_IA),32)
_ilp64 = _$(interface)
endif

_fflags  = $(_fflags_$(compiler))
_fflags += $(_fflags_$(compiler)_$(_IA))
_fflags += $(_fflags_$(compiler)_$(interface))
_fflags += $(_fflags_$(compiler)_$(parallel))
_fflags += -I$(MKLROOT)/include/fftw
_fflags += $(FFLAGS)

_fflags_intel = -vec-report0
_fflags_intel_ilp64 = -i8
_fflags_gnu_ilp64 = -fdefault-integer-8
_fflags_pgi = -Mnokeepobj
_fflags_pgi_ilp64 = -i8
_fflags_pgi_pgi = -mp

## Option -O0 is required by Intel(R) compiler to produce
## Pentium(R) III compatible executables.
_fflags_intel_32 = -O0

# Maybe define wraplib
ifeq ($(wraplib),yes)
_maybe_wraplib = $(_resdir)/libfftw3xf.a
_maybe_wraplib_libs = -L$(_resdir) -lfftw3xf
_maybe_wraplib_makeflags_ilp64 = i8=yes
endif

# Pick MKL interface layer
_lib_iface = $(_lib_iface_$(compiler))$(_ilp64)
_lib_iface_intel = -lmkl_intel
_lib_iface_pgi = -lmkl_intel
_lib_iface_gnu = -lmkl_gf

# Pick MKL threading layer
ifeq ($(threading),parallel)
_lib_thread_pgi = -lmkl_pgi_thread
_lib_thread_intel = -lmkl_intel_thread
_lib_thread_gnu = -lmkl_gnu_thread
_lib_thread = $(_lib_thread_$(parallel))
else
_lib_thread = -lmkl_sequential
endif

# Pick MKL core layer
_lib_core = -lmkl_core

# Maybe pick OpenMP library
ifeq ($(threading),parallel)
_maybe_omp = -l$(omp) -lpthread
else
_maybe_omp =
endif

# Finally compose the _libs
_libs  = $(_maybe_wraplib_libs)
_libs += -L$(MKLROOT)/lib/$(_IA)
_libs += -Wl,--start-group
_libs += $(_lib_iface) $(_lib_thread) $(_lib_core)
_libs += -Wl,--end-group
_libs += $(_maybe_omp)
_libs += -lm

.SUFFIXES: .res .out

_srcdir = source
vpath %.f $(_srcdir)

_resdir = $(resdir)/$(compiler)$(_ilp64)_$(threading)_$(_IA)

_cmnobjs = mkl_fftw_examples_support.o

##-----------------------------------------------------------------------------
## Rules

lib: clean mkresdir $(_maybe_wraplib) $(function:%=$(_resdir)/%.res)

.PRECIOUS: $(_resdir)/%.out
$(_resdir)/%.res: $(_resdir)/%.out
	LD_LIBRARY_PATH="$(MKLROOT)/lib/$(_IA):$$LD_LIBRARY_PATH" $< >$@

$(_resdir)/%.out: %.f $(_cmnobjs:%=$(_resdir)/%)
	$(FC) $(_fflags) $^ $(_libs) -o $@

$(_resdir)/%.o: %.f
	$(FC) $(_fflags) -c $< -o $@

clean:
	-rm -rf $(_resdir)

mkresdir:
	test -d $(_resdir) || mkdir -p $(_resdir)

# We shall use absolute path for install_to
_install_to=$(shell cd '$(@D)' && pwd)
$(_maybe_wraplib):
	$(MAKE) -C $(MKLROOT)/interfaces/fftw3xf lib$(_IA) \
		install_to="$(_install_to)" install_as=$(@F) \
		$(_maybe_wraplib_makeflags$(_ilp64))

##-----------------------------------------------------------------------------
endif
