# MakefileGPU (Linux/gcc + nvcc) version
# Usage: make all
# Individual GPU targets: make ct_rec_g hp_tg_g tf_tg_g etc.
#
# CUDA 13.x: Maxwell/Pascal/Volta removed.  Minimum arch is sm_75 (Turing).
#   Override CUDA_ARCH on command line if targeting a specific GPU:
#     make all CUDA_ARCH="-arch=sm_89"     (Ada Lovelace)
#     make all CUDA_ARCH="-arch=sm_100"    (Blackwell)

CC      = gcc
CFLAGS  = -O2 -D_USE_MATH_DEFINES
OMPF    = -fopenmp
LIBS    = -lm
TIFFLIB = -ltiff
CBP     = cbp_thread_int.c
SIF_F   = sif_f_fast.c

CUDA_HOME ?= /usr/local/cuda
CUDAINCL  = $(CUDA_HOME)/include
CUDALIB   = $(CUDA_HOME)/lib64
CUDART    = -L$(CUDALIB) -lcudart
CUFFT     = -L$(CUDALIB) -lcufft

# Default: Turing (sm_75).  CUDA 13.x does not support older architectures.
CUDA_ARCH ?= -arch=sm_75

NVCCFLAGS = -O3 -I$(CUDAINCL) $(CUDA_ARCH) -use_fast_math -Xcompiler "-Wno-unused-result"

EXE_DIR = ../bin

.PHONY: all clean ct_rec_g tf_rec_g hp_tg_g tf_tg_g \
        ofct_srec_g otf_rec_g oftf_srec_g p_rec_g filters_g

all: ct_rec_g tf_rec_g hp_tg_g tf_tg_g \
     ofct_srec_g otf_rec_g oftf_srec_g p_rec_g filters_g

# ---------------------------------------------------------------
# Normal CT reconstruction (GPU)
# ---------------------------------------------------------------
ct_rec_g: ct_rec_g_r ct_rec_g_s ct_rec_g_c

ct_rec_g_r:
	nvcc $(NVCCFLAGS) cbp.cu -DFloat=float -c -DFilter=Ramachandran -o cbp.o
	$(CC) $(CFLAGS) $(OMPF) -o $(EXE_DIR)/ct_rec_g_r ct_rec.c error.c sort_filter_omp.c $(SIF_F) $(CUFFT) $(CUDART) cbp.o $(LIBS)
ct_rec_g_s:
	nvcc $(NVCCFLAGS) cbp.cu -DFloat=float -c -DFilter=Shepp -o cbp.o
	$(CC) $(CFLAGS) $(OMPF) -o $(EXE_DIR)/ct_rec_g_s ct_rec.c error.c sort_filter_omp.c $(SIF_F) $(CUFFT) $(CUDART) cbp.o $(LIBS)
ct_rec_g_c:
	nvcc $(NVCCFLAGS) cbp.cu -DFloat=float -c -DFilter=Chesler -o cbp.o
	$(CC) $(CFLAGS) $(OMPF) -o $(EXE_DIR)/ct_rec_g_c ct_rec.c error.c sort_filter_omp.c $(SIF_F) $(CUFFT) $(CUDART) cbp.o $(LIBS)

tf_rec_g: tf_rec_g_r tf_rec_g_s tf_rec_g_c

tf_rec_g_r:
	nvcc $(NVCCFLAGS) cbp.cu -DFloat=float -c -DFilter=Ramachandran -o cbp.o
	$(CC) $(CFLAGS) $(OMPF) -o $(EXE_DIR)/tf_rec_g_r tf_rec.c error.c sort_filter_omp.c $(TIFFLIB) $(CUFFT) $(CUDART) cbp.o $(LIBS)
tf_rec_g_s:
	nvcc $(NVCCFLAGS) cbp.cu -DFloat=float -c -DFilter=Shepp -o cbp.o
	$(CC) $(CFLAGS) $(OMPF) -o $(EXE_DIR)/tf_rec_g_s tf_rec.c error.c sort_filter_omp.c $(TIFFLIB) $(CUFFT) $(CUDART) cbp.o $(LIBS)
