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 :)
Great!
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