gpp=/usr/bin/g++
gcc=/usr/bin/gcc
CUDA=/usr/local/cuda/include
CUDALIB=/usr/local/cuda/lib64
QDsrc=../../Ada/Math_Lib/QD/C
MPD=../Norms
CNV=../Convolutions
MAT=../Matrices

# tested on different NVIDIA GPUs

# the architecture flag for Volta V100
# smflag=sm_70
# the architecture flag for Ampere A100
smflag=sm_80
# the architecture flag for RTX 4080
# smflag=sm_89

# code needed from the multiple double library MPD :

random_numbers.o:
	@-echo ">>> compiling double random numbers"
	$(gpp) -O3 -c -I$(MPD) $(MPD)/random_numbers.cpp

random2_vectors.o:
	@-echo ">>> compiling double double random vector generators ..."
	$(gpp) -O3 -c -I$(MPD) $(MPD)/random2_vectors.cpp

random2_matrices.o:
	@-echo ">>> compiling double double random matrix generators ..."
	$(gpp) -O3 -c -I$(MPD) -I$(MAT) $(MAT)/random2_matrices.cpp

random4_vectors.o:
	@-echo ">>> compiling quad double random vector generators ..."
	$(gpp) -O3 -c -I$(MPD) $(MPD)/random4_vectors.cpp

random4_matrices.o:
	@-echo ">>> compiling quad double random matrix generators ..."
	$(gpp) -O3 -c -I$(MPD) -I$(MAT) $(MAT)/random4_matrices.cpp

random8_vectors.o:
	@-echo ">>> compiling octo double random vector generators ..."
	$(gpp) -O3 -c -I$(MPD) $(MPD)/random8_vectors.cpp

random8_matrices.o:
	@-echo ">>> compiling octo double random matrix generators ..."
	$(gpp) -O3 -c -I$(MPD) -I$(MAT) $(MAT)/random8_matrices.cpp

random16_vectors.o:
	@-echo ">>> compiling hexa double random vector generators ..."
	$(gpp) -O3 -c -I$(MPD) $(MPD)/random16_vectors.cpp

random16_matrices.o:
	@-echo ">>> compiling hexa double random matrix generators ..."
	$(gpp) -O3 -c -I$(MPD) -I$(MAT) $(MAT)/random16_matrices.cpp

# simple tensor core matrix multiplication :

smTCGemm:
	nvcc -ccbin=$(gcc) -O3 -o smTCGemm -arch=$(smflag) \
             simpleTensorCoreGemm.cu

# code to prepare for vectored multiple double arithmetic :

pi64bits:
	$(gcc) -o pi64bits bits_of_pi.c

splitting_doubles.o:
	@-echo ">>> compiling splitting doubles ..."
	$(gpp) -O3 -c splitting_doubles.cpp

test_split: splitting_doubles.o
	@-echo ">>> compiling test splitting doubles..."
	$(gpp) -c test_splitting_doubles.cpp -o test_splitting_doubles.o
	@-echo ">>> linking ..."
	$(gpp) -o test_split test_splitting_doubles.o splitting_doubles.o

double_double.o:
	@-echo ">>> compiling double double ..."
	$(gpp) -O3 -c -I$(QDsrc) $(QDsrc)/double_double.c

quad_double.o:
	@-echo ">>> compiling quad double ..."
	$(gpp) -O3 -c -I$(QDsrc) $(QDsrc)/quad_double.c

octo_double.o:
	@-echo ">>> compiling octo double ..."
	$(gpp) -O3 -c -I$(QDsrc) $(QDsrc)/octo_double.c

hexa_double.o:
	@-echo ">>> compiling hexa double ..."
	$(gpp) -O3 -c -I$(QDsrc) $(QDsrc)/hexa_double.c

double_double_functions.o:
	@-echo ">>> compiling double double functions ..."
	$(gpp) -O3 -c -I$(MPD) $(MPD)/double_double_functions.cpp

quad_double_functions.o:
	@-echo ">>> compiling quad double functions ..."
	$(gpp) -O3 -c -I$(MPD) $(MPD)/quad_double_functions.cpp

octo_double_functions.o:
	@-echo ">>> compiling octo double functions ..."
	$(gpp) -O3 -c -I$(MPD) $(MPD)/octo_double_functions.cpp

hexa_double_functions.o:
	@-echo ">>> compiling hexa double functions ..."
	$(gpp) -O3 -c -I$(MPD) $(MPD)/hexa_double_functions.cpp

vectored_double_doubles.o:
	@-echo ">>> compiling vectored double doubles ..."
	$(gpp) -O3 -c -I$(QDsrc) -I$(MPD) vectored_double_doubles.cpp

vectored_quad_doubles.o:
	@-echo ">>> compiling vectored quad doubles ..."
	$(gpp) -O3 -c -I$(QDsrc) -I$(MPD) vectored_quad_doubles.cpp