tf_rec_g_c:
	nvcc $(NVCCFLAGS) cbp.cu -DFloat=float -c -DFilter=Chesler -o cbp.o
	$(CC) $(CFLAGS) $(OMPF) -o $(EXE_DIR)/tf_rec_g_c tf_rec.c error.c sort_filter_omp.c $(TIFFLIB) $(CUFFT) $(CUDART) cbp.o $(LIBS)

hp_tg_g: hp_tg_g_r hp_tg_g_s hp_tg_g_c

hp_tg_g_r:
	nvcc $(NVCCFLAGS) cbp.cu -DFloat=float -c -DFilter=Ramachandran -o cbp.o
	$(CC) $(CFLAGS) $(OMPF) -DONLY_CT_VIEWS -DFOM=float -DFloat=float -o $(EXE_DIR)/hp_tg_g_r hp_tg_ku.c error.c rhp.c sort_filter_omp.c $(TIFFLIB) $(CUFFT) $(CUDART) cbp.o $(LIBS)
hp_tg_g_s:
	nvcc $(NVCCFLAGS) cbp.cu -DFloat=float -c -DFilter=Shepp -o cbp.o
	$(CC) $(CFLAGS) $(OMPF) -DONLY_CT_VIEWS -DFOM=float -DFloat=float -o $(EXE_DIR)/hp_tg_g_s hp_tg_ku.c error.c rhp.c sort_filter_omp.c $(TIFFLIB) $(CUFFT) $(CUDART) cbp.o $(LIBS)
hp_tg_g_c:
	nvcc $(NVCCFLAGS) cbp.cu -DFloat=float -c -DFilter=Chesler -o cbp.o
	$(CC) $(CFLAGS) $(OMPF) -DONLY_CT_VIEWS -DFOM=float -DFloat=float -o $(EXE_DIR)/hp_tg_g_c hp_tg_ku.c error.c rhp.c sort_filter_omp.c $(TIFFLIB) $(CUFFT) $(CUDART) cbp.o $(LIBS)

tf_tg_g: tf_tg_g_r tf_tg_g_s tf_tg_g_c

tf_tg_g_r:
	nvcc $(NVCCFLAGS) cbp.cu -DFloat=float -c -DFilter=Ramachandran -o cbp.o
	$(CC) $(CFLAGS) $(OMPF) -DONLY_CT_VIEWS -DFOM=float -DFloat=float -o $(EXE_DIR)/tf_tg_g_r hp_tg_ku.c error.c rtf.c sort_filter_omp.c $(TIFFLIB) $(CUFFT) $(CUDART) cbp.o $(LIBS)
tf_tg_g_s:
	nvcc $(NVCCFLAGS) cbp.cu -DFloat=float -c -DFilter=Shepp -o cbp.o
	$(CC) $(CFLAGS) $(OMPF) -DONLY_CT_VIEWS -DFOM=float -DFloat=float -o $(EXE_DIR)/tf_tg_g_s hp_tg_ku.c error.c rtf.c sort_filter_omp.c $(TIFFLIB) $(CUFFT) $(CUDART) cbp.o $(LIBS)
tf_tg_g_c:
	nvcc $(NVCCFLAGS) cbp.cu -DFloat=float -c -DFilter=Chesler -o cbp.o
	$(CC) $(CFLAGS) $(OMPF) -DONLY_CT_VIEWS -DFOM=float -DFloat=float -o $(EXE_DIR)/tf_tg_g_c hp_tg_ku.c error.c rtf.c sort_filter_omp.c $(TIFFLIB) $(CUFFT) $(CUDART) cbp.o $(LIBS)

# ---------------------------------------------------------------
# Offset CT reconstruction (GPU)
# ---------------------------------------------------------------
ofct_srec_g: ofct_srec_g_r ofct_srec_g_s ofct_srec_g_c

ofct_srec_g_r:
	nvcc $(NVCCFLAGS) cbp.cu -DFloat=float -c -DFilter=Ramachandran -o cbp.o
	$(CC) $(CFLAGS) $(OMPF) -o $(EXE_DIR)/ofct_srec_g_r ofct_srec.c error.c rhp.c rl.c sort_filter_omp.c $(TIFFLIB) $(CUFFT) $(CUDART) cbp.o $(LIBS)
