# C/C++ ベンチマークのビルド
#   make flint        : flint_eig flint_fft            (要 libflint-dev >= 3.0)
#   make mpfrfft      : mpfr_fft_omp                   (要 libmpfr-dev)
#   make eigen        : eigen_mpreal_eig               (要 libeigen3-dev, MPREAL_DIR に mpreal.h)
#   make scalar       : scalar_bench                   (要 mpreal.h; BOOST/QD/F128/FLINT はあれば有効化)
#   make mplapack     : mplapack_eig_{mpfr,gmp,dd,qd,float128}  (要 MPLAPACK=インストール先)
#   make all
#
# 変数の例:  make all MPREAL_DIR=$HOME/src/mpreal MPLAPACK=$HOME/opt/mplapack HAVE_QD=1
CXX      ?= g++
CC       ?= gcc
CXXFLAGS ?= -O2 -std=c++17 -march=native
CFLAGS   ?= -O2 -march=native
MPREAL_DIR ?= ./mpreal
MPLAPACK   ?= /usr/local
EIGEN_INC  ?= /usr/include/eigen3

SCALAR_DEFS := -DHAVE_FLINT -DHAVE_F128
SCALAR_LIBS := -lflint -lmpfr -lgmp -lquadmath
ifdef HAVE_BOOST
  SCALAR_DEFS += -DHAVE_BOOST
endif
ifdef HAVE_QD
  SCALAR_DEFS += -DHAVE_QD
  SCALAR_LIBS += -lqd
endif

all: flint mpfrfft eigen scalar

flint: flint_eig flint_fft
flint_eig: flint_eig.c bench_common.h
	$(CC) $(CFLAGS) -o $@ $< -lflint -lmpfr -lgmp -lm -lpthread
flint_fft: flint_fft.c bench_common.h
	$(CC) $(CFLAGS) -o $@ $< -lflint -lmpfr -lgmp -lm -lpthread

mpfrfft: mpfr_fft_omp
mpfr_fft_omp: mpfr_fft_omp.cpp bench_common.h
	$(CXX) $(CXXFLAGS) -fopenmp -o $@ $< -lmpfr -lgmp

eigen: eigen_mpreal_eig
eigen_mpreal_eig: eigen_mpreal_eig.cpp bench_common.h
	$(CXX) $(CXXFLAGS) -I$(EIGEN_INC) -I$(MPREAL_DIR) -o $@ $< -lmpfr -lgmp

scalar: scalar_bench
scalar_bench: scalar_bench.cpp bench_common.h
	$(CXX) $(CXXFLAGS) -I$(MPREAL_DIR) $(SCALAR_DEFS) -o $@ $< $(SCALAR_LIBS)

# MPLAPACK 3.0: BLAS と LAPACK は 1 つの libmplapack_<type>.so にまとまっている。
#   --enable-optimization でビルドすると OpenMP 版 libmplapack_<type>_opt.so もできる (既定で使用。MPL_OPT= で参照版に切替)
#   binary128 版はライブラリ名が libmplapack_binary128 (ヘッダも mpblas_binary128.h / mplapack_binary128.h)
MPL_OPT ?= _opt
MPL_INC := -I$(MPLAPACK)/include -I$(MPLAPACK)/include/mplapack
MPL_LIB := -L$(MPLAPACK)/lib -Wl,-rpath,$(MPLAPACK)/lib
mplapack: mplapack_eig_mpfr mplapack_eig_gmp mplapack_eig_dd mplapack_eig_qd mplapack_eig_float128
mplapack_gemm: mplapack_gemm.cpp bench_common.h      # Rgemm / Rgehrd 単体のスレッドスケーリング (mpfr)
	$(CXX) $(CXXFLAGS) -fopenmp $(MPL_INC) -o $@ $< $(MPL_LIB) -lmplapack_mpfr$(MPL_OPT) -lmpfr -lmpc -lgmp
mplapack_eig_mpfr: mplapack_eig.cpp bench_common.h
	$(CXX) $(CXXFLAGS) -fopenmp -DBACKEND_MPFR $(MPL_INC) -o $@ $< $(MPL_LIB) -lmplapack_mpfr$(MPL_OPT) -lmpfr -lmpc -lgmp
mplapack_eig_gmp: mplapack_eig.cpp bench_common.h
	$(CXX) $(CXXFLAGS) -fopenmp -DBACKEND_GMP $(MPL_INC) -o $@ $< $(MPL_LIB) -lmplapack_gmp$(MPL_OPT) -lgmpxx -lgmp
mplapack_eig_dd: mplapack_eig.cpp bench_common.h
	$(CXX) $(CXXFLAGS) -fopenmp -DBACKEND_DD $(MPL_INC) -o $@ $< $(MPL_LIB) -lmplapack_dd$(MPL_OPT) -lqd
mplapack_eig_qd: mplapack_eig.cpp bench_common.h
	$(CXX) $(CXXFLAGS) -fopenmp -DBACKEND_QD $(MPL_INC) -o $@ $< $(MPL_LIB) -lmplapack_qd$(MPL_OPT) -lqd
mplapack_eig_float128: mplapack_eig.cpp bench_common.h
	$(CXX) $(CXXFLAGS) -fopenmp -DBACKEND_FLOAT128 $(MPL_INC) -o $@ $< $(MPL_LIB) -lmplapack_binary128$(MPL_OPT) -lquadmath

clean:
	rm -f flint_eig flint_fft mpfr_fft_omp eigen_mpreal_eig scalar_bench mplapack_eig_* mplapack_gemm

.PHONY: all flint mpfrfft eigen scalar mplapack clean
