Hi Brad,
Yeah found ##flonum.->exact-int at the same time as you wrote.
(From tests, for reference, floor is ~15 million per sec always, while inexact->exact takes time for flonums and rationals and for the others is a noop.)
So a performant, general definition goes:
(define ->integer
(let ((fixnum-max-as-flonum (##fixnum->flonum ##max-fixnum)))
(lambda (n)
(declare (not safe))
(cond
((##fixnum? n) n)
((##bignum? n) n) ; Bignums are integer by definition
((##flonum? n) (if (##fl< n fixnum-max-as-flonum)
(##flonum.->fixnum n)
(##flonum.->exact-int n)))
((##ratnum? n) (##inexact->exact (##floor n)))
(else (error "Complex numbers not supported"))))))
> (->integer 5)
5
> (->integer 5.)
5
> (->integer 10/7)
1
> (->integer 1e25)
10000000000000000905969664
> (->integer 1000000000000000000000000)
1000000000000000000000000
Note that it is a completely safe procedure, even while it has (declare (not safe)) as to make compilation more efficient.
Benchmark:
(->integer 5) 41,862,119
(->integer 5.) 26,032,509
(->integer 536870912.) 2,625,793 (this is the max flonum + 1, as a fixnum)
(->integer 1e15) 1,097,751
(->integer 1e25) 643,797
(->integer 10/7) 5,134,476
(->integer 1000000000000000000000000) 41,216,439
Well, this is as good as it goes then :)
Yes you certainly have a point about the semantics of Gambit/Scheme numerical operations; do you recommend any particular document for really getting them?
Thanks,
Mikael
2013/4/25 Bradley Lucier
<lucier@math.purdue.edu>
On Apr 24, 2013, at 5:17 PM, Mikael wrote:
>
> 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; .
If you want to do that, you can do (##flonum->fixnum d) (undocumented, internal function):
> (##flonum->fixnum 5.5)
5
> (##flonum->fixnum -5.5)
-5
But that isn't floor; that doesn't work for large flonums.
If you want C, you can write C in Gambit. Many people don't understand the semantics of the numerical operations in Scheme generally, or in Gambit in particular.
Brad