|
12 | 12 | (define *blue-theme* (color-theme "lightblue" "blue" "navy")) |
13 | 13 | (define *green-theme* (color-theme "lightgreen" "green" "darkgreen")) |
14 | 14 |
|
15 | | -(define (double-transform) |
16 | | - ;; TODO: needs to be repr-aware |
17 | | - (define repr (get-representation* 'real)) |
| 15 | +(define (repr-transform repr) |
18 | 16 | (invertible-function |
19 | 17 | (compose (representation-repr->ordinal repr) (curryr ->flonum repr)) |
20 | 18 | (compose (representation-ordinal->repr repr) round))) |
21 | 19 |
|
22 | | -(define (double-axis) |
23 | | - (make-axis-transform (double-transform))) |
| 20 | +(define (repr-axis repr) |
| 21 | + (make-axis-transform (repr-transform repr))) |
24 | 22 |
|
25 | | -(define (power10-upto x) |
26 | | - (define ->repr (if (flag-set? 'precision 'double) real->double-flonum real->single-flonum)) |
| 23 | +(define (power10-upto x repr) |
27 | 24 | (if (= x 0) |
28 | 25 | '() |
29 | 26 | (reverse |
30 | 27 | (let loop ([power (round (/ (log x) (log 10)))]) |
31 | | - (define value (->repr (expt 10.0 power))) |
| 28 | + (define value (fl->repr (expt 10.0 power) repr)) |
32 | 29 | (if (= value 0) '() (cons value (loop (- power 1)))))))) |
33 | 30 |
|
34 | | -(define (possible-ticks min max) |
| 31 | +(define (possible-ticks min max repr) |
35 | 32 | ;; Either |
36 | 33 | ;; + 0 is between min and max |
37 | 34 | ;; + 0 is one of min and max (two cases) |
38 | 35 | ;; + min and max are on the same side of 0 (two cases) |
39 | 36 | (sort |
40 | 37 | (cond |
41 | | - [(< (* min max) 0) (append (map - (power10-upto (- min))) '(0.0) (power10-upto max))] |
42 | | - [(= min 0) (cons 0 (power10-upto max))] |
43 | | - [(= max 0) (append (map - (power10-upto (abs min))) '(0.0))] |
44 | | - [(> min 0) (set-subtract (power10-upto max) (power10-upto min))] |
45 | | - [(< max 0) (map - (set-subtract (power10-upto (abs min)) (power10-upto (abs max))))]) |
| 38 | + [(< (* min max) 0) (append (map - (power10-upto (- min) repr)) '(0.0) (power10-upto max repr))] |
| 39 | + [(= min 0) (cons 0 (power10-upto max repr))] |
| 40 | + [(= max 0) (append (map - (power10-upto (abs min) repr)) '(0.0))] |
| 41 | + [(> min 0) (set-subtract (power10-upto max repr) (power10-upto min repr))] |
| 42 | + [(< max 0) (map - (set-subtract (power10-upto (abs min) repr) (power10-upto (abs max) repr)))]) |
46 | 43 | <)) |
47 | 44 |
|
48 | 45 | (define (pick-spaced-indices necessary possible number) |
|
82 | 79 | (define stopper (if (null? necessary) 0 (apply max necessary))) |
83 | 80 | (car (argmin (λ (x) (+ (cdr x) (sqr (- (- possible 1) (caar x))))) (drop (vector->list final) stopper)))) |
84 | 81 |
|
85 | | -(define (choose-ticks min max) |
86 | | - (define possible (possible-ticks min max)) |
87 | | - |
| 82 | +(define (choose-ticks min max repr) |
| 83 | + (define possible (possible-ticks min max repr)) |
88 | 84 | (cond |
89 | 85 | [(< (length possible) 12) |
90 | 86 | ;; If there aren't enough possible big ticks, we fall back to the standard method |
91 | 87 | (append |
92 | 88 | (if (<= min 1.0 max) (list (pre-tick 1.0 #t)) '()) |
93 | 89 | (if (<= min 0.0 max) (list (pre-tick 0.0 #t)) '()) |
94 | 90 | (if (<= min -1.0 max) (list (pre-tick -1.0 #t)) '()) |
95 | | - ((ticks-layout (ticks-scale (linear-ticks #:number 6 #:base 10 #:divisors '(1 2 5)) (double-transform))) min max))] |
| 91 | + ((ticks-layout (ticks-scale (linear-ticks #:number 6 #:base 10 #:divisors '(1 2 5)) (repr-transform repr))) min max))] |
96 | 92 | [else |
97 | 93 | (define necessary (filter identity (map (curry index-of possible) '(1.0 0.0 -1.0)))) |
98 | 94 | (define major-indices (pick-spaced-indices necessary (length possible) 12)) |
99 | 95 | (for/list ([idx major-indices]) |
100 | 96 | (pre-tick (list-ref possible idx) #t))])) |
101 | 97 |
|
102 | | -(define (double-ticks) |
| 98 | +(define (repr-ticks repr) |
103 | 99 | (ticks |
104 | | - choose-ticks |
| 100 | + (curryr choose-ticks repr) |
105 | 101 | (λ (lft rgt pticks) |
106 | 102 | (for/list ([ptick pticks]) |
107 | 103 | (define val (pre-tick-value ptick)) |
|
155 | 151 | (y-tick-lines) |
156 | 152 | (error-points (map (const 1) pts) pts #:axis axis #:alpha 0))) |
157 | 153 |
|
158 | | -(define (with-herbie-plot #:title [title #f] thunk) |
| 154 | +(define (with-herbie-plot repr #:title [title #f] thunk) |
159 | 155 | (parameterize ([plot-width 800] [plot-height 300] |
160 | 156 | [plot-background-alpha 0] |
161 | | - [plot-x-transform (double-axis)] |
162 | | - [plot-x-ticks (double-ticks)] |
| 157 | + [plot-x-transform (repr-axis repr)] |
| 158 | + [plot-x-ticks (repr-ticks repr)] |
163 | 159 | [plot-x-tick-label-anchor 'top] |
164 | 160 | [plot-x-label #f] |
165 | 161 | [plot-x-far-axis? #t] |
|
177 | 173 | (if port |
178 | 174 | (lambda () (plot-file (cons (y-axis) renderers) port kind #:y-min 0 #:y-max bit-width)) |
179 | 175 | (lambda () (plot-pict (cons (y-axis) renderers) #:y-min 0 #:y-max bit-width)))) |
180 | | - (with-herbie-plot #:title title thunk)) |
| 176 | + (with-herbie-plot repr #:title title thunk)) |
181 | 177 |
|
182 | | -(define (with-alt-plot #:title [title #f] thunk) |
| 178 | +(define (with-alt-plot repr #:title [title #f] thunk) |
183 | 179 | (parameterize ([plot-width 800] [plot-height 800] |
184 | 180 | [plot-background-alpha 1] |
185 | | - [plot-x-transform (double-axis)] |
186 | | - [plot-x-ticks (double-ticks)] |
| 181 | + [plot-x-transform (repr-axis repr)] |
| 182 | + [plot-x-ticks (repr-ticks repr)] |
187 | 183 | [plot-x-tick-label-anchor 'top] |
188 | 184 | [plot-x-label #f] |
189 | 185 | [plot-x-far-axis? #t] |
190 | 186 | [plot-x-far-ticks no-ticks] |
191 | | - [plot-y-transform (double-axis)] |
192 | | - [plot-y-ticks (double-ticks)] |
| 187 | + [plot-y-transform (repr-axis repr)] |
| 188 | + [plot-y-ticks (repr-ticks repr)] |
193 | 189 | [plot-y-tick-label-anchor 'left] |
194 | 190 | [plot-y-label #f] |
195 | 191 | [plot-y-far-axis? #t] |
|
198 | 194 | [plot-y-label title]) |
199 | 195 | (thunk))) |
200 | 196 |
|
201 | | -(define (alt-plot #:port [port #f] #:kind [kind 'auto] #:title [title #f] . renderers) |
| 197 | +(define (alt-plot repr #:port [port #f] #:kind [kind 'auto] #:title [title #f] . renderers) |
202 | 198 | (define thunk |
203 | 199 | (lambda () (plot-file renderers port kind))) |
204 | | - (with-alt-plot #:title title thunk)) |
| 200 | + (with-alt-plot repr #:title title thunk)) |
205 | 201 |
|
206 | 202 | (define (errors-by x errs pts) |
207 | 203 | (sort (map (λ (pt err) (cons (apply x pt) err)) pts errs) < #:key car)) |
|
243 | 239 | (for/list ([i (in-range idx-min (+ idx-min bin-size))]) (vector-ref errs i))]) |
244 | 240 | <))))) |
245 | 241 |
|
246 | | -(define (error-avg errs pts #:axis [axis 0] #:vars [vars '()] |
| 242 | +(define (error-avg errs pts repr #:axis [axis 0] #:vars [vars '()] |
247 | 243 | #:color [color *blue-theme*] #:bin-size [bin-size 128]) |
248 | 244 | (define get-coord |
249 | 245 | (if (number? axis) |
250 | 246 | (λ x (list-ref x axis)) |
251 | 247 | (eval-prog `(λ ,vars ,axis) 'fl))) |
| 248 | + |
| 249 | + ; works for binary64, binary32 (probably not for posits) |
| 250 | + (define-values (maxbound minbound) |
| 251 | + (let ([hi (sub1 ((representation-repr->ordinal repr) (fl->repr +inf.0 repr)))] |
| 252 | + [lo (add1 ((representation-repr->ordinal repr) (fl->repr -inf.0 repr)))]) |
| 253 | + (values ((representation-ordinal->repr repr) hi) |
| 254 | + ((representation-ordinal->repr repr) lo)))) |
| 255 | + |
252 | 256 | (define eby (errors-by get-coord errs pts)) |
253 | 257 | (define histogram-f (histogram-function eby #:bin-size bin-size)) |
254 | 258 | (define (avg-fun x) |
255 | 259 | (define h (histogram-f x)) |
256 | 260 | (/ (apply + (vector->list h)) (vector-length h))) |
257 | | - ;; TODO: This is a weird hack in several ways, and ideally wouldn't exist |
258 | | - ;; TODO: This doesn't work in single-precision |
259 | | - (define-values (min max) |
| 261 | + (define-values (min* max*) ; plot requires finite bounds |
260 | 262 | (match* ((car (first eby)) (car (last eby))) |
261 | 263 | [(x x) (values #f #f)] |
262 | | - [(x y) (values (flmax (flnext -inf.0) x) (flmin (flprev +inf.0) y))])) |
263 | | - (function avg-fun min max |
264 | | - #:width 2 #:color (color-theme-fit color))) |
| 264 | + [(x y) (values (max minbound x) (min maxbound y))])) ; hence this |
| 265 | + (function avg-fun min* max* #:width 2 #:color (color-theme-fit color))) |
265 | 266 |
|
266 | 267 | (define (error-mark x-val) |
267 | 268 | (inverse (const x-val) #:color "gray" #:width 3)) |
|
282 | 283 | (define info (regime-info altn)) |
283 | 284 | (and info (sp-bexpr (car info)))) |
284 | 285 |
|
285 | | -(define (points->doubles pts repr) |
286 | | - (cond |
287 | | - [(or (real? (caar pts)) (complex? (caar pts))) pts] |
288 | | - [else |
289 | | - (map (curry map (curryr repr->fl repr)) pts)])) |
290 | | - |
291 | 286 | (define (make-axis-plot result out idx) |
292 | 287 | (define var (list-ref (test-vars (test-result-test result)) idx)) |
293 | 288 | (define split-var? (equal? var (regime-var (test-success-end-alt result)))) |
294 | 289 | (define repr (get-representation (test-output-prec (test-result-test result)))) |
295 | | - (define pts (points->doubles (test-success-newpoints result) repr)) |
| 290 | + (define pts (test-success-newpoints result)) |
296 | 291 | (herbie-plot |
297 | 292 | #:port out #:kind 'png |
298 | 293 | repr |
|
307 | 302 | ['b (values *blue-theme* test-success-end-error)])) |
308 | 303 |
|
309 | 304 | (define repr (get-representation (test-output-prec (test-result-test result)))) |
310 | | - (define pts (points->doubles (test-success-newpoints result) repr)) |
| 305 | + (define pts (test-success-newpoints result)) |
311 | 306 | (define err (accessor result)) |
312 | 307 |
|
313 | 308 | (herbie-plot |
314 | 309 | #:port out #:kind 'png |
315 | 310 | repr |
316 | 311 | (error-points err pts #:axis idx #:color theme) |
317 | | - (error-avg err pts #:axis idx #:color theme))) |
| 312 | + (error-avg err pts repr #:axis idx #:color theme))) |
318 | 313 |
|
319 | | -(define (make-alt-plots point-alt-idxs alt-idxs title out) |
| 314 | +(define (make-alt-plots point-alt-idxs alt-idxs title out result) |
320 | 315 | (define best-alt-point-renderers (best-alt-points point-alt-idxs alt-idxs)) |
321 | | - (alt-plot best-alt-point-renderers #:port out #:kind 'png #:title title)) |
| 316 | + (define repr (get-representation (test-output-prec (test-result-test result)))) |
| 317 | + (alt-plot best-alt-point-renderers repr #:port out #:kind 'png #:title title)) |
322 | 318 |
|
323 | 319 | (define (make-point-alt-idxs result) |
324 | 320 | (define repr (get-representation (test-output-prec (test-result-test result)))) |
|
328 | 324 | (define newexacts (test-success-newexacts result)) |
329 | 325 | (oracle-error-idx all-alt-bodies newpoints newexacts repr)) |
330 | 326 |
|
331 | | -(define (make-contour-plot point-colors var-idxs title out) |
| 327 | +(define (make-contour-plot point-colors var-idxs title out result) |
332 | 328 | (define point-renderers (herbie-ratio-point-renderers point-colors var-idxs)) |
333 | | - (alt-plot point-renderers #:port out #:kind 'png #:title title)) |
| 329 | + (define repr (get-representation (test-output-prec (test-result-test result)))) |
| 330 | + (alt-plot point-renderers repr #:port out #:kind 'png #:title title)) |
334 | 331 |
|
335 | 332 | #; |
336 | 333 | (define (make-plots result rdir profile? debug?) |
|
350 | 347 | (define alt-idxs (list i j)) |
351 | 348 | (define title (format "~a vs ~a" (list-ref vars j) (list-ref vars i))) |
352 | 349 | (open-file (- (+ j (* i (- (length vars)))) 1) #:type 'best-alts |
353 | | - make-alt-plots point-alt-idxs alt-idxs title) |
| 350 | + make-alt-plots point-alt-idxs alt-idxs title result) |
354 | 351 | (open-file (- (+ j (* i (- (length vars)))) 1) #:type 'contours |
355 | | - make-contour-plot point-colors alt-idxs title))) |
| 352 | + make-contour-plot point-colors alt-idxs title result))) |
356 | 353 |
|
357 | 354 | (for ([var (test-vars (test-result-test result))] [idx (in-naturals)]) |
358 | 355 | (when (> (length (remove-duplicates (map (curryr list-ref idx) (test-success-newpoints result)))) 1) |
|
0 commit comments