home *** CD-ROM | disk | FTP | other *** search
- Path: sparky!uunet!pmafire!mica.inel.gov!ux1!news.byu.edu!hamblin.math.byu.edu!sol.ctr.columbia.edu!usc!elroy.jpl.nasa.gov!ames!data.nas.nasa.gov!taligent!apple!cambridge.apple.com!bill@cambridge.apple.com
- From: bill@cambridge.apple.com (Bill St. Clair)
- Newsgroups: comp.lang.lisp.mcl
- Subject: Re: Double floats
- Message-ID: <9211061649.AA27464@cambridge.apple.com>
- Date: 6 Nov 92 17:53:18 GMT
- Sender: info-mcl-request@cambridge.apple.com
- Lines: 85
- Approved: comp.lang.lisp.mcl@Cambridge.Apple.C0M
- Full-Name: Bill St. Clair
- Original-To: millett@sbctri.sbc.com
- Original-Cc: info-mcl
-
- >I am tring to take a double-float number, break it down into 2 long
- >integers (high-word and low-word) to send over the network conforming to
- >the IEEE floating point standard. I also want to read 2 words from the
- >stream and make a double-float from them. Any Ideas? Symbolics has two
- >functions that do what I want: "si:dfloat-components: (double)" &
- >"si:%make-double: (high low)" Any way to do this with the mac?
- >
- >Thanks,
- >millett@sbctri.sbc.com
-
- MCL has a function that breaks a double float into 4 fixnums:
- high-mantissa, low-mantissa, exponent, and sign.
- It also has a function for putting these components back together again.
-
- ccl::fixnum-decode-float double-float
- ; decompose a double-float into fixnum size pieces
- ; returns 4 values
- ; hi is high 24 bits of mantissa (with the implied 1 in bit 25 if appropriate)
- ; lo is low 28 bits of mantissa (hi and lo are both right justified)
- ; exp is 11 bit exponent (the bits as they are - not unbiased; i.e. exp is >= 0)
- ; sign is 1 or -1
-
- ccl::make-float-from-fixnums hi lo exp sign
- ; make a float from hi - high 24 bits mantissa (ignore implied higher bit)
- ; lo - low 28 bits mantissa
- ; exp - take low 11 bits
- ; sign - sign(sign) => result
- ; hi result - 1 bit sign: 11 bits exp: 20 hi bits of hi arg
- ; lo result - 4 lo bits of hi arg: 28 lo bits of lo arg
- ; no error checks, no tweaks, no nuthin
-
- You can use these to make the integers (likely bignums) that you want:
-
- (defun dfloat-components (dfloat)
- (multiple-value-bind (hi lo exp sign) (ccl::fixnum-decode-float dfloat)
- (declare (fixnum hi lo exp sign))
- (values
- (+ (if (< sign 0) (ash 1 31) 0)
- (ash exp (- 31 11))
- (ash (logand hi #xfffff0) (- 20 24)))
- (+ (ash (logand hi #xf) (- 32 4))
- lo))))
-
- (defun make-double (high low)
- (ccl::make-float-from-fixnums
- (+ (ash (logand high #xfffff) 4)
- (ash low -28))
- (logand low #xfffffff)
- (logand (ash high -20) #x7ff)
- (if (logbitp 31 high) -1 1)))
-
- This is not very efficient.
- The following LAP versions are more efficient
- (though dfloat-components still conses bignums):
-
- (in-package :ccl)
-
- (eval-when (:compile-toplevel :execute)
- (require "LAPMACROS") ; lap-inline
- (require "LISPEQU")) ; $floathi
-
- (defun dfloat-components (dfloat)
- (setq dfloat (require-type dfloat 'double-float))
- (let (hi lo)
- (lap-inline ()
- (:variable dfloat hi lo)
- (move.l (varg dfloat) atemp0)
- (move.l (atemp0 $floathi) arg_z)
- (jsr_subprim $sp-mklong)
- (move.l acc (varg hi))
- (move.l (varg dfloat) atemp0)
- (move.l (atemp0 (+ $floathi 4)) arg_z)
- (jsr_subprim $sp-mklong)
- (move.l acc (varg lo)))
- (values hi lo)))
-
- (defun make-float (high low)
- (lap-inline ()
- (:variable high low)
- (move.l (varg high) arg_z)
- (jsr_subprim $sp-getxlong)
- (move.l acc arg_y)
- (move.l (varg low) arg_z)
- (jsr_subprim $sp-getxlong)
- (jsr_subprim $sp-makefloat)))
-