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:
double d = (double)rand()/100.0;
for (i = 0; i < 1000000000; i++) {
g++ cfile.c; time ./a.out