2013/4/24 Bradley Lucier lucier@math.purdue.edu
OK, data is good.
Here is what Gambit expands your code to, with some annotations:
heine:~/Downloads> gsc -c -expansion conversion.scm Expansion:
(define noop (lambda () #!void))
The following implies that gsc could expand (floor n) better as:
(cond ((fixnum? n) n) ((and ('#<procedure #2 ##flonum?> n) ('#<procedure #3 ##flfinite?> n)) ('#<procedure #4 ##flfloor> n)) (else ('#<procedure #5 floor> n))))
and it could expand inexact->exact better (after defining flfixnum?) as
(cond ((fixnum? n) n) ((and (flonum? n) (flinteger? n) (flfixnum? n)) (flonum->fixnum n)) (else (<inexact->exact> n))
Wait, is this a feature suggestion for Gambit, did I understand you right by that?
(As in, currently Gambit expands it another way and now you suggest this particular way that you've given here)
(define ->integer (lambda (n) (lambda () (let ((temp.5 (if (and ('#<procedure #2 ##flonum?> n) ('#<procedure #3 ##flfinite?> n)) ('#<procedure #4 ##flfloor> n) ('#<procedure #5 floor> n)))) (if ('#<procedure #6 ##fixnum?> temp.5) temp.5 ('#<procedure #7 inexact->exact> temp.5))))))
(define ->flonum (lambda (n) (lambda () (if ('#<procedure #6 ##fixnum?> n) ('#<procedure #8 ##fl<-fx> n) (if ('#<procedure #2 ##flonum?> n) n ('#<procedure #9 exact->inexact> n))))))
This following machinery seems pretty heavy. I'd suggest
(define (test t #!optional (seconds 1.)) (let loop ((n 1)) (let ((start-time (cpu-time))) (do ((i 0 (fx+ i 1))) ((fx= i n)) (t)) (let ((end-time (cpu-time))) (if (<= seconds (fl- end-time start-time)) (pp (/ n (fl- end-time start-time))) (loop (fx* n 2)))))))
(define test (lambda (t #!optional (seconds 5)) (let ((at ('#<procedure #10 ##box> 0))) (let ((th (thread-start! (make-thread (lambda () (letrec ((loop (lambda (t at) (let ((begin-temp.1 (t))) (let ((begin-temp.0 ('#<procedure #11 ##set-box!> at (let ((temp.7 ('#<procedure #12 ##unbox> at))) (if ('#<procedure #6 ##fixnum?> temp.7) (let ((temp.9 ('#<procedure #13 ##fx+?> temp.7 1))) (if temp.9 temp.9 ('#<procedure #14 fx+> temp.7 1))) ('#<procedure #14 fx+> temp.7 1)))))) (loop t at)))))) (loop t at))))))) (let ((begin-temp.3 (thread-sleep! seconds))) (let ((r ('#<procedure #12 ##unbox> at))) (let ((begin-temp.2 (thread-terminate! th))) (let ((temp.12 (if (and ('#<procedure #2 ##flonum?> seconds) ('#<procedure #2 ##flonum?> r)) ('#<procedure #15 ##fl/> r seconds) ('#<procedure #16 /> r seconds)))) (if ('#<procedure #6 ##fixnum?> temp.12) ('#<procedure #8 ##fl<-fx> temp.12) (if ('#<procedure #2 ##flonum?> temp.12) temp.12 ('#<procedure #9 exact->inexact> temp.12)))))))))))
With that, my rates are (first for void, then the four ->integer, then the four ->flonum):
76082403.02475469
18077766.69130593 2113932.395354323 12632656.242117403 1560283.434666285
34377410.006859235 69323006.15509051 1230645.7282318561 69180045.37858963
And, with (declare (not safe)) I get
105510445.88390666
18807367.927219782 2444080.701261633 13230418.609566122 1569627.036643679
47124065.98183112 92942772.26488659 1327228.230636181 92942772.26488681
Basically, nice numbers!
Numbers that are in the millions are good really.
I'd love to see the flonum to integer speed a bit higher (yellow above), I mean in C that's just double d; int i = (int) d; .
I tried it out in C and got 47,619,047 per second, code below.
Now, Gambit does lots of typechecking and boxing and stuff, though shouldn't like 5-10 million per second be reachable?
That I got 10-50 million per second of the other operations that do basically the same thing as this in Gambit led me to think that there might be some other definition of |->integer| that could get to this result, though not clear right now what that definition would be.
Addressed this because I thought it's like a generally relevant thing.
Brgds
C test:
#include <stdio.h> #include <stdlib.h>
int main() { double d = (double)rand()/100.0; int x; int i; for (i = 0; i < 1000000000; i++) { x = (int) d; } }
g++ cfile.c; time ./a.out