# Predictive Algorithms — finite-domain CSP and exact-cover (DLX) library
#
# A small C99 codebase, ~1800 lines across the core library, that
# implements:
#
#   - trail.{c,h}    a delta-log of word-sized mutations with checkpoint
#                    and O(k) restoration.
#   - csp.{c,h}      a finite-domain constraint solver built on the trail.
#                    Domains are Briggs sparse sets; constraints are
#                    propagated via a watch-list-driven AC-3 fixpoint.
#   - dlx.{c,h}      a Dancing-Cells exact-cover solver supporting
#                    primary/secondary items and XCC colours.
#
# Each comes with examples and tests. Build everything with:
#     make
# Run all tests with:
#     make test
#
# Optional: build the benchmark harness too:
#     make bench

CC      ?= cc
CFLAGS  ?= -std=c99 -Wall -Wextra -Wpedantic -O2 -g
LDFLAGS ?=

# ---- Targets summary -----------------------------------------------------

CSP_DEMOS  = csp_tutorial csp_examples csp_puzzles csp_regalloc csp_sched \
             csp_cryptarithmetic csp_magic_square csp_binpacking
DLX_DEMOS  = dlx_tutorial dlx_pentomino dlx_sudoku dlx_queens dlx_crossword
TESTS      = trail_test csp_test dlx_test
BENCHMARKS = bench_naive bench_queued

OBJS = trail.o csp.o

all: $(CSP_DEMOS) $(DLX_DEMOS) $(TESTS)

# ---- Core library --------------------------------------------------------

trail.o: src/trail.c src/trail.h
	$(CC) $(CFLAGS) -c -o $@ $< -Isrc

csp.o: src/csp.c src/csp.h src/trail.h
	$(CC) $(CFLAGS) -c -o $@ $< -Isrc

dlx.o: src/dlx.c src/dlx.h src/trail.h
	$(CC) $(CFLAGS) -c -o $@ $< -Isrc

# ---- CSP demos -----------------------------------------------------------

csp_tutorial: src/csp_tutorial.c $(OBJS) src/csp.h
	$(CC) $(CFLAGS) -Isrc -o $@ src/csp_tutorial.c $(OBJS) $(LDFLAGS)

csp_examples: src/csp_examples.c $(OBJS) src/csp.h
	$(CC) $(CFLAGS) -Isrc -o $@ src/csp_examples.c $(OBJS) $(LDFLAGS)

csp_puzzles: src/csp_puzzles.c $(OBJS) src/csp.h
	$(CC) $(CFLAGS) -Isrc -o $@ src/csp_puzzles.c $(OBJS) $(LDFLAGS)

csp_regalloc: src/csp_regalloc.c $(OBJS) src/csp.h
	$(CC) $(CFLAGS) -Isrc -o $@ src/csp_regalloc.c $(OBJS) $(LDFLAGS)

csp_sched: src/csp_sched.c $(OBJS) src/csp.h
	$(CC) $(CFLAGS) -Isrc -o $@ src/csp_sched.c $(OBJS) $(LDFLAGS)

csp_cryptarithmetic: src/csp_cryptarithmetic.c $(OBJS) src/csp.h
	$(CC) $(CFLAGS) -Isrc -o $@ src/csp_cryptarithmetic.c $(OBJS) $(LDFLAGS)

csp_magic_square: src/csp_magic_square.c $(OBJS) src/csp.h
	$(CC) $(CFLAGS) -Isrc -o $@ src/csp_magic_square.c $(OBJS) $(LDFLAGS)

csp_binpacking: src/csp_binpacking.c $(OBJS) src/csp.h
	$(CC) $(CFLAGS) -Isrc -o $@ src/csp_binpacking.c $(OBJS) $(LDFLAGS)

# ---- DLX demos -----------------------------------------------------------

dlx_tutorial: src/dlx_tutorial.c csp.o dlx.o trail.o src/csp.h src/dlx.h
	$(CC) $(CFLAGS) -Isrc -o $@ src/dlx_tutorial.c csp.o dlx.o trail.o $(LDFLAGS)

dlx_pentomino: src/dlx_pentomino.c dlx.o trail.o src/dlx.h
	$(CC) $(CFLAGS) -Isrc -o $@ src/dlx_pentomino.c dlx.o trail.o $(LDFLAGS)

dlx_sudoku: src/dlx_sudoku.c dlx.o trail.o src/dlx.h
	$(CC) $(CFLAGS) -Isrc -o $@ src/dlx_sudoku.c dlx.o trail.o $(LDFLAGS)

dlx_queens: src/dlx_queens.c dlx.o trail.o src/dlx.h
	$(CC) $(CFLAGS) -Isrc -o $@ src/dlx_queens.c dlx.o trail.o $(LDFLAGS)

dlx_crossword: src/dlx_crossword.c dlx.o trail.o src/dlx.h
	$(CC) $(CFLAGS) -Isrc -o $@ src/dlx_crossword.c dlx.o trail.o $(LDFLAGS)

# ---- Tests ---------------------------------------------------------------

trail_test: src/trail_test.c trail.o
	$(CC) $(CFLAGS) -Isrc -o $@ src/trail_test.c trail.o $(LDFLAGS)

csp_test: src/csp_test.c $(OBJS) src/csp.h
	$(CC) $(CFLAGS) -Isrc -o $@ src/csp_test.c $(OBJS) $(LDFLAGS)

dlx_test: src/dlx_test.c dlx.o trail.o src/dlx.h
	$(CC) $(CFLAGS) -Isrc -o $@ src/dlx_test.c dlx.o trail.o $(LDFLAGS)

test: $(TESTS)
	@echo "running trail_test..."
	@./trail_test
	@echo "running csp_test..."
	@./csp_test
	@echo "running dlx_test..."
	@./dlx_test

# ---- Benchmarks ----------------------------------------------------------
# Two binaries built from the same bench.c. bench_naive links the original
# AC-3 fixpoint; bench_queued links the queue-driven version. Same API,
# so the harness is identical -- the speedup is purely from the queue.

csp_naive.o: src/csp_naive.c src/csp.h src/trail.h
	$(CC) $(CFLAGS) -Isrc -c -o $@ $<

bench_queued: src/bench.c csp.o trail.o src/csp.h
	$(CC) $(CFLAGS) -Isrc -o $@ src/bench.c csp.o trail.o $(LDFLAGS)

bench_naive: src/bench.c csp_naive.o trail.o src/csp.h
	$(CC) $(CFLAGS) -Isrc -o $@ src/bench.c csp_naive.o trail.o $(LDFLAGS)

bench: $(BENCHMARKS)

# ---- Boilerplate ---------------------------------------------------------

clean:
	rm -f *.o $(CSP_DEMOS) $(DLX_DEMOS) $(TESTS) $(BENCHMARKS)

.PHONY: all clean test bench
