# cuSTC -- CUDA-accelerated Syndrome-Trellis Codes
#
# Set ARCH to your GPU's compute capability:
#   sm_75 Turing (RTX 20xx) | sm_80/sm_86 Ampere | sm_89 Ada | sm_90 Hopper
NVCC      = nvcc
CXX       = g++
ARCH      = sm_75
NVCCFLAGS = -O3 -arch=$(ARCH) -Xcompiler -O3
CXXFLAGS  = -O3 -msse2

SRC       = ml_stc_src
BENCH     = benchmark
GPU_CORE  = $(SRC)/stc_cuda.cu $(SRC)/common.cpp $(SRC)/stc_extract_c.cpp
CPU_CORE  = $(SRC)/stc_embed_c.cpp $(SRC)/stc_extract_c.cpp $(SRC)/common.cpp $(SRC)/stc_ml_c.cpp

EXAMPLES   = example1_gpu example2_gpu example1_ml_stc example2_ml_stc
TESTS      = $(BENCH)/main_verify $(BENCH)/main_verify_v $(BENCH)/main_verify_ml \
             $(BENCH)/main_verify_plan
BENCHMARKS = $(BENCH)/main_compare $(BENCH)/main_benchmark_cuda $(TESTS)

all: $(EXAMPLES)
benchmarks: $(BENCHMARKS)

# Verification suite (needs a GPU): every harness exits 0 iff all cases pass.
# main_verify       h x alpha sweep, both strategies, odd n, wet costs (binary core)
# main_verify_v     mixed-shape batches, waves, infeasible trellises (roadmap 1.2)
# main_verify_ml    batched +-1 multi-layer embedding vs stc_pm1_pls_embed (1.3)
# main_verify_plan  plan API vs the one-shot path (3.1)
test: $(TESTS)
	@set -e; for t in $(TESTS); do echo "--- $$t"; ./$$t; done; \
	echo "=== make test: ALL SUITES PASS ==="

# --- GPU examples -----------------------------------------------------------
example1_gpu: $(SRC)/example1_gpu_stc.cpp $(GPU_CORE)
	$(NVCC) $(NVCCFLAGS) -o $@ $^

example2_gpu: $(SRC)/example2_gpu_stc.cpp $(GPU_CORE)
	$(NVCC) $(NVCCFLAGS) -o $@ $^

# --- CPU reference examples (multi-layer +-1 / +-2 constructions) -----------
example1_ml_stc: $(SRC)/example1_ml_stc.cpp $(CPU_CORE)
	$(CXX) $(CXXFLAGS) -o $@ $^

example2_ml_stc: $(SRC)/example2_ml_stc.cpp $(CPU_CORE)
	$(CXX) $(CXXFLAGS) -o $@ $^

# --- benchmarks --------------------------------------------------------------
$(BENCH)/main_compare: $(BENCH)/main_compare.cpp $(SRC)/stc_cuda.cu $(SRC)/common.cpp $(SRC)/stc_embed_c.cpp $(SRC)/stc_extract_c.cpp
	$(NVCC) $(NVCCFLAGS) -o $@ $^

$(BENCH)/main_benchmark_cuda: $(BENCH)/main_benchmark.cpp $(GPU_CORE)
	$(NVCC) $(NVCCFLAGS) -o $@ $^

# committed verification suite (h x alpha sweep, both strategies, wet costs)
$(BENCH)/main_verify: $(BENCH)/main_verify.cpp $(SRC)/stc_cuda.cu $(SRC)/common.cpp $(SRC)/stc_embed_c.cpp $(SRC)/stc_extract_c.cpp
	$(NVCC) $(NVCCFLAGS) -o $@ $^

# mixed-shape correctness harness (stc_embed_cuda_batch_v vs CPU reference)
$(BENCH)/main_verify_v: $(BENCH)/main_verify_v.cpp $(SRC)/stc_cuda.cu $(SRC)/common.cpp $(SRC)/stc_embed_c.cpp $(SRC)/stc_extract_c.cpp
	$(NVCC) $(NVCCFLAGS) -o $@ $^

# batched GPU +-1 embedding harness (stc_pm1_pls_embed_cuda_batch vs CPU reference)
$(BENCH)/main_verify_ml: $(BENCH)/main_verify_ml.cpp $(SRC)/stc_ml_cuda.cpp $(SRC)/stc_cuda.cu $(CPU_CORE)
	$(NVCC) $(NVCCFLAGS) -Xcompiler -fopenmp -o $@ $^ -lgomp

# plan API harness (stc_plan_create/embed/destroy vs the one-shot path)
$(BENCH)/main_verify_plan: $(BENCH)/main_verify_plan.cpp $(GPU_CORE)
	$(NVCC) $(NVCCFLAGS) -o $@ $^

clean:
	rm -f $(EXAMPLES) $(BENCHMARKS)

.PHONY: all benchmarks test clean