vectored_octo_doubles.o:
	@-echo ">>> compiling vectored octo doubles ..."
	$(gpp) -O3 -c -I$(QDsrc) -I$(MPD) vectored_octo_doubles.cpp

vectored_hexa_doubles.o:
	@-echo ">>> compiling vectored hexa doubles ..."
	$(gpp) -O3 -c -I$(QDsrc) -I$(MPD) vectored_hexa_doubles.cpp

double_matrix_multiplications.o:
	@-echo ">>> compiling double matrix multiplications ..."
	$(gpp) -O3 -c double_matrix_multiplications.cpp

random_series.o:
	@-echo ">>> compiling double random series generators ..."
	$(gpp) -O3 -c -I$(MPD) -I$(CNV) $(CNV)/random_series.cpp

random_matrices.o:
	@-echo ">>> compiling double random matrix generators ..."
	$(gpp) -O3 -c -I$(MPD) -I$(CNV) -I$(MAT) $(MAT)/random_matrices.cpp

test_mmm: random_numbers.o random_series.o random_matrices.o \
          double_matrix_multiplications.o
	@-echo ">>> compiling test_mmm ..."
	$(gpp) -c -I$(MAT) test_mmm.cpp -o test_mmm.o
	@-echo ">>> linking ..."
	$(gpp) -o test_mmm test_mmm.o \
               random_numbers.o random_series.o random_matrices.o \
               double_matrix_multiplications.o

ddmm_host.o:
	@-echo ">>> compiling ddmm_host ..."
	$(gpp) -O3 -c -I$(MPD) -I$(CNV) -I$(MAT) ddmm_host.cpp

ddmm_kernels.o:
	@-echo ">>> compiling ddmm_kernels ..."
	nvcc -ccbin=$(gcc) -arch=$(smflag) -I$(MPD) -O3 -c ddmm_kernels.cu

test_ddmm: double_double.o double_double_functions.o \
           random_numbers.o random2_vectors.o random2_matrices.o \
           ddmm_host.o ddmm_kernels.o
	@-echo ">>> compiling test_ddmm ..."
	$(gpp) -c -I$(CUDA) test_ddmm.cpp -o test_ddmm.o
	@-echo ">>> linking ..."
	$(gpp) -o test_ddmm test_ddmm.o ddmm_host.o ddmm_kernels.o \
                  double_double.o double_double_functions.o \
                  random_numbers.o random2_vectors.o random2_matrices.o \
               -lcudart -L$(CUDALIB)

test_vdd: double_double.o double_double_functions.o \
          random_numbers.o random2_vectors.o random2_matrices.o \
          splitting_doubles.o vectored_double_doubles.o \
          double_matrix_multiplications.o ddmm_host.o
	@-echo ">>> compiling test_vdd ..."
	$(gpp) -c -I$(QDsrc) -I$(MPD) -I$(MAT) test_vdd.cpp -o test_vdd.o
	@-echo ">>> linking ..."
	$(gpp) -o test_vdd test_vdd.o \
               double_double.o double_double_functions.o \
               random_numbers.o random2_vectors.o random2_matrices.o \
               splitting_doubles.o vectored_double_doubles.o \
               double_matrix_multiplications.o ddmm_host.o

test_vqd: double_double.o quad_double.o \
          double_double_functions.o quad_double_functions.o \
          random_numbers.o random4_vectors.o random4_matrices.o \
          splitting_doubles.o vectored_quad_doubles.o \
          double_matrix_multiplications.o
	@-echo ">>> compiling test_vqd ..."
	$(gpp) -c -I$(QDsrc) -I$(MPD) -I$(MAT) test_vqd.cpp -o test_vqd.o
	@-echo ">>> linking ..."
	$(gpp) -o test_vqd test_vqd.o double_double.o quad_double.o \
               double_double_functions.o quad_double_functions.o \
               random_numbers.o random4_vectors.o random4_matrices.o \
               splitting_doubles.o vectored_quad_doubles.o \
               double_matrix_multiplications.o

test_vod: double_double.o quad_double.o octo_double.o \
          double_double_functions.o quad_double_functions.o \
          octo_double_functions.o double_matrix_multiplications.o \
          random_numbers.o random8_vectors.o random8_matrices.o \
          splitting_doubles.o vectored_octo_doubles.o
	@-echo ">>> compiling test_vod ..."
	$(gpp) -c -I$(QDsrc) -I$(MPD) -I$(MAT) test_vod.cpp -o test_vod.o
	@-echo ">>> linking ..."
	$(gpp) -o test_vod test_vod.o \
               double_double.o quad_double.o octo_double.o \
               double_double_functions.o quad_double_functions.o \
               octo_double_functions.o double_matrix_multiplications.o \
               random_numbers.o random8_vectors.o random8_matrices.o \
               splitting_doubles.o vectored_octo_doubles.o

