The Computer Language
23.03 Benchmarks Game

spectral-norm Lisp SBCL program

source code

;;   The Computer Language Benchmarks Game
;;    Adapted from the C (gcc) code by Sebastien Loisel
;;    Contributed by Christopher Neufeld
;;    Modified by Juho Snellman 2005-10-26
;;      * Use SIMPLE-ARRAY instead of ARRAY in declarations
;;      * Use TRUNCATE instead of / for fixnum division
;;      * Rearrange EVAL-A to make it more readable and a bit faster

;; Note that sbcl is at least 10 times faster than either clisp or gcl
;; on this program, running with an argument of 500.  It would be nice
;; to know why the others are so slow.

(defun eval-AtA-times-u (n u)
  (eval-At-times-u n (eval-A-times-u n u)))

;; This is our most expensive function.  Optimized with the knowledge
;; that 'n' will never be "huge".  This will break if 'n' exceeds
;; approximately half of the square root of the largest fixnum
;; supported by the implementation.  On sbcl 0.9.3,
;; 'most-positive-fixnum' is 536870911, and we can support values of
;; 'n' above 11000.
(declaim (inline eval-A))
(defun eval-A (i j)
  (declare (type fixnum i j))
  (let* ((n (+ i j))
         (n+1 (1+ n)))
    (declare (fixnum n n+1))
    (/ (float (+ (truncate (the fixnum (* n n+1)) 2) i 1) 0d0))))

(defun eval-A-times-u (n u)
  (declare (type fixnum n)
           (type (simple-array double-float) u))
  (let ((retval (make-array n :element-type 'double-float :initial-element 0.0d0)))
    (dotimes (i n)
      (dotimes (j n)
        (incf (aref retval i) (* (eval-A i j) (aref u j)))))

(defun eval-At-times-u (n u)
  (declare (type fixnum n)
           (type (simple-array double-float) u))
  (let ((retval (make-array n :element-type 'double-float :initial-element 0.0d0)))
    (dotimes (i n)
      (dotimes (j n)
        (incf (aref retval i) (* (eval-A j i) (aref u j)))))

(defun main (&optional n-supplied)
  (let ((n (or n-supplied
               (parse-integer (or (car (last #+sbcl sb-ext:*posix-argv*
                                             #+clisp ext:*args*
                                             #+cmu extensions:*command-line-strings*
                                             #+gcl  si::*command-args*))
    (or (typep (* (- (* 2 n) 1) (- (* 2 n) 2)) 'fixnum)
        (error "The supplied value of 'n' breaks the optimizations in EVAL-A"))
    (let ((u (make-array n :element-type 'double-float :initial-element 1.0d0))
          (v (make-array n :element-type 'double-float)))
      (declare (type (simple-array double-float) U V))
      (dotimes (i 10)
        (setf v (eval-AtA-times-u n u))
        (setf u (eval-AtA-times-u n v)))
      (let ((vBv 0.0d0)
            (vv 0.0d0))
        (dotimes (i n)
          (incf vBv (* (aref u i) (aref v i)))
          (incf vv (* (aref v i) (aref v i))))
        (format t "~11,9F~%" (sqrt (the (double-float 0d0) (/ vBv vv))))))))

;; #+sbcl (progn
;;          (sb-profile:profile eval-AtA-times-u)
;;          (sb-profile:profile eval-A)
;;          (sb-profile:profile eval-A-times-u)
;;          (sb-profile:profile eval-At-times-u)
;;          (sb-profile:profile main))


notes, command-line, and program output

64-bit Ubuntu quad core
SBCL 2.3.0

Wed, 25 Jan 2023 20:59:49 GMT

cp: 'spectralnorm.sbcl' and './spectralnorm.sbcl' are the same file
SBCL built with: /opt/src/sbcl-2.3.0/bin/sbcl --userinit /dev/null --batch --eval '(load "spectralnorm.sbcl_compile")'
### START spectralnorm.sbcl_compile
(handler-bind ((sb-ext:defconstant-uneql      (lambda (c) (abort c))))      (require :sb-concurrency)      (load (compile-file "spectralnorm.sbcl" ))) (save-lisp-and-die "sbcl.core" :purify t)
### END spectralnorm.sbcl_compile

; compiling file "/home/dunham/all-benchmarksgame/benchmarksgame_i53330/spectralnorm/tmp/spectralnorm.sbcl" (written 26 APR 2018 12:50:14 PM):

; wrote /home/dunham/all-benchmarksgame/benchmarksgame_i53330/spectralnorm/tmp/spectralnorm.fasl
; compilation finished in 0:00:00.100
### START spectralnorm.sbcl_run
(main) (quit)
### END spectralnorm.sbcl_run

3.07s to complete and log all make actions

/opt/src/sbcl-2.3.0/bin/sbcl --dynamic-space-size 500 --noinform --core sbcl.core --userinit /dev/null --load spectralnorm.sbcl_run 5500