1
;;; N-body benchmark - Common Lisp without SBEXT
(declaim (optimize (speed 3) (safety 0) (debug 0) (space 0)))
(defconstant +solar-mass+ (* 4.0d0 3.141592653589793d0 3.141592653589793d0))
(defconstant +days-per-year+ 365.24d0)
(defconstant +dt+ 0.01d0)
(deftype f64-5 () '(simple-array double-float (5)))
(declaim (type f64-5 *x* *y* *z* *vx* *vy* *vz* *mass*))
(defparameter *x*
(make-array 5 :element-type 'double-float
:initial-contents '(0.0d0
4.84143144246472090d0
8.34336671824457987d0
1.28943695621391310d+01
1.53796971148509165d+01)))
(defparameter *y*
(make-array 5 :element-type 'double-float
:initial-contents '(0.0d0
-1.16032004402742839d0
4.12479856412430479d0
-1.51111514016986312d+01
-2.59193146099879641d+01)))
(defparameter *z*
(make-array 5 :element-type 'double-float
:initial-contents '(0.0d0
-1.03622044471123109d-01
-4.03523417114321381d-01
-2.23307578892655734d-01
1.79258772950371181d-01)))
(defparameter *vx*
(make-array 5 :element-type 'double-float
:initial-contents (list 0.0d0
(* 1.66007664274403694d-03 +days-per-year+)
(* -2.76742510726862411d-03 +days-per-year+)
(* 2.96460137564761618d-03 +days-per-year+)
(* 2.68067772490389322d-03 +days-per-year+))))
(defparameter *vy*
(make-array 5 :element-type 'double-float
:initial-contents (list 0.0d0
(* 7.69901118419740425d-03 +days-per-year+)
(* 4.99852801234917238d-03 +days-per-year+)
(* 2.37847173959480950d-03 +days-per-year+)
(* 1.62824170038242295d-03 +days-per-year+))))
(defparameter *vz*
(make-array 5 :element-type 'double-float
:initial-contents (list 0.0d0
(* -6.90460016972063023d-05 +days-per-year+)
(* 2.30417297573763929d-05 +days-per-year+)
(* -2.96589568540237556d-05 +days-per-year+)
(* -9.51592254519715870d-05 +days-per-year+))))
(defparameter *mass*
(make-array 5 :element-type 'double-float
:initial-contents (list +solar-mass+
(* 9.54791938424326609d-04 +solar-mass+)
(* 2.85885980666130812d-04 +solar-mass+)
(* 4.36624404335156298d-05 +solar-mass+)
(* 5.15138902046611451d-05 +solar-mass+))))
(declaim (ftype (function () (values)) advance))
(defun advance ()
(let ((x *x*) (y *y*) (z *z*)
(vx *vx*) (vy *vy*) (vz *vz*)
(mass *mass*))
(declare (type f64-5 x y z vx vy vz mass))
(loop for i fixnum from 0 below 5 do
(let ((xi (aref x i)) (yi (aref y i)) (zi (aref z i))
(vxi (aref vx i)) (vyi (aref vy i)) (vzi (aref vz i))
(mi (aref mass i)))
(declare (type double-float xi yi zi vxi vyi vzi mi))
(loop for j fixnum from (1+ i) below 5 do
(let* ((dx (- xi (aref x j)))
(dy (- yi (aref y j)))
(dz (- zi (aref z j)))
(dsq (+ (* dx dx) (* dy dy) (* dz dz)))
(mag (/ +dt+ (* dsq (sqrt dsq))))
(mj-mag (* (aref mass j) mag))
(mi-mag (* mi mag)))
(declare (type double-float dx dy dz dsq mag mj-mag mi-mag))
(decf vxi (* dx mj-mag))
(decf vyi (* dy mj-mag))
(decf vzi (* dz mj-mag))
(incf (aref vx j) (* dx mi-mag))
(incf (aref vy j) (* dy mi-mag))
(incf (aref vz j) (* dz mi-mag))))
(setf (aref vx i) vxi)
(setf (aref vy i) vyi)
(setf (aref vz i) vzi)))
(loop for i fixnum from 0 below 5 do
(incf (aref x i) (* +dt+ (aref vx i)))
(incf (aref y i) (* +dt+ (aref vy i)))
(incf (aref z i) (* +dt+ (aref vz i)))))
(values))
(defun energy ()
(let ((x *x*) (y *y*) (z *z*)
(vx *vx*) (vy *vy*) (vz *vz*)
(mass *mass*)
(e 0.0d0))
(declare (type f64-5 x y z vx vy vz mass)
(type double-float e))
(loop for i fixnum from 0 below 5 do
(incf e (* 0.5d0 (aref mass i)
(+ (* (aref vx i) (aref vx i))
(* (aref vy i) (aref vy i))
(* (aref vz i) (aref vz i)))))
(loop for j fixnum from (1+ i) below 5 do
(let* ((dx (- (aref x i) (aref x j)))
(dy (- (aref y i) (aref y j)))
(dz (- (aref z i) (aref z j))))
(declare (type double-float dx dy dz))
(decf e (/ (* (aref mass i) (aref mass j))
(sqrt (+ (* dx dx) (* dy dy) (* dz dz))))))))
e))
(defun main ()
(let ((args (list "nbody-lw.lisp" "50000000")))
(when (< (length args) 2)
(format *error-output* "Usage: nbody <iterations>~%")
(quit))
(let ((n (parse-integer (second args))))
(declare (type fixnum n))
(loop repeat n do (advance))
(format *error-output* "~,9F~%" (energy))
(quit))))
;;; When run as script, call main directly
(eval-when (:execute)
(main))
For immediate assistance, please email our customer support: [email protected]