File: fbench.scm

package info (click to toggle)
snd 26.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 44,044 kB
  • sloc: ansic: 291,996; lisp: 260,569; ruby: 71,134; sh: 3,293; fortran: 2,342; csh: 1,067; cpp: 294; makefile: 294; python: 87; xml: 27; javascript: 1
file content (239 lines) | stat: -rw-r--r-- 9,374 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
;;;  John Walker's Floating Point Benchmark, derived from...
;;;
;;;  Marinchip Interactive Lens Design System
;;;
;;;  By John Walker
;;;     http://www.fourmilab.ch/
;;;
;;;  This program may be used, distributed, and modified freely as
;;;  long as the origin information is preserved.
;;;
;;;  This is a complete optical design raytracing algorithm,
;;;  stripped of its user interface and recast into Common Lisp.
;;;  It not only determines execution speed on an extremely
;;;  floating point (including trig function) intensive
;;;  real-world application, it checks accuracy on an algorithm
;;;  that is exquisitely sensitive to errors.  The performance of
;;;  this program is typically far more sensitive to changes in
;;;  the efficiency of the trigonometric library routines than the
;;;  average floating point program.
;;;
;;;  Ported from the C language implementation in September 2005
;;;  by John Walker.
;;;
;;;  Ported to s7 20-May-2019

;;      Wavelengths of standard spectral lines in Angstroms
(define spectral-line
  '(( A-line . 7621.0 )	        ; A
    ( B-line . 6869.955 )       ; B
    ( C-line . 6562.816 )       ; C
    ( D-line . 5895.944 )       ; D
    ( E-line . 5269.557 )       ; E
    ( F-line . 4861.344 )       ; F
    ( Gprime-line . 4340.477 )  ; G'
    ( H-line . 3968.494 )))     ; H