test_vhd: double_double.o quad_double.o octo_double.o hexa_double.o \
          double_double_functions.o quad_double_functions.o \
          octo_double_functions.o hexa_double_functions.o \
          random_numbers.o random16_vectors.o random16_matrices.o \
          splitting_doubles.o vectored_hexa_doubles.o 
	@-echo ">>> compiling test_vhd ..."
	$(gpp) -c -I$(QDsrc) -I$(MPD) -I$(MAT) test_vhd.cpp -o test_vhd.o
	@-echo ">>> linking ..."
	$(gpp) -o test_vhd test_vhd.o \
               double_double.o quad_double.o octo_double.o hexa_double.o \
               double_double_functions.o quad_double_functions.o \
               octo_double_functions.o hexa_double_functions.o \
               random_numbers.o random16_vectors.o random16_matrices.o \
               splitting_doubles.o vectored_hexa_doubles.o

# applying tensor cores ...

smDMMA_host.o:
	@-echo ">>> compiling smDMMA_host ..."
	$(gpp) -I$(MAT) -O3 -c smDMMA_host.cpp -o smDMMA_host.o

smDMMA_kernels.o:
	@-echo ">>> compiling smDMMA_kernels ..."
	nvcc -ccbin=$(gcc) -arch=$(smflag) -c smDMMA_kernels.cu

test_dd_setup.o:
	@-echo ">>> compiling test_dd_setup ..."
	$(gpp) -O3 -c test_dd_setup.cpp -o test_dd_setup.o

test_dd_setup: smDMMA_host.o test_dd_setup.o \
        double_matrix_multiplications.o \
        random_numbers.o random2_vectors.o random2_matrices.o \
        double_double.o double_double_functions.o \
        splitting_doubles.o vectored_double_doubles.o 
	@-echo ">>> linking ..."
	$(gpp) -o test_dds test_dd_setup.o smDMMA_host.o \
                  double_matrix_multiplications.o \
                  random_numbers.o random2_vectors.o random2_matrices.o \
                  double_double.o double_double_functions.o \
                  splitting_doubles.o vectored_double_doubles.o

test_smDMMA.o:
	@-echo ">>> compiling test_smDMMA ..."
	$(gpp) -I$(CUDA) -O3 -c test_smDMMA.cpp

test_smDMMA: smDMMA_host.o smDMMA_kernels.o test_smDMMA.o \
        double_matrix_multiplications.o \
        random_numbers.o random2_vectors.o random2_matrices.o \
        double_double.o double_double_functions.o \
        splitting_doubles.o vectored_double_doubles.o 
	@-echo ">>> linking ..."
	$(gpp) -o test_smDMMA smDMMA_host.o smDMMA_kernels.o test_smDMMA.o \
                  double_matrix_multiplications.o \
                  random_numbers.o random2_vectors.o random2_matrices.o \
                  double_double.o double_double_functions.o \
                  splitting_doubles.o vectored_double_doubles.o \
               -lcudart -L$(CUDALIB)

clean:
	/bin/rm -f -r smTCGemm pi64bits
	/bin/rm -f -r smDMMA_host.o smDMMA_kernels.o
	/bin/rm -f -r test_smDMMA.o test_smDMMA
	/bin/rm -f -r test_split test_splitting_doubles.o splitting_doubles.o
	/bin/rm -f -r random_numbers.o random2_vectors.o random2_matrices.o
	/bin/rm -f -r double_double.o double_double_functions.o
	/bin/rm -f -r vectored_double_doubles.o 
	/bin/rm -f -r double_matrix_multiplications.o
	/bin/rm -f -r test_mmm test_mmm.o random_series.o random_matrices.o
	/bin/rm -f -r test_ddmm test_ddmm.o ddmm_host.o ddmm_kernels.o
	/bin/rm -f -r test_vdd test_vdd.o
	/bin/rm -f -r quad_double.o quad_double_functions.o
	/bin/rm -f -r random4_vectors.o random4_matrices.o
	/bin/rm -f -r vectored_quad_doubles.o
	/bin/rm -f -r test_vqd test_vqd.o
	/bin/rm -f -r octo_double.o octo_double_functions.o
	/bin/rm -f -r random8_vectors.o random8_matrices.o
	/bin/rm -f -r vectored_octo_doubles.o
	/bin/rm -f -r test_vod test_vod.o
	/bin/rm -f -r hexa_double.o hexa_double_functions.o
	/bin/rm -f -r random16_vectors.o random16_matrices.o
	/bin/rm -f -r vectored_hexa_doubles.o
	/bin/rm -f -r test_vhd test_vhd.o
	/bin/rm -f -r test_dds test_dd_setup.o
