r4243: Auto commit for Debian build
[kmrcl.git] / genutils.lisp
index e13e46c69279fb80db6228248d318e6840b84669..cee438bcbf53ff4f5235015a45455aedf8efbc5d 100644 (file)
@@ -7,7 +7,7 @@
 ;;;; Programmer:    Kevin M. Rosenberg
 ;;;; Date Started:  Apr 2000
 ;;;;
-;;;; $Id: genutils.lisp,v 1.6 2002/11/04 18:02:13 kevin Exp $
+;;;; $Id: genutils.lisp,v 1.15 2003/02/07 14:21:55 kevin Exp $
 ;;;;
 ;;;; This file, part of KMRCL, is Copyright (c) 2002 by Kevin M. Rosenberg
 ;;;;
 (in-package :kmrcl)
 (declaim (optimize (speed 3) (safety 1) (compilation-speed 0) (debug 3)))
 
-(defmacro bind-when ((bind-var boundForm) &body body)
-  `(let ((,bind-var ,boundForm))
-      (declare (ignore-if-unused ,bind-var))
-      (when ,bind-var
-        ,@body)))
+(defmacro let-when ((var test-form) &body body)
+  `(let ((,var ,test-form))
+      (when ,var ,@body)))
   
-(defmacro bind-if ((bind-var boundForm) yup &optional nope)
-  `(let ((,bind-var ,boundForm))
-      (if ,bind-var
-         ,yup
-         ,nope)))
+(defmacro let-if ((var test-form) if-true &optional if-false)
+  `(let ((,var ,test-form))
+      (if ,var ,if-true ,if-false)))
 
 ;; Anaphoric macros
 
         (if val (push val acc))))
     (nreverse acc)))
 
+(defun appendnew (l1 l2)
+  "Append two lists, filtering out elem from second list that are already in first list"
+  (dolist (elem l2)
+    (unless (find elem l1)
+      (setq l1 (append l1 (list elem)))))
+  l1)
 
 ;; Functions
 
          ((> ,var ,gstop))
        ,@body)))
 
-
+(defmacro with-each-stream-line ((var stream) &body body)
+  (let ((eof (gensym))
+       (eof-value (gensym))
+       (strm (gensym)))
+    `(let ((,strm ,stream)
+          (,eof ',eof-value))
+      (do ((,var (read-line ,strm nil ,eof) (read-line ,strm nil ,eof)))
+         ((eql ,var ,eof))
+       ,@body))))
+
+(defmacro with-each-file-line ((var file) &body body)
+  (let ((stream (gensym)))
+    `(with-open-file (,stream ,file :direction :input)
+      (with-each-stream-line (,var ,stream)
+       ,@body))))
+
+               
 ;;; Keyword functions
 
 (defun remove-keyword (key arglist)
 
 (defun indent-spaces (n &optional (stream *standard-output*))
   "Indent n*2 spaces to output stream"
-  (let ((fmt (format nil "~~~DT" (+ n n))))
-    (format stream fmt)))
+  (when (numberp n)
+    (let ((fmt (format nil "~~~DT" (+ n n))))
+      (format stream fmt))))
 
 (defun print-list (l &optional (output *standard-output*))
   "Print a list to a stream"
     (terpri ostrm)))
 
 
-;;; Symbol functions
-
-(defmacro concat-symbol (&rest args)
-  `(intern (concatenate 'string ,@args)))
-
-(defmacro concat-symbol-pkg (pkg &rest args)
-  `(intern (concatenate 'string ,@args) ,pkg))
-
-
 ;;; IO
 
 
 
 (defun file-subst (old new file1 file2)
   (with-open-file (in file1 :direction :input)
-     (with-open-file (out file2 :direction :output
-                                :if-exists :supersede)
-       (stream-subst old new in out))))
+    (with-open-file (out file2 :direction :output
+                        :if-exists :supersede)
+      (stream-subst old new in out))))
 
 (defun stream-subst (old new in out)
   (declare (string old new))
   "Opens a reads a file. Returns the contents as a single string"
   (when (probe-file file)
     (with-open-file (in file :direction :input)
-                   (do ((line (read-line in nil 'eof) 
-                              (read-line in nil 'eof)))
-                       ((eql line 'eof))
-                     (format strm "~A~%" line)))))
+      (let ((eof (gensym)))                
+       (do ((line (read-line in nil eof) 
+                  (read-line in nil eof)))
+           ((eq line eof))
+         (format strm "~A~%" line))))))
 
 (defun read-file-to-string (file)
   "Opens a reads a file. Returns the contents as a single string"
   (with-output-to-string (out)
     (with-open-file (in file :direction :input)
-      (do ((line (read-line in nil 'eof) 
-                (read-line in nil 'eof)))
-         ((eql line 'eof))
-       (format out "~A~%" line)))))
+      (let ((eof (gensym)))                
+       (do ((line (read-line in nil eof) 
+                  (read-line in nil eof)))
+           ((eq line eof))
+         (format out "~A~%" line))))))
 
 (defun read-file-to-strings (file)
   "Opens a reads a file. Returns the contents as a list of strings"
   (let ((lines '()))
     (with-open-file (in file :direction :input)
-      (do ((line (read-line in nil 'eof) 
-                (read-line in nil 'eof)))
-         ((eql line 'eof))
-       (push line lines)))
-    (nreverse lines)))
-
+      (let ((eof (gensym)))                
+       (do ((line (read-line in nil eof) 
+                  (read-line in nil eof)))
+           ((eq line eof))
+         (push line lines)))
+      (nreverse lines))))
 
 
 ;;; Formatting functions
                year
                hr min sec))))
 
+
+;; Benchmarking
+
+(defun print-float-units (val unit)
+  (cond
+    ((< val 1d-6)
+     (format t "~,2,9F nano~A" val unit))
+    ((< val 1d-3)
+     (format t "~,2,6F micro~A" val unit))
+    ((< val 1)
+     (format t "~,2,3F milli~A" val unit))
+    ((> val 1d9)
+     (format t "~,2,-9F giga~A" val unit))
+    ((> val 1d6)
+     (format t "~,2,-6F mega~A" val unit))
+    ((> val 1d3)
+     (format t "~,2,-3F kilo~A" val unit))
+    (t
+     (format t "~,2F ~A" val unit))))
+
+(defun print-seconds (secs)
+  (print-float-units secs "sec"))
+
+(defmacro time-iterations (n &body body)
+  (let ((i (gensym))
+       (count (gensym)))
+    `(progn
+       (let ((,count ,n))
+        (format t "~&Test with ~d iterations: ~W" ,count (quote ,body))
+        (let ((t1 (get-internal-real-time)))
+          (dotimes (,i ,count)
+            ,@body)
+          (let* ((t2 (get-internal-real-time))
+                 (secs (coerce (/ (- t2 t1)
+                                  internal-time-units-per-second)
+                               'double-float)))
+            (format t "~&Total time: ")
+            (print-seconds secs)
+            (format t ", time per iteration: ")
+            (print-seconds (coerce (/ secs ,n) 'double-float))))))))
+
+
+(defun nsubseq (sequence start &optional (end (length sequence)))
+  (make-array (- end start)
+             :element-type (array-element-type sequence)
+             :displaced-to sequence
+             :displaced-index-offset start))