%%%%%%%%%%%%%%%%%%%%%%%%% Start LaTeX boilerplate %%%%%%%%%%%%%%%%%%%%%%%%%%%
% we have our own preamble,
% use `noweave -delay` to not print noweb's automatic one
- % -*- mode: Noweb; noweb-code-mode: c-mode -*-
+% -*- mode: Noweb; noweb-code-mode: c-mode -*-
\documentclass[letterpaper, 11pt]{article}
\usepackage{noweb}
\pagestyle{noweb}
@
<<parse module makefile lines>>=
-parse.c : sawsim.nw
- notangle -Rparse.c $^ > $@
-parse.h : sawsim.nw
- notangle -Rparse.h $^ > $@
-check_parse.c : sawsim.nw
- notangle -Rcheck-parse.c $^ > $@
-check_parse : check_parse.c parse.c parse.h
- gcc -g -o $@ $< parse.c -lcheck
-clean_parse :
- rm -f parse.c parse.h check_parse.c check_parse
+NW_SAWSIM_MODS += parse
+CHECK_BINS += check_parse
+check_parse_MODS =
@
<<parse definitions>>=
@
<<tension balance module makefile lines>>=
-tension_balance.c : sawsim.nw
- notangle -Rtension-balance.c $^ > $@
-tension_balance.h : sawsim.nw
- notangle -Rtension-balance.h $^ > $@
-check_tension_balance.c : sawsim.nw
- notangle -Rcheck-tension-balance.c $^ > $@
-check_tension_balance : check_tension_balance.c global.h tension_balance.c tension_balance.h
- gcc -g -o $@ $< tension_balance.c -lcheck
-clean_tension :
- rm -f tension_balance.c tension_balance.h check_tension_balance.c check_tension_balance
+NW_SAWSIM_MODS += tension_balance
+CHECK_BINS += check_tension_balance
+check_tension_balance_MODS =
@
The entire force balancing problem reduces to a solving two nested
@
<<list module makefile lines>>=
-list.c : sawsim.nw
- notangle -Rlist.c $^ > $@
-list.h : sawsim.nw
- notangle -Rlist.h $^ > $@
-check_list.c : sawsim.nw
- notangle -Rcheck-list.c $^ > $@
-check_list : check_list.c global.h list.c list.h
- gcc -g -o $@ $< list.c -lcheck
-clean_list :
- rm -f list.c list.h check_list.c check_list
+NW_SAWSIM_MODS += list
+CHECK_BINS += check_list
+check_list_MODS =
@
<<list definitions>>=
<<list check includes>>=
#include <stdlib.h> /* EXIT_SUCCESS and EXIT_FAILURE */
+#include <stdio.h> /* FILE */
<<check includes>>
+#include "global.h"
#include "list.h"
@
@
<<string eval module makefile lines>>=
-string_eval.c : sawsim.nw
- notangle -Rstring-eval.c $^ > $@
-string_eval.h : sawsim.nw
- notangle -Rstring-eval.h $^ > $@
-check_string_eval.c : sawsim.nw
- notangle -Rcheck-string-eval.c $^ > $@
-check_string_eval : check_string_eval.c string_eval.c string_eval.h
- gcc -g -o $@ $< string_eval.c -lcheck -lgsl -lgslcblas -lm
-clean_string_eval :
- rm -f string_eval.c string_eval.h check_string_eval.c check_string_eval
+NW_SAWSIM_MODS += string_eval
+CHECK_BINS += check_string_eval
+check_string_eval_MODS =
@
For an introduction to POSIX process control, see\\
@
<<accel k module makefile lines>>=
-accel_k.c : sawsim.nw
- notangle -Raccel-k.c $^ > $@
-accel_k.h : sawsim.nw
- notangle -Raccel-k.h $^ > $@
-check_accel_k.c : sawsim.nw
- notangle -Rcheck-accel_k.c $^ > $@
-check_accel_k : check_accel_k.c global.h
- gcc -g -o $@ $< accel_k.c -lcheck -lgsl -lgslcblas -lm
-clean_accel_k :
- rm -f accel_k.c accel_k.h check_accel_k.c check_accel_k
+NW_SAWSIM_MODS += accel_k
+#CHECK_BINS += check_accel_k
+check_accel_k_MODS =
@
<<accel-k.c>>=
@
<<tension model module makefile lines>>=
-tension_model.c : sawsim.nw
- notangle -Rtension-model.c $^ > $@
-tension_model.h : sawsim.nw
- notangle -Rtension-model.h $^ > $@
-check_tension_model.c : sawsim.nw
- notangle -Rcheck-tension-model.c $^ > $@
-check_tension_model : check_tension_model.c global.h tension_model.c tension_model.h
- gcc -g -o $@ $< tension_model.c -lcheck -lgsl -lgslcblas -lm
-clean_tension_model : clean_tension_model_utils
- rm -f tension_model.c tension_model.h check_tension_model.c check_tension_model
-tension_model_utils.c : sawsim.nw
- notangle -Rtension-model-utils.c $^ > $@
-tension_model_utils : tension_model_utils.c global.h tension_model.c tension_model.h parse.c parse.h \
- list.c list.h tension_balance.c tension_balance.h
- gcc -g -o $@ $< tension_model.c parse.c list.c tension_balance.c -lgsl -lgslcblas -lm
-tension_model_utils_static : tension_model_utils.c global.h tension_model.c tension_model.h parse.c parse.h \
- list.c list.h tension_balance.c tension_balance.h
- gcc -g -static -o $@ $< tension_model.c parse.c list.c tension_balance.c -lgsl -lgslcblas -lm
+NW_SAWSIM_MODS += tension_model
+#CHECK_BINS += check_tension_model
+check_tension_model_MODS =
+@
+<<tension model utils makefile lines>>=
+TENSION_MODEL_MODS = tension_model parse list tension_balance
+TENSION_MODEL_SRC = $(BUILD_DIR)/tension_model_utils.c $(BUILD_DIR)/global.h \
+ $(TENSION_MODEL_MODS:%=$(BUILD_DIR)/%.c) \
+ $(TENSION_MODEL_MODS:%=$(BUILD_DIR)/%.h)
+$(BUILD_DIR)/tension_model_utils.c : $(SRC_DIR)/sawsim.nw $(BUILD_DIR)
+ notangle -Rtension-model-utils.c $< > $@
+$(BIN_DIR)/tension_model_utils : $(TENSION_MODEL_SRC) $(BIN_DIR)
+ gcc -g -o $@ $< $(TENSION_MODEL_MODS:%=$(BUILD_DIR)/%.c) $(LIBS:%=-l%)
clean_tension_model_utils :
- rm -f tension_model_utils.c tension_model_utils
+ rm -f $(BUILD_DIR)/tension_model_utils.c $(BIN_DIR)/tension_model_utils
@
\subsection{Null}
@
<<k model module makefile lines>>=
-k_model.c : sawsim.nw
- notangle -Rk-model.c $^ > $@
-k_model.h : sawsim.nw
- notangle -Rk-model.h $^ > $@
-check_k_model.c : sawsim.nw
- notangle -Rcheck-k-model.c $^ > $@
-check_k_model : check_k_model.c global.h k_model.c k_model.h
- gcc -g -o $@ $< k_model.c -lcheck -lgsl -lgslcblas -lm
-clean_k_model : clean_k_model_utils
- rm -f k_model.c k_model.h check_k_model.c check_k_model
-k_model_utils.c : sawsim.nw
- notangle -Rk-model-utils.c $^ > $@
-k_model_utils : k_model_utils.c global.h k_model.c k_model.h parse.c parse.h string_eval.c string_eval.h
- gcc -g -o $@ $< k_model.c parse.c string_eval.c -lgsl -lgslcblas -lm
-k_model_utils_static : k_model_utils.c global.h k_model.c k_model.h parse.c parse.h string_eval.c string_eval.h
- gcc -g -static -o $@ $< k_model.c parse.c string_eval.c -lgsl -lgslcblas -lm
+NW_SAWSIM_MODS += k_model
+CHECK_BINS += check_k_model
+check_k_model_MODS = parse string_eval
+@
+[[check_k_model]] also depends on the parse module.
+
+<<k model utils makefile lines>>=
+K_MODEL_MODS = k_model parse string_eval
+K_MODEL_SRC = $(BUILD_DIR)/k_model_utils.c $(BUILD_DIR)/global.h \
+ $(K_MODEL_MODS:%=$(BUILD_DIR)/%.c) $(K_MODEL_MODS:%=$(BUILD_DIR)/%.h)
+$(BUILD_DIR)/k_model_utils.c : $(SRC_DIR)/sawsim.nw $(BUILD)
+ notangle -Rk-model-utils.c $< > $@
+$(BIN_DIR)/k_model_utils : $(K_MODEL_SRC) $(BIN_DIR)
+ gcc -g -o $@ $< $(K_MODEL_MODS:%=$(BUILD_DIR)/%.c) $(LIBS:%=-l%)
clean_k_model_utils :
- rm -f k_model_utils.c k_model_utils
+ rm -f $(BUILD_DIR)/k_model_utils.c $(BIN_DIR)/k_model_utils
@
\subsection{Null}
int i;
for( i=0; i < sizeof(knot)/sizeof(char *); i++) {
params[0] = knot[i];
- p = string_create_const_param_t(params);
- destroy_const_param_t(p);
+ p = string_create_const_k_param_t(params);
+ destroy_const_k_param_t(p);
}
}
END_TEST
env.T = T;
for( i=0; i < sizeof(knot)/sizeof(char *); i++) {
params[0] = knot[i];
- p = string_create_const_param_t(params);
- for ( F=Fm, F<FM, F+=dF ) {
+ p = string_create_const_k_param_t(params);
+ for ( F=Fm; F<FM; F+=dF ) {
fail_unless(const_k(F, &env, p)==atof(knot[i]),
- "const_k(%g, %g, &{%s,%s}) = %g != %s",
- F, T, knot[i], dx, const_k(F, &env, p), knot[i]);
+ "const_k(%g, %g, &{%s}) = %g != %s",
+ F, T, knot[i], const_k(F, &env, p), knot[i]);
}
- destroy_const_param_t(p);
+ destroy_const_k_param_t(p);
}
}
END_TEST
The comment blocks in this [[noweb]] file are in \LaTeX\ with \BibTeX\ citations.
The comment blocks are extracted (with nicely formatted code blocks), using
<<latex makefile lines>>=
-sawsim.tex : sawsim.nw
- noweave -latex -index -delay $^ > $@
+$(BUILD_DIR)/sawsim.tex : $(SRC_DIR)/sawsim.nw $(BUILD_DIR)
+ noweave -latex -index -delay $< > $@
+$(BUILD_DIR)/sawsim.bib : $(SRC_DIR)/sawsim.bib $(BUILD_DIR)
+ cp -f $< $@
@
and compiled using
<<latex makefile lines>>=
-sawsim.pdf : sawsim.tex sawsim.bib
- pdflatex $^
- bibtex sawsim
- pdflatex $^
- pdflatex $^
+$(DOC_DIR)/sawsim.pdf : $(BUILD_DIR)/sawsim.tex $(BUILD_DIR)/sawsim.bib \
+ $(DOC_DIR)
+ $(SHELL) -e -c "cd $(BUILD_DIR) && pdflatex sawsim"
+ $(SHELL) -e -c "cd $(BUILD_DIR) && bibtex sawsim"
+ $(SHELL) -e -c "cd $(BUILD_DIR) && pdflatex sawsim"
+ $(SHELL) -e -c "cd $(BUILD_DIR) && pdflatex sawsim"
+ mv $(BUILD_DIR)/sawsim.pdf $@
@
The first [[pdflatex]] pass reads through the \TeX\ source and extracts citation information,
the \BibTeX\ pass looks through the \BibTeX\ databases for the cited works, and
[[bibtex]] and [[pdflatex]] produce quite a few intermediate files, so provide a means to clean them up.
<<latex makefile lines>>=
semi-clean_latex :
- rm -f sawsim.aux sawsim.bbl sawsim.blg sawsim.log sawsim.out sawsim.tex
+ rm -f $(BUILD_DIR)/sawsim.aux $(BUILD_DIR)/sawsim.bbl \
+ $(BUILD_DIR)/sawsim.blg $(BUILD_DIR)/sawsim.log \
+ $(BUILD_DIR)/sawsim.out $(BUILD_DIR)/sawsim.tex \
+ $(BUILD_DIR)/sawsim.bib
clean_latex : semi-clean_latex
- rm -f sawsim.pdf
+ rm -f $(DOC_DIR)/sawsim.pdf
@
\section{Makefile}
% [[dist]] for generating a distributable tar file.
Extract the makefile with
-`[[notangle -Rmakefile sawsim.nw | sed 's/ /\t/' > Makefile]]'.
+`[[notangle -Rmakefile src/sawsim.nw | sed 's/ /\t/' > Makefile]]'.
The sed is needed because notangle replaces tabs with eight spaces,
but [[make]] needs tabs.
<<makefile>>=
-all : sawsim sawsim.pdf Makefile tension_model_utils k_model_utils
-
-view : sawsim.pdf
- xpdf $^ &
-profile : sawsim_profile
- sawsim_profile -v1e-6 -Mhooke -A.05 -U1 -kkramers_integ -mnull -Mwlc -A0.39e-9,28e-9 -F8
- gprof sawsim_profile gmon.out > $@
-
-clean : clean_check clean_list clean_tension clean_tension_model clean_tension_model_utils clean_k_model clean_parse clean_string_eval clean_latex
- rm -f sawsim.c sawsim sawsim_static sawsim_profile gmon.out global.h
-
-sawsim.c : sawsim.nw
- notangle $^ > $@
-global.h : sawsim.nw
- notangle -Rglobal.h $^ > $@
-sawsim : sawsim.c global.h list.c list.h tension_balance.c tension_balance.h \
- tension_model.c tension_model.h k_model.c k_model.h parse.c parse.h string_eval.c string_eval.h \
- accel_k.c accel_k.h
- gcc -g -o $@ $< list.c tension_balance.c tension_model.c k_model.c parse.c string_eval.c accel_k.c interp.c tavl.c -lgsl -lgslcblas -lm
-sawsim_static : sawsim
- gcc -g -static -o $@ sawsim.c list.c tension_balance.c tension_model.c k_model.c parse.c string_eval.c accel_k.c interp.c tavl.c -lgsl -lgslcblas -lm
-sawsim_profile : sawsim
- gcc -g -pg -o $@ sawsim.c list.c tension_balance.c tension_model.c k_model.c parse.c string_eval.c accel_k.c interp.c tavl.c -lgsl -lgslcblas -lm
-
-
-check_sawsim.c : sawsim.nw
- notangle -Rchecks $^ > $@
-check_sawsim : check_sawsim.c global.h list.c list.h tension_balance.c tension_balance.h \
- k_model.c k_model.h parse.c parse.h string_eval.c string_eval.h accel_k.c accel_k.h
- gcc -g -o $@ $< list.c tension_balance.c k_model.c parse.c string_eval.c accel_k.c interp.c tavl.c -lgsl -lgslcblas -lm -lcheck
-clean_check :
- rm -f check_sawsim check_sawsim.c
-check : check_list check_tension_balance check_k_model check_parse check_string_eval check_accel_k check_sawsim
- check_list
- check_tension_balance
- check_k_model
- check_parse
- check_string_eval
- check_accel_k
- check_sawsim
+# Decide what directories to put things in
+SRC_DIR = src
+BUILD_DIR = build
+BIN_DIR = bin
+DOC_DIR = doc
+# Note: Cannot use, for example, `./build', because make eats the `./'
+# and then $(BUILD_DIR) doesn't match in $$(subst $(BUILD_DIR), ...)
+
+# Modules (X.c, X.h) defined in the noweb file
+NW_SAWSIM_MODS =
+CHECK_BINS =
+# Modules defined outside the noweb file
+FREE_SAWSIM_MODS = interp tavl
<<list module makefile lines>>
<<tension balance module makefile lines>>
<<parse module makefile lines>>
<<string eval module makefile lines>>
<<accel k module makefile lines>>
+
+SAWSIM_MODS = $(NW_SAWSIM_MODS) $(FREE_SAWSIM_MODS)
+
+# Everything needed for sawsim under one roof. sawsim.c must come first
+SAWSIM_SRC = $(BUILD_DIR)/sawsim.c $(BUILD_DIR)/global.h \
+ $(SAWSIM_MODS:%=$(BUILD_DIR)/%.c) $(SAWSIM_MODS:%=$(BUILD_DIR)/%.h)
+# Libraries needed to compile sawsim
+LIBS = gsl gslcblas m
+CHECK_LIBS = gsl gslcblas m check
+# The non-check binaries generated
+BINS = sawsim tension_model_utils k_model_utils sawsim_profile
+DOCS = sawsim.pdf
+
+# Define the major targets
+all : ./Makefile $(BINS:%=$(BIN_DIR)/%) $(DOCS:%=$(DOC_DIR)/%) ;
+
+view : $(DOC_DIR)/sawsim.pdf
+ xpdf $< &
+profile : $(BIN_DIR)/sawsim_profile $(BIN_DIR)
+ $(BIN_DIR)/sawsim_profile -v1e-6 -Mhooke -A.05 -U1 -kkramers_integ \
+ -mnull -Mwlc -A0.39e-9,28e-9 -F8
+ gprof $(BIN_DIR)/sawsim_profile gmon.out > $@
+check : $(CHECK_BINS:%=$(BIN_DIR)/%) $(BIN_DIR)/check_sawsim
+ $(SHELL) -e -c 'for B in $^; do ./$$B; done'
+clean : $(CHECK_BINS:%=clean_%) clean_tension_model_utils \
+ clean_k_model_utils clean_latex
+ rm -f $(BIN_DIR)/sawsim $(BIN_DIR)/sawsim_static \
+ $(BIN_DIR)/sawsim_profile $(BUILD_DIR)/sawsim.c \
+ $(BUILD_DIR)/interp.c $(BUILD_DIR)/interp.h \
+ $(BUILD_DIR)/tavl.c $(BUILD_DIR)/tavl.h \
+ $(BUILD_DIR)/global.h ./gmon.out
+ $(SHELL) -e -c "rmdir $(BUILD_DIR) $(BIN_DIR) $(DOC_DIR)"
+
+# Various builds of sawsim
+$(BIN_DIR)/sawsim : $(SAWSIM_SRC) $(BIN_DIR)
+ gcc -g -o $@ $< $(SAWSIM_MODS:%=$(BUILD_DIR)/%.c) $(LIBS:%=-l%)
+$(BIN_DIR)/sawsim_static : $(SAWSIM_SRC) $(BIN_DIR)
+ gcc -g -static -o $@ $< $(SAWSIM_MODS:%=$(BUILD_DIR)/%.c) $(LIBS:%=-l%)
+$(BIN_DIR)/sawsim_profile : $(SAWSIM_SRC) $(BIN_DIR)
+ gcc -g -pg -o $@ $< $(SAWSIM_MODS:%=$(BUILD_DIR)/%.c) $(LIBS:%=-l%)
+
+# Create the directories
+$(BUILD_DIR) $(BIN_DIR) $(DOC_DIR) :
+ mkdir $@
+
+# Copy over the source external to sawsim
+# Note: Cannot use, for example, `./build', because make eats the `./'
+# and then $(BUILD_DIR) doesn't match in $$(subst $(BUILD_DIR), ...)
+.SECONDEXPANSION:
+$(FREE_SAWSIM_MODS:%=$(BUILD_DIR)/%.h) : $$(subst $(BUILD_DIR),$(SRC_DIR),$$@)\
+ $(BUILD_DIR)
+ cp -f $< $@
+.SECONDEXPANSION:
+$(FREE_SAWSIM_MODS:%=$(BUILD_DIR)/%.c) : $$(subst $(BUILD_DIR),$(SRC_DIR),$$@)\
+ $(BUILD_DIR)
+ cp -f $< $@
+
+## Basic source generated with noweb
+# The central files sawsim.c and global.h...
+$(BUILD_DIR)/sawsim.c : $(SRC_DIR)/sawsim.nw $(BUILD_DIR)
+ notangle $< > $@
+$(BUILD_DIR)/global.h : $(SRC_DIR)/sawsim.nw $(BUILD_DIR)
+ notangle -Rglobal.h $< > $@
+# ... and the modules
+$(NW_SAWSIM_MODS:%=$(BUILD_DIR)/%.h) : $(SRC_DIR)/sawsim.nw $(BUILD_DIR)
+ notangle -R$(subst _,-,$(@:$(BUILD_DIR)/%=%)) $< > $@
+$(NW_SAWSIM_MODS:%=$(BUILD_DIR)/%.c) : $(SRC_DIR)/sawsim.nw $(BUILD_DIR)
+ notangle -R$(subst _,-,$(@:$(BUILD_DIR)/%=%)) $< > $@
+$(CHECK_BINS:%=$(BUILD_DIR)/%.c) : $(SRC_DIR)/sawsim.nw $(BUILD_DIR)
+ notangle -R$(subst _,-,$(@:$(BUILD_DIR)/%=%)) $< > $@
+# Note: I use `_' as a space in my file names, but noweb doesn't like
+# that so we use `-' to name the noweb roots and substitute here.
+
+## Building the unit-test programs
+# for sawsim.c...
+$(BUILD_DIR)/check_sawsim.c : $(SRC_DIR)/sawsim.nw
+ notangle -Rchecks $< > $@
+$(BIN_DIR)/check_sawsim : $(BUILD_DIR)/check_sawsim.c $(BUILD_DIR)/global.h \
+ $(SAWSIM_MODS:%=$(BUILD_DIR)/%.c) \
+ $(SAWSIM_MODS:%=$(BUILD_DIR)/%.h) $(BIN_DIR)
+ gcc -g -o $@ $< $(SAWSIM_MODS:%=$(BUILD_DIR)/%.c) $(CHECK_LIBS:%=-l%)
+clean_check_sawsim :
+ rm -f $(BIN_DIR)/check_sawsim $(BUILD_DIR)/check_sawsim.c
+# ... and the modules
+.SECONDEXPANSION:
+$(CHECK_BINS:%=$(BIN_DIR)/%) : $$(subst $(BIN_DIR),$(BUILD_DIR),$$@).c \
+ $$(subst $(BIN_DIR)/check_,$(BUILD_DIR)/,$$@).c \
+ $$(subst $(BIN_DIR)/check_,$(BUILD_DIR)/,$$@).h \
+ $$(patsubst %,$(BUILD_DIR)/%.c,$$($$(subst $(BIN_DIR)/,,$$@_MODS)))\
+ $$(patsubst %,$(BUILD_DIR)/%.h,$$($$(subst $(BIN_DIR)/,,$$@_MODS)))\
+ $$(BUILD_DIR)/global.h $(BIN_DIR)
+ gcc -g -o $@ $< $(@:$(BIN_DIR)/check_%=$(BUILD_DIR)/%.c) \
+ $(patsubst %,$(BUILD_DIR)/%.c,$($(subst $(BIN_DIR)/,,$@_MODS)))\
+ $(CHECK_LIBS:%=-l%)
+# todo: clean up the required modules to
+$(CHECK_BINS:%=clean_%) :
+ rm -f $(@:clean_%=$(BIN_DIR)/%) $(@:clean_%=$(BUILD_DIR)/%.c)
+
+# Cleaning up the modules
+.SECONDEXPANSION:
+$(SAWSIM_MODS:%=clean_%) :
+ rm -f $(@:clean_%=$(BUILD_DIR)/%.c) $(@:clean_%=$(BUILD_DIR)/%.h)
+
+<<tension model utils makefile lines>>
+<<k model utils makefile lines>>
<<latex makefile lines>>
-Makefile : sawsim.nw
- notangle -Rmakefile $^ | sed 's/ /\t/' > $@
+Makefile : $(SRC_DIR)/sawsim.nw
+ notangle -Rmakefile $< | sed 's/ /\t/' > $@
@
-This is fairly self-explanatory.
-We compile a dynamically linked version ([[sawsim]]) and a statically linked version ([[sawsim_static]]).
-The static version is about 9 times as big, but it runs without needing dynamic GSL libraries to link to, so it's a better format for distributing to a cluster for parallel evaluation.
-
+This is fairly self-explanatory. We compile a dynamically linked
+version ([[sawsim]]) and a statically linked version
+([[sawsim_static]]). The static version is about 9 times as big, but
+it runs without needing dynamic GSL libraries to link to, so it's a
+better format for distributing to a cluster for parallel evaluation.
\section{Math}