(define D-light (cdr (assq 'D-line spectral-line)))
(define C-light (cdr (assq 'C-line spectral-line)))
(define F-light (cdr (assq 'F-line spectral-line)))

;;      The test case used in this program is the design for a 4 inch
;;      f/12 achromatic telescope objective used as the example in Wyld's
;;      classic work on ray tracing by hand, given in Amateur Telescope
;;      Making, Volume 3 (Volume 2 in the 1996 reprint edition).
(define testcase
  '(( 27.05 1.5137 63.6 0.52 )
    ( -16.68 1 0 0.138 )
    ( -16.68 1.6164 36.7 0.38 )
    ( -78.1 1 0 0 )))

(define default-iteration-count 100000)

;;      Reference results.  These happen to be derived from a
;;      run on Microsoft Quick BASIC on the IBM PC/AT.
(define reference-results
  '("   Marginal ray          47.09479120920   0.04178472683"
    "   Paraxial ray          47.08372160249   0.04177864821"
    "Longitudinal spherical aberration:        -0.01106960671"
    "    (Maximum permissible):                 0.05306749907"
    "Offense against sine condition (coma):     0.00008954761"
    "    (Maximum permissible):                 0.00250000000"
    "Axial chromatic aberration:                0.00448229032"
    "    (Maximum permissible):                 0.05306749907"))

(define current-surfaces 0)
(define paraxial 0)
(define clear-aperture 0)
(define aberr-lspher 0)
(define aberr-osc 0)
(define aberr-lchrom 0)
(define max-lspher 0)
(define max-osc 0)
(define max-lchrom 0)
(define radius-of-curvature 0.0)
(define object-distance 0.0)
(define ray-height 0)
(define axis-slope-angle 0)
(define from-index 0)
(define to-index 0)

;;      Calculate passage through surface
;;
;;      If the variable paraxial is 1, the trace through the
;;      surface will be done using the paraxial approximations.
;;      Otherwise, the normal trigonometric trace will be done.
;;
;;      This subroutine takes the following global inputs:
;;
;;      radius-of-curvature     Radius of curvature of surface
;;                              being crossed.  If 0, surface is
;;                              plane.
;;
;;      object-distance         Distance of object focus from
;;                              lens vertex.  If 0, incoming
;;                              rays are parallel and
;;                              the following must be specified:
;;
;;      ray-height              Height of ray from axis.  Only
;;                              relevant if $object-distance == 0
;;
;;      axis-slope-angle        Angle incoming ray makes with axis
;;                              at intercept
;;
;;      from-index              Refractive index of medium being left
;;
;;      to-index                Refractive index of medium being
;;                              entered.
;;
;;      The outputs are the following global variables:
;;
;;      object-distance         Distance from vertex to object focus
;;                              after refraction.
;;
;;      axis-slope-angle        Angle incoming ray makes with axis
;;                              at intercept after refraction.

(define (transit-surface)
  (let ((iang-sin 0))
    (if (= paraxial 1)
	(if (= radius-of-curvature 0.0)
	    (begin
	      (set! object-distance (* object-distance (/ to-index from-index)))
	      (set! axis-slope-angle (* axis-slope-angle (/ from-index to-index))))
	    (begin
	      (if (= object-distance 0.0)
		  (begin
		    (set! axis-slope-angle 0.0)
		    (set! iang-sin (/ ray-height radius-of-curvature)))
		  (set! iang-sin (* (/ (- object-distance radius-of-curvature) radius-of-curvature) axis-slope-angle)))
	      (let ((rang-sin (* (/ from-index to-index) iang-sin))
		    (old-axis-slope-angle axis-slope-angle))
		(set! axis-slope-angle (- (+ axis-slope-angle iang-sin) rang-sin))
		(if (not (= object-distance 0.0))
		    (set! ray-height (* object-distance old-axis-slope-angle)))
		(set! object-distance (/ ray-height axis-slope-angle)))))
	(if (= radius-of-curvature 0.0)
	    (let ((rang (- (asin (* (/ from-index to-index) (sin axis-slope-angle))))))
	      (set! object-distance (/ (* object-distance to-index (cos rang)) (* from-index (cos axis-slope-angle))))
	      (set! axis-slope-angle (- rang)))
	    (begin
	      (if (= object-distance 0.0)
		  (begin
		    (set! axis-slope-angle 0.0)
		    (set! iang-sin (/ ray-height radius-of-curvature)))
		  (set! iang-sin (* (/ (- object-distance radius-of-curvature) radius-of-curvature) (sin axis-slope-angle))))
	      (let ((iang (asin iang-sin))
		    (rang-sin (* (/ from-index to-index) iang-sin))
		    (old-axis-slope-angle axis-slope-angle))
		(set! axis-slope-angle (+ axis-slope-angle (- iang (asin rang-sin))))
		(let ((sagitta (sin (/ (+ old-axis-slope-angle iang) 2.0))))
		  (set! sagitta (* (* 2 radius-of-curvature) (* sagitta sagitta)))
		  (set! object-distance (+ (/ (* radius-of-curvature (sin (+ old-axis-slope-angle iang))) (tan axis-slope-angle)) sagitta)))))))))

;;	Perform ray trace in specific spectral line
(define (trace-line line ray-h)
  (set! object-distance 0.0)
  (set! ray-height ray-h)
  (set! from-index 1)
  (for-each (lambda (surface)
	      (set! radius-of-curvature (car surface))
	      (set! to-index (cadr surface))
	      (if (> to-index 1)
		  (set! to-index (+ to-index (/ (* (- D-light line) (- (cadr surface) 1)) 
						(* (- C-light F-light) (caddr surface))))))
	      (transit-surface)
	      (set! from-index to-index)
	      (if (cdr surface)
		  (set! object-distance (- object-distance (cadddr surface)))))
	    testcase))

;;	Set parameters for the design to be traced
(set! clear-aperture 4)
(define clear-aperture/2 (/ clear-aperture 2))
(set! current-surfaces 4)

(define (fbench iteration-count)
  (let ((od-sa ()))
    (do ((iteration 0 (+ iteration 1)))
	((> iteration iteration-count))
      (set! od-sa ())
      (do ((jp 0 (+ jp 1)))
	  ((> jp 1))
	;;  Do main trace in D light
	(set! paraxial jp)
	(trace-line D-light clear-aperture/2)
	;; (set! od-sa (append od-sa (list (list object-distance axis-slope-angle)))) ; yikes!
	(set! od-sa (cons (list object-distance axis-slope-angle) od-sa)))
      (set! od-sa (reverse! od-sa))
      
      (set! paraxial 0)
      
      ;;	Trace marginal ray in C
      (trace-line C-light clear-aperture/2)
      (let ((od-cline object-distance))
	
	;;	Trace marginal ray in F
	(trace-line F-light clear-aperture/2)
	(set! aberr-lspher (- (caadr od-sa) (caar od-sa)))
	(set! aberr-osc (- 1 (/ (* (caadr od-sa) (cadadr od-sa)) (* (sin (cadar od-sa)) (caar od-sa)))))
	(set! aberr-lchrom (- object-distance od-cline))
	(set! max-lspher (sin (cadar od-sa)))
	  
	;;  D light
	(set! max-lspher (/ 0.0000926 (* max-lspher max-lspher)))
	(set! max-osc 0.0025)
	(set! max-lchrom max-lspher)))
    
    (let ((results
	   (list
	    (format #f "   Marginal ray          ~14,11F  ~14,11F" (caar od-sa) (cadar od-sa))
	    (format #f "   Paraxial ray          ~14,11F  ~14,11F" (caadr od-sa) (cadadr od-sa))
	    (format #f "Longitudinal spherical aberration:      ~16,11F" aberr-lspher)
	    (format #f "    (Maximum permissible):              ~16,11F" max-lspher)
	    (format #f "Offense against sine condition (coma):  ~16,11F" aberr-osc)
	    (format #f "    (Maximum permissible):              ~16,11F" max-osc)
	    (format #f "Axial chromatic aberration:             ~16,11F" aberr-lchrom)
	    (format #f "    (Maximum permissible):              ~16,11F" max-lchrom))))
      
      (unless (equal? results reference-results)
	(do ((errors 0)
	     (received results (cdr received))
	     (expected reference-results (cdr expected))
	     (line 1 (+ line 1)))
	    ((null? received)
	     (format #t "~D error~A in results.~%" errors (if (> errors 1) "s" ""))) 
	  (unless (equal? (car expected) (car received))
	    (set! errors (+ errors 1))
	    (format () "Error in results in line ~D...~%" line)
	    (format () "Expected: ~A~%" (car expected))
	    (format () "Received: ~A~%" (car received))))))))


(fbench 50000)
;(fbench 1)

(when (> (*s7* 'profile) 0)
  (show-profile 200))
(exit)