From mboxrd@z Thu Jan 1 00:00:00 1970 Path: main.gmane.org!not-for-mail From: "Ehud Karni" Newsgroups: gmane.emacs.sources,gmane.emacs.help Subject: Re: IEEE-754 binary rep functions Date: Wed, 23 Oct 2002 16:19:53 +0200 Organization: Mivtach-Simon Insurance agencies Sender: gnu-emacs-sources-admin@gnu.org Message-ID: <200210231419.g9NEJrgi031692@beta.mvs.co.il> References: <3DB4EE47.4D801FAC@era.ericsson.se> Reply-To: ehud@unix.mvs.co.il NNTP-Posting-Host: main.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=iso-8859-8 Content-Transfer-Encoding: 7bit X-Trace: main.gmane.org 1035382736 16681 80.91.224.249 (23 Oct 2002 14:18:56 GMT) X-Complaints-To: usenet@main.gmane.org NNTP-Posting-Date: Wed, 23 Oct 2002 14:18:56 +0000 (UTC) Cc: "Gnu Emacs help" , " Gnu Emacs source code" Return-path: Original-Received: from monty-python.gnu.org ([199.232.76.173]) by main.gmane.org with esmtp (Exim 3.35 #1 (Debian)) id 184MLV-0004Kc-00 for ; Wed, 23 Oct 2002 16:18:54 +0200 Original-Received: from localhost ([127.0.0.1] helo=monty-python.gnu.org) by monty-python.gnu.org with esmtp (Exim 4.10) id 184MLz-0004VD-00; Wed, 23 Oct 2002 10:19:23 -0400 Original-Received: from list by monty-python.gnu.org with tmda-scanned (Exim 4.10) id 184ML0-0003qH-00 for gnu-emacs-sources@gnu.org; Wed, 23 Oct 2002 10:18:22 -0400 Original-Received: from mail by monty-python.gnu.org with spam-scanned (Exim 4.10) id 184MKx-0003me-00 for gnu-emacs-sources@gnu.org; Wed, 23 Oct 2002 10:18:22 -0400 Original-Received: from unix.simonwiesel.co.il ([192.114.178.12] helo=unix.mvs.co.il) by monty-python.gnu.org with esmtp (Exim 4.10) id 184MKt-0003j1-00; Wed, 23 Oct 2002 10:18:15 -0400 Original-Received: from beta.mvs.co.il (beta [10.253.0.3]) by unix.mvs.co.il (8.11.6/8.11.6) with ESMTP id g9NEI9h32230; Wed, 23 Oct 2002 16:18:09 +0200 Original-Received: from beta.mvs.co.il (localhost [127.0.0.1]) by beta.mvs.co.il (8.12.5/8.12.5) with ESMTP id g9NEJsed031698; Wed, 23 Oct 2002 16:19:54 +0200 Original-Received: (from ehud@localhost) by beta.mvs.co.il (8.12.5/8.12.5/Submit) id g9NEJrgi031692; Wed, 23 Oct 2002 16:19:53 +0200 X-Authentication-Warning: beta.mvs.co.il: ehud set sender to ehud@unix.mvs.co.il using -f Original-To: "Heinz Eriksson" In-reply-to: <3DB4EE47.4D801FAC@era.ericsson.se> (message from Heinz Eriksson on Tue, 22 Oct 2002 08:20:55 +0200) X-Mailer: Emacs 21.2.91.3 rmail (send-msg 1.106) Errors-To: gnu-emacs-sources-admin@gnu.org X-BeenThere: gnu-emacs-sources@gnu.org X-Mailman-Version: 2.0.11 Precedence: bulk List-Help: List-Post: List-Subscribe: , List-Id: GNU Emacs source code postings and patches List-Unsubscribe: , List-Archive: Xref: main.gmane.org gmane.emacs.sources:200 gmane.emacs.help:2855 X-Report-Spam: http://spam.gmane.org/gmane.emacs.help:2855 On Tue, 22 Oct 2002 08:20:55 +0200, Heinz Eriksson wrote: > > How would one write elisp functions to convert > to and from the binary representation of a > IEEE-754 (single precision) floating point number? > I don't care about NaN etc. Bellow is my code for the conversions you asked for. Save the code to a file "IEEE-754.el" and load it into your Emacs session using `load-file'. To convert from number to hex representation do: (setq HEX-VAL (IEEE-float-2-hex -5.678e+9)) To convert from hex representation to floating number do: (setq FLT-VAL (IEEE-hex-2-float "4fed0123")) Ehud. ;; IEEE-754.el - convert 32 bit floating number to/from its hex ;; (big-endian) representation according to IEEE-754 ;; ;; These functions deals correctly with 0 and -/+ infinity ;; Both kind of NaN (not a number) are ignored ;; ;; written by Ehud Karni ;; References: http://www.cs.berkeley.edu/~ejr/projects/754/ ;; http://research.microsoft.com/~hollasch/cgindex/coding/ieeefloat.html ;; http://www.cs.berkeley.edu/~wkahan/ieee754status/ieee754.ps ;; Conversion on-line: ;; http://babbage.cs.qc.edu/courses/cs341/IEEE-754.html ;; History of IEEE-754 ;; http://www.cs.berkeley.edu/~wkahan/ieee754status/754story.html ;; the value of IEEE-754 float is: ;; Normal number (normalized) ;; ( 1 - 2*sign ) * 2 ** (exp - exp-bias) * ( 1 + mantissa / mantissa-divisor ) ;; Very small number (De-normalized) ;; ( 1 - 2*sign ) * 2 ** (1 - exp-bias ) * ( mantissa / mantissa-divisor ) ;; ;; for a 32 bit float (sign/exp/mantissa bits = 1/8/23) ===> ;; ( 1 - 2*sign ) * 2 ** (exp - 127) * ( 1 + mantissa / 8388608 ) ;; for a 64 bit float (sign/exp/mantissa bits = 1/11/52) ===> ;; ( 1 - 2*sign ) * 2 ** (exp - 1023) * ( 1 + mantissa / 4503599627370496 ) (defvar IEEE-sign-mlt 128 "multiplier for sign") ; 1 bits (defvar IEEE-exp-bias 127 "exponent bias for float" ; 8 bits (defvar IEEE-mantissa-divisor ?\x800000 "mantissa divisor for float") ; 23 bits (defvar IEEE-float-mantissa-divisor (/ 1.0 (float IEEE-mantissa-divisor)) "floated 1 / mantissa divisor") (defun IEEE-float-2-hex (FNUM) "Convert a floating point number FNUM to 8 Hex digits string (big endian)" (interactive "nEnter float to convert: ") (or (floatp-safe FNUM) (setq FNUM (float FNUM))) (let ((IEEE-sign 0) (IEEE-exp 0) (IEEE-mantissa 0) hex ) (and (< FNUM 0) ; negative (setq IEEE-sign IEEE-sign-mlt) ; yes, sign=1 (* 2**7) (setq FNUM (- FNUM))) ; negate (abs) it (cond ((= FNUM 0)) ; Zero - we all set ((= FNUM 1e+INF) ; infinite ? (setq IEEE-exp IEEE-exp-bias)) ; exp = max, mantissa = 0 (t ;; real float (setq IEEE-exp (floor (log FNUM 2.0))) ; exponent [ log 2 FNUM ] - integer (if (<= IEEE-exp (- IEEE-exp-bias)) ; check for De-normalized number (setq IEEE-exp 0 ; really - IEEE-exp-bias IEEE-mantissa (truncate (* IEEE-mantissa-divisor 0.5 FNUM (expt 2.0 IEEE-exp-bias)))) ;; normal float (setq IEEE-mantissa (truncate (* IEEE-mantissa-divisor (- (/ FNUM (expt 2.0 IEEE-exp)) 1)))) (setq IEEE-exp (+ IEEE-exp IEEE-exp-bias))) ;; offset-ed exp )) (setq hex (format "%02X%06X" (+ IEEE-sign (/ IEEE-exp 2)) (+ IEEE-mantissa (* (% IEEE-exp 2) IEEE-mantissa-divisor)))) ;; (message "Float=%f sign=%d, exp=%d, mant=%d HEX=%s" ;; FNUM IEEE-sign IEEE-exp IEEE-mantissa hex) hex)) (defun IEEE-hex-2-float (HEX) "Convert an 8 Hex digits string (big endian) to floating point number" (interactive "sEnter hex value (8 hex digits): ") (if (or (not (stringp HEX)) (/= (length HEX) 8) (string-match "[^0-9a-fA-F]" HEX)) (error "Arg must be a string of EXACTLY 8 hex (1-8, a-f, A-F) digits")) (let ((S-EXP (string-to-number (substring HEX 0 2) 16)) (MANTISSA (string-to-number (substring HEX 2) 16)) (RSLT 1) IEEE-sign IEEE-exp IEEE-mantissa ) (setq IEEE-mantissa (logior MANTISSA IEEE-mantissa-divisor)) ; always set upper bit (if (= IEEE-mantissa IEEE-mantissa-divisor) ; = --> zero mantissa, check special cases (cond ((string-equal HEX "00000000") (setq RSLT (float 0))) ; Zero ((string-equal HEX "3F800000") (setq RSLT 1e+INF)) ; + infinity ((string-equal HEX "BF800000") (setq RSLT -1e+INF)) ; - infinity )) (if (/= RSLT 1) RSLT ; special cases (0, infinity) (setq IEEE-sign (ash S-EXP -7)) ; shift right 7 bits (setq IEEE-exp (+ (ash (% S-EXP IEEE-sign-mlt) 1) ; shift (part) exp 1 (ash MANTISSA -23))) ; 1 bit from mantissa (if (= IEEE-exp 0) ; De-normalized ? (setq IEEE-mantissa (ash (logxor IEEE-mantissa IEEE-mantissa-divisor) 1))) ; clear upper bit ;; (message "Hex=%s sign=%d, exp=%d, mant=%d" ;; HEX IEEE-sign IEEE-exp IEEE-mantissa) (* ; result float (- 1 IEEE-sign IEEE-sign) ; sign (expt 2.0 (- IEEE-exp IEEE-exp-bias)) ; 2 ** exponent (un-biased) (float IEEE-mantissa) ; mantissa part IEEE-float-mantissa-divisor ; 1 / mantissa divisor )))) ;; For test do (note: the re-computed float is NOT rounded) ;; (IEEE-hex-2-float (IEEE-float-2-hex 123.456)) ;; ---------------------- IEEE-754.el ends here ----------------------- -- Ehud Karni Tel: +972-3-7966-561 /"\ Mivtach - Simon Fax: +972-3-7966-667 \ / ASCII Ribbon Campaign Insurance agencies (USA) voice mail and X Against HTML Mail http://www.mvs.co.il FAX: 1-815-5509341 / \ mailto:ehud@unix.mvs.co.il Better Safe Than Sorry