2 ;; Copyright (C) 2005 Andy Wingo <wingo at pobox.com>
4 ;; This program is free software; you can redistribute it and/or
5 ;; modify it under the terms of the GNU General Public License as
6 ;; published by the Free Software Foundation; either version 2 of
7 ;; the License, or (at your option) any later version.
9 ;; This program is distributed in the hope that it will be useful,
10 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
11 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 ;; GNU General Public License for more details.
14 ;; You should have received a copy of the GNU General Public License
15 ;; along with this program; if not, contact:
17 ;; Free Software Foundation Voice: +1-617-542-5942
18 ;; 59 Temple Place - Suite 330 Fax: +1-617-542-2652
19 ;; Boston, MA 02111-1307, USA gnu@gnu.org
24 ;; Utilities for the network clock simulator.
31 (use-modules ((srfi srfi-1) (fold unfold)))
33 (define (read-bytes-from-file-as-integer f n)
34 (with-input-from-file f
36 (fold (lambda (x seed) (+ x (ash seed 8)))
38 (unfold zero? (lambda (n) (char->integer (read-char))) 1- n)))))
40 (set! *random-state* (seed->random-state
41 (read-bytes-from-file-as-integer "/dev/random" 4)))
47 (inexact->exact (round x))
50 (define (filter proc l)
53 ((proc (car l)) (cons (car l) (filter proc (cdr l))))
54 (else (filter proc (cdr l)))))
60 (/ (sum nums) (length nums)))
65 (define (debug str . args)
67 (apply format (current-error-port) str args)))
69 (define (print-event kind x y)
70 (format #t "~a ~a ~a\n" kind x y))
72 ;; Linear least squares.
74 ;; See http://mathworld.wolfram.com/LeastSquaresFitting.html
75 ;; returns (values slope intercept r-squared)
77 (define (least-squares x y)
79 (let ((xbar (apply avg x))
81 (let ((sxx (- (sum (map sq x)) (* n (sq xbar))))
82 (syy (- (sum (map sq y)) (* n (sq ybar))))
83 (sxy (- (sum (map * x y)) (* n xbar ybar))))
84 (let ((slope (/ sxy sxx)))
87 (- ybar (* slope xbar))
88 (/ (sq sxy) (* sxx syy))))))))
90 ;; Streams: lists with lazy cdrs.
92 (define-macro (stream-cons kar kdr)
93 `(cons ,kar (delay ,kdr)))
95 (define (stream-cdr stream)
98 (define (stream-car stream)
101 (define (stream-null? stream)
104 (define (stream-ref stream n)
107 (stream-ref (stream-cdr stream) (1- n))))
109 (define (stream->list stream n)
110 (let lp ((in stream) (out '()) (n n))
113 (lp (stream-cdr in) (cons (stream-car in) out) (1- n)))))
115 (define (stream-skip stream n)
118 (stream-skip (stream-cdr stream) (1- n))))
120 (define (stream-sample stream n)
121 (stream-cons (stream-car stream)
122 (stream-sample (stream-skip stream n) n)))
124 (define (stream-map proc . streams)
125 (stream-cons (apply proc (map stream-car streams))
126 (apply stream-map proc (map stream-cdr streams))))
128 (define (arithmetic-series start step)
129 (stream-cons start (arithmetic-series (+ start step) step)))
131 (define (scale-stream stream factor)
132 (stream-map (lambda (t) (* t factor)) stream))
134 (define (stream-while pred proc . streams)
135 (if (apply pred (map stream-car streams))
137 (apply proc (map stream-car streams))
138 (apply stream-while pred proc (map stream-cdr streams)))))
140 (define (stream-of val)
141 (stream-cons val (stream-of val)))
143 (define (periodic-stream val period)
144 (let ((period (iround (max 1 (* *sample-frequency* period)))))
147 (stream-cons val (lp period))
148 (stream-cons #f (lp (1- n)))))))
151 ;; Queues with a maximum length.
154 (cons l (last-pair l)))
162 (define (q-push q val)
163 (let ((tail (cons val '())))
164 (if (null? (q-tail q))
166 (let ((l (append! (q-head q) tail)))
167 (if (> (length (q-head q)) *window-size*)
168 (make-q (cdr (q-head q)))
172 ;; Parameters, settable via command line arguments.
174 (define %parameters '())
175 (define-macro (define-parameter name val)
176 (let ((str (symbol->string name)))
177 (or (and (eqv? (string-ref str 0) #\*)
178 (eqv? (string-ref str (1- (string-length str))) #\*))
179 (error "Invalid parameter name" name))
180 (let ((param (string->symbol
181 (substring str 1 (1- (string-length str)))))
185 (let ((,val-sym ,val))
186 (set! ,name ,val-sym)
187 (set! %parameters (cons (cons ',param ,val-sym)
189 (define (set-parameter! name val)
190 (define (symbol-append . args)
191 (string->symbol (apply string-append (map symbol->string args))))
192 (or (assq name %parameters)
193 (error "Unknown parameter" name))
194 (module-set! (current-module) (symbol-append '* name '*) val))
196 (define (parse-parameter-arguments args)
198 (format #t "Usage: ~a ARG1...\n\n" "network-clock.scm")
201 (format #t "\t--~a=VAL \t(default: ~a)\n" (car pair) (cdr pair)))
203 (define (unknown-arg arg)
204 (with-output-to-port (current-error-port)
206 (format #t "\nUnknown argument: ~a\n\n" arg)
209 (define (parse-arguments args)
210 (let lp ((in args) (out '()))
214 ((not (string=? (substring (car in) 0 2) "--"))
215 (unknown-arg (car in)))
217 (let ((divider (or (string-index (car in) #\=)
218 (unknown-arg (car in)))))
219 (or (> divider 2) (unknown-arg (car in)))
220 (let ((param (string->symbol (substring (car in) 2 divider)))
221 (val (with-input-from-string (substring (car in) (1+ divider))
223 (lp (cdr in) (acons param val out))))))))
226 (or (false-if-exception
227 (set-parameter! (car pair) (cdr pair)))
228 (unknown-arg (format #f "--~a=~a" (car pair) (cdr pair)))))
229 (parse-arguments args)))