ofct_srec_g_s:
	nvcc $(NVCCFLAGS) cbp.cu -DFloat=float -c -DFilter=Shepp -o cbp.o
	$(CC) $(CFLAGS) $(OMPF) -o $(EXE_DIR)/ofct_srec_g_s ofct_srec.c error.c rhp.c rl.c sort_filter_omp.c $(TIFFLIB) $(CUFFT) $(CUDART) cbp.o $(LIBS)
ofct_srec_g_c:
	nvcc $(NVCCFLAGS) cbp.cu -DFloat=float -c -DFilter=Chesler -o cbp.o
	$(CC) $(CFLAGS) $(OMPF) -o $(EXE_DIR)/ofct_srec_g_c ofct_srec.c error.c rhp.c rl.c sort_filter_omp.c $(TIFFLIB) $(CUFFT) $(CUDART) cbp.o $(LIBS)

otf_rec_g: otf_rec_g_r otf_rec_g_s otf_rec_g_c

otf_rec_g_r:
	nvcc $(NVCCFLAGS) cbp.cu -DFloat=float -c -DFilter=Ramachandran -o cbp.o
	$(CC) $(CFLAGS) $(OMPF) -o $(EXE_DIR)/otf_rec_g_r otf_rec.c error.c sort_filter_omp.c $(TIFFLIB) $(CUFFT) $(CUDART) cbp.o $(LIBS)
otf_rec_g_s:
	nvcc $(NVCCFLAGS) cbp.cu -DFloat=float -c -DFilter=Shepp -o cbp.o
	$(CC) $(CFLAGS) $(OMPF) -o $(EXE_DIR)/otf_rec_g_s otf_rec.c error.c sort_filter_omp.c $(TIFFLIB) $(CUFFT) $(CUDART) cbp.o $(LIBS)
otf_rec_g_c:
	nvcc $(NVCCFLAGS) cbp.cu -DFloat=float -c -DFilter=Chesler -o cbp.o
	$(CC) $(CFLAGS) $(OMPF) -o $(EXE_DIR)/otf_rec_g_c otf_rec.c error.c sort_filter_omp.c $(TIFFLIB) $(CUFFT) $(CUDART) cbp.o $(LIBS)

oftf_srec_g: oftf_srec_g_r oftf_srec_g_s oftf_srec_g_c

oftf_srec_g_r:
	nvcc $(NVCCFLAGS) cbp.cu -DFloat=float -c -DFilter=Ramachandran -o cbp.o
	$(CC) $(CFLAGS) $(OMPF) -o $(EXE_DIR)/oftf_srec_g_r ofct_srec.c error.c rtf.c rl.c sort_filter_omp.c $(TIFFLIB) $(CUFFT) $(CUDART) cbp.o $(LIBS)
oftf_srec_g_s:
	nvcc $(NVCCFLAGS) cbp.cu -DFloat=float -c -DFilter=Shepp -o cbp.o
	$(CC) $(CFLAGS) $(OMPF) -o $(EXE_DIR)/oftf_srec_g_s ofct_srec.c error.c rtf.c rl.c sort_filter_omp.c $(TIFFLIB) $(CUFFT) $(CUDART) cbp.o $(LIBS)
oftf_srec_g_c:
	nvcc $(NVCCFLAGS) cbp.cu -DFloat=float -c -DFilter=Chesler -o cbp.o
	$(CC) $(CFLAGS) $(OMPF) -o $(EXE_DIR)/oftf_srec_g_c ofct_srec.c error.c rtf.c rl.c sort_filter_omp.c $(TIFFLIB) $(CUFFT) $(CUDART) cbp.o $(LIBS)

# ---------------------------------------------------------------
# p image CT reconstruction (GPU)
# ---------------------------------------------------------------
p_rec_g: p_rec_g_r p_rec_g_s p_rec_g_c

p_rec_g_r:
	nvcc $(NVCCFLAGS) cbp.cu -DFloat=float -c -DFilter=Ramachandran -o cbp.o
	$(CC) $(CFLAGS) $(OMPF) -DFOM=float -DFloat=float -o $(EXE_DIR)/p_rec_g_r p_rec.c error.c sort_filter_omp.c $(TIFFLIB) $(CUFFT) $(CUDART) cbp.o $(LIBS)
