[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Converting floats to fixnums



At 17:24 11/28/92 -0500, Guillaume Cartier wrote:
>Hello all MCL'ers,
>
>  I am developing a software in which it is vital that I can
>  convert a float into a fixnum in the fastest way possible and
>  with no memory allocation.
>
>  ROUND, FLOOR and company all return a second float value
>  that I don't need and are relatively slow.
>
>  Any idea? Internal undocumented stuff is ok with me...
>
>PS: The method used to obtain the fixnum (i.e. rounding, flooring,
>    truncating, ...) is not important.
>
>Any answer will be well appreciated.

These won't be quite as fast as assuming the arg is a float and
doing the appropriate floating point stuff, but they are more
general, and less complicated for me to figure out. (ifloor 1.5)
takes 56 microseconds on my fx. If that is still too slow, and
you can tell me which rounding mode you want (floor, ceiling, truncate,
or round), I may be able to provide a faster version.

-----------------------------------------------------------------------

; float->integer.lisp
;
; quotient only versions of truncate, floor, ceiling, & round.
; These don't cons unless the result is a bignum.
; Use undocumented internals of MCL's implementation which may
; change in a future release.

(in-package :ccl)

(export '(itruncate ifloor iceiling iround))

(eval-when (:compile-toplevel :execute)
  (require "LAPMACROS"))

(defun itruncate (number &optional divisor)
  (lap
    (if# (eq arg_z nilreg) (move.l '1 arg_z))
    (moveq 1 da)                        ; truncate
    (moveq 1 db)                        ; quotient only
    (jsr #'%%numdiv)
    (movereg arg_y acc)
    (lfret)))

(defun ifloor (number &optional divisor)
  (lap
    (if# (eq arg_z nilreg) (move.l '1 arg_z))
    (moveq 3 da)                        ; floor
    (moveq 1 db)                        ; quotient only
    (jsr #'%%numdiv)
    (movereg arg_y acc)
    (lfret)))

(defun iceiling (number &optional divisor)
  (lap
    (if# (eq arg_z nilreg) (move.l '1 arg_z))
    (moveq 5 da)                        ; ceiling
    (moveq 1 db)                        ; quotient only
    (jsr #'%%numdiv)
    (movereg arg_y acc)
    (lfret)))

(defun iround (number &optional divisor)
  (lap
    (if# (eq arg_z nilreg) (move.l '1 arg_z))
    (moveq 7 da)                        ; round
    (moveq 1 db)                        ; quotient only
    (jsr #'%%numdiv)
    (movereg arg_y acc)
    (lfret)))