p_rec_g_s:
	nvcc $(NVCCFLAGS) cbp.cu -DFloat=float -c -DFilter=Shepp -o cbp.o
	$(CC) $(CFLAGS) $(OMPF) -DFOM=float -DFloat=float -o $(EXE_DIR)/p_rec_g_s p_rec.c error.c sort_filter_omp.c $(TIFFLIB) $(CUFFT) $(CUDART) cbp.o $(LIBS)
p_rec_g_c:
	nvcc $(NVCCFLAGS) cbp.cu -DFloat=float -c -DFilter=Chesler -o cbp.o
	$(CC) $(CFLAGS) $(OMPF) -DFOM=float -DFloat=float -o $(EXE_DIR)/p_rec_g_c p_rec.c error.c sort_filter_omp.c $(TIFFLIB) $(CUFFT) $(CUDART) cbp.o $(LIBS)

# ---------------------------------------------------------------
# Filters made by ClaudeAI (GPU)
# ---------------------------------------------------------------
filters_g: tif_adf_g tif_blf_g tif_bm4d_g tif_gsf_g tif_mdf_g tif_nlm_g tif_tvd_g tif_wvd_g

tif_adf_g:
	nvcc $(NVCCFLAGS) -o $(EXE_DIR)/tif_adf_g tif_adf_g.cu $(TIFFLIB)

tif_blf_g:
	nvcc $(NVCCFLAGS) -o $(EXE_DIR)/tif_blf_g tif_blf_g.cu $(TIFFLIB)

tif_bm4d_g:
	nvcc $(NVCCFLAGS) -o $(EXE_DIR)/tif_bm4d_g tif_bm4d_g.cu $(TIFFLIB)

tif_gsf_g:
	nvcc $(NVCCFLAGS) -o $(EXE_DIR)/tif_gsf_g tif_gsf_g.cu $(TIFFLIB)

tif_mdf_g:
	nvcc $(NVCCFLAGS) -o $(EXE_DIR)/tif_mdf_g tif_mdf_g.cu $(TIFFLIB)

tif_nlm_g:
	nvcc $(NVCCFLAGS) -o $(EXE_DIR)/tif_nlm_g tif_nlm_g.cu $(TIFFLIB)

tif_tvd_g:
	nvcc $(NVCCFLAGS) -o $(EXE_DIR)/tif_tvd_g tif_tvd_g.cu $(TIFFLIB)

tif_wvd_g:
	nvcc $(NVCCFLAGS) -o $(EXE_DIR)/tif_wvd_g tif_wvd_g.cu $(TIFFLIB)

# ---------------------------------------------------------------
# Clean
# ---------------------------------------------------------------
clean:
	rm -f *.o \
	$(EXE_DIR)/ct_rec_g_r $(EXE_DIR)/ct_rec_g_s $(EXE_DIR)/ct_rec_g_c \
	$(EXE_DIR)/tf_rec_g_r $(EXE_DIR)/tf_rec_g_s $(EXE_DIR)/tf_rec_g_c \
	$(EXE_DIR)/hp_tg_g_r  $(EXE_DIR)/hp_tg_g_s  $(EXE_DIR)/hp_tg_g_c \
	$(EXE_DIR)/tf_tg_g_r  $(EXE_DIR)/tf_tg_g_s  $(EXE_DIR)/tf_tg_g_c \
	$(EXE_DIR)/ofct_srec_g_r $(EXE_DIR)/ofct_srec_g_s $(EXE_DIR)/ofct_srec_g_c \
	$(EXE_DIR)/otf_rec_g_r   $(EXE_DIR)/otf_rec_g_s   $(EXE_DIR)/otf_rec_g_c \
	$(EXE_DIR)/oftf_srec_g_r $(EXE_DIR)/oftf_srec_g_s $(EXE_DIR)/oftf_srec_g_c \
	$(EXE_DIR)/p_rec_g_r $(EXE_DIR)/p_rec_g_s $(EXE_DIR)/p_rec_g_c \
	$(EXE_DIR)/tif_adf_g $(EXE_DIR)/tif_blf_g $(EXE_DIR)/tif_bm4d_g \
	$(EXE_DIR)/tif_gsf_g $(EXE_DIR)/tif_mdf_g $(EXE_DIR)/tif_nlm_g \
	$(EXE_DIR)/tif_tvd_g $(EXE_DIR)/tif_wvd_g
	