pax_global_header00006660000000000000000000000064131476272110014516gustar00rootroot0000000000000052 comment=566b51a005e81ff618554b9b2f0b795d3b29398d ieee-floats-20170830-git/000077500000000000000000000000001314762721100147425ustar00rootroot00000000000000ieee-floats-20170830-git/LICENSE000066400000000000000000000015521314762721100157520ustar00rootroot00000000000000Copyright (c) Marijn Haverbeke, marijnh@gmail.com This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. ieee-floats-20170830-git/doc/000077500000000000000000000000001314762721100155075ustar00rootroot00000000000000ieee-floats-20170830-git/doc/index.html000066400000000000000000000077731314762721100175220ustar00rootroot00000000000000 IEEE Floats

IEEE Floats

IEEE-Floats provides a way of converting values of type float and double-float to and from their binary representation as defined by IEEE 754 (which is commonly used by processors and network protocols).

The library defines encoding and decoding functions for the common 32-bit and 64-bit formats, and a macro for defining similar functions for other formats. The default functions do not detect the special cases for NaN or infinity, but functions can be generated which do, in which case the keywords :not-a-number, :positive-infinity, and :negative-infinity are used to represent them.

Download and installation

IEEE-Floats is released under a BSD-style license. The latest release can be downloaded from https://github.com/marijnh/ieee-floats/zipball/current.

A git repository with the most recent changes can be checked out with:

  
    > git clone https://github.com/marijnh/ieee-floats.git
  

Or look at it on github.

If you have Quicklisp installed, you can run:

  
    CL-USER> (ql:quickload :ieee-floats)
    

Running tests

Tests are available from ASDF:

  
    CL-USER> (asdf:test-system :ieee-floats)
  

Alternatively, you can run tests manually, provided you first load the ieee-floats-tests system.

  
    CL-USER> (asdf:load-system :ieee-floats-tests)
    ...
    CL-USER> (fiveam:run! :ieee-floats)
    ..................................................
    Did 50 checks.
    Pass: 50 (100%)
    Skip: 0 ( 0%)
    Fail: 0 ( 0%)

    NIL
  

Support and mailing lists

The ieee-floats-devel mailing list can be used for any questions, discussion, bug-reports, patches, or anything else relating to this library. You can also e-mail the author/maintainer, Marijn Haverbeke, directly.

Reference

function encode-float32 (float) => integer

Convert a float into its 32-bit binary representation.

function decode-float32 (integer) => float

Create a float from a 32-bit binary representation.

function encode-float64 (float) => integer

Convert a float into its 64-bit binary representation.

function decode-float64 (integer) => double-float

Create a float from a 64-bit binary representation.

macro make-float-converters (encoder-name decoder-name exponent-bits significand-bits support-nan-and-infinity-p)

Writes an encoder and decoder function for floating point numbers with the given amount of exponent and significand bits (plus an extra sign bit). If support-nan-and-infinity-p is true, the decoders will also understand these special cases. NaN is represented as :not-a-number, and the infinities as :positive-infinity and :negative-infinity. Note that this means that the in- or output of these functions is not just floating point numbers anymore, but also keywords.


Back to Common-lisp.net.

Valid XHTML 1.0 Strict
ieee-floats-20170830-git/doc/style.css000066400000000000000000000021431314762721100173610ustar00rootroot00000000000000 .header { font-size: medium; background-color:#336699; color:#ffffff; border-style:solid; border-width: 5px; border-color:#002244; padding: 1mm 1mm 1mm 5mm; } .footer { font-size: small; font-style: italic; text-align: right; background-color:#336699; color:#ffffff; border-style:solid; border-width: 2px; border-color:#002244; padding: 1mm 1mm 1mm 1mm; } .footer a:link { font-weight:bold; color:#ffffff; text-decoration:underline; } .footer a:visited { font-weight:bold; color:#ffffff; text-decoration:underline; } .footer a:hover { font-weight:bold; color:#002244; text-decoration:underline; } .check {font-size: x-small; text-align:right;} .check a:link { font-weight:bold; color:#a0a0ff; text-decoration:underline; } .check a:visited { font-weight:bold; color:#a0a0ff; text-decoration:underline; } .check a:hover { font-weight:bold; color:#000000; text-decoration:underline; } tt { font-size: 1.1em; font-weight: bold; } .def { margin-top: 1.5em; font-family: tahoma, arial, sans-serif; } .desc { padding-left: .6em; } h2 { font-size: 14pt; } ieee-floats-20170830-git/ieee-floats.asd000066400000000000000000000010511314762721100176250ustar00rootroot00000000000000(defsystem :ieee-floats :description "Convert floating point values to IEEE 754 binary representation" :author "Marijn Haverbeke " :license "BSD" :components ((:file "ieee-floats")) :in-order-to ((test-op (test-op "ieee-floats-tests")))) (defsystem :ieee-floats-tests :description "Test suite for ieee-floats" :author "Marijn Haverbeke " :license "BSD" :depends-on (:ieee-floats :fiveam) :components ((:file "tests")) :perform (test-op (o s) (uiop:symbol-call :fiveam '#:run! :ieee-floats))) ieee-floats-20170830-git/ieee-floats.lisp000066400000000000000000000145061314762721100200360ustar00rootroot00000000000000;;; Functions for converting floating point numbers represented in ;;; IEEE 754 style to lisp numbers. ;;; ;;; See http://common-lisp.net/project/ieee-floats/ (defpackage :ieee-floats (:use :common-lisp) (:export :make-float-converters :encode-float32 :decode-float32 :encode-float64 :decode-float64)) (in-package :ieee-floats) ;; The following macro may look a bit overcomplicated to the casual ;; reader. The main culprit is the fact that NaN and infinity can be ;; optionally included, which adds a bunch of conditional parts. ;; ;; Assuming you already know more or less how floating point numbers ;; are typically represented, I'll try to elaborate a bit on the more ;; confusing parts, as marked by letters: ;; ;; (A) Exponents in IEEE floats are offset by half their range, for ;; example with 8 exponent bits a number with exponent 2 has 129 ;; stored in its exponent field. ;; ;; (B) The maximum possible exponent is reserved for special cases ;; (NaN, infinity). ;; ;; (C) If the exponent fits in the exponent-bits, we have to adjust ;; the significand for the hidden bit. Because decode-float will ;; return a significand between 0 and 1, and we want one between 1 ;; and 2 to be able to hide the hidden bit, we double it and then ;; subtract one (the hidden bit) before converting it to integer ;; representation (to adjust for this, 1 is subtracted from the ;; exponent earlier). When the exponent is too small, we set it to ;; zero (meaning no hidden bit, exponent of 1), and adjust the ;; significand downward to compensate for this. ;; ;; (D) Here the hidden bit is added. When the exponent is 0, there is ;; no hidden bit, and the exponent is interpreted as 1. ;; ;; (E) Here the exponent offset is subtracted, but also an extra ;; factor to account for the fact that the bits stored in the ;; significand are supposed to come after the 'decimal dot'. (defmacro make-float-converters (encoder-name decoder-name exponent-bits significand-bits support-nan-and-infinity-p) "Writes an encoder and decoder function for floating point numbers with the given amount of exponent and significand bits (plus an extra sign bit). If support-nan-and-infinity-p is true, the decoders will also understand these special cases. NaN is represented as :not-a-number, and the infinities as :positive-infinity and :negative-infinity. Note that this means that the in- or output of these functions is not just floating point numbers anymore, but also keywords." (let* ((total-bits (+ 1 exponent-bits significand-bits)) (exponent-offset (1- (expt 2 (1- exponent-bits)))) ; (A) (sign-part `(ldb (byte 1 ,(1- total-bits)) bits)) (exponent-part `(ldb (byte ,exponent-bits ,significand-bits) bits)) (significand-part `(ldb (byte ,significand-bits 0) bits)) (nan support-nan-and-infinity-p) (max-exponent (1- (expt 2 exponent-bits)))) ; (B) `(progn (defun ,encoder-name (float) ,@(unless nan `((declare (type float float)))) (multiple-value-bind (sign significand exponent) (cond ,@(when nan `(((eq float :not-a-number) (values 0 1 ,max-exponent)) ((eq float :positive-infinity) (values 0 0 ,max-exponent)) ((eq float :negative-infinity) (values 1 0 ,max-exponent)))) (t (multiple-value-bind (significand exponent sign) (decode-float float) (let ((exponent (if (= 0 significand) exponent (+ (1- exponent) ,exponent-offset))) (sign (if (= sign 1.0) 0 1))) (unless (< exponent ,(expt 2 exponent-bits)) (error "Floating point overflow when encoding ~A." float)) (if (<= exponent 0) ; (C) (values sign (ash (round (* ,(expt 2 significand-bits) significand)) exponent) 0) (values sign (round (* ,(expt 2 significand-bits) (1- (* significand 2)))) exponent)))))) (let ((bits 0)) (declare (type (unsigned-byte ,total-bits) bits)) (setf ,sign-part sign ,exponent-part exponent ,significand-part significand) bits))) (defun ,decoder-name (bits) (declare (type (unsigned-byte ,total-bits) bits)) (let* ((sign ,sign-part) (exponent ,exponent-part) (significand ,significand-part)) ,@(when nan `((when (= exponent ,max-exponent) (return-from ,decoder-name (cond ((not (zerop significand)) :not-a-number) ((zerop sign) :positive-infinity) (t :negative-infinity)))))) (if (zerop exponent) ; (D) (setf exponent 1) (setf (ldb (byte 1 ,significand-bits) significand) 1)) (let ((float-significand (float significand ,(if (> total-bits 32) 1.0d0 1.0f0)))) (scale-float (if (zerop sign) float-significand (- float-significand)) (- exponent ,(+ exponent-offset significand-bits))))))))) ; (E) ;; And instances of the above for the common forms of floats. (declaim (inline encode-float32 decode-float32 encode-float64 decode-float64)) (make-float-converters encode-float32 decode-float32 8 23 nil) (make-float-converters encode-float64 decode-float64 11 52 nil) ;;; Copyright (c) 2006 Marijn Haverbeke ;;; ;;; This software is provided 'as-is', without any express or implied ;;; warranty. In no event will the authors be held liable for any ;;; damages arising from the use of this software. ;;; ;;; Permission is granted to anyone to use this software for any ;;; purpose, including commercial applications, and to alter it and ;;; redistribute it freely, subject to the following restrictions: ;;; ;;; 1. The origin of this software must not be misrepresented; you must ;;; not claim that you wrote the original software. If you use this ;;; software in a product, an acknowledgment in the product ;;; documentation would be appreciated but is not required. ;;; ;;; 2. Altered source versions must be plainly marked as such, and must ;;; not be misrepresented as being the original software. ;;; ;;; 3. This notice may not be removed or altered from any source ;;; distribution. ieee-floats-20170830-git/tests.lisp000066400000000000000000000060131314762721100167750ustar00rootroot00000000000000(defpackage :ieee-floats-tests (:use :common-lisp :ieee-floats :fiveam)) (in-package :ieee-floats-tests) ;; After loading, run the tests with (fiveam:run! :ieee-floats) ;; The tiny-XX tests will error on systems that do not support 64-bit ;; floats, CLISP is one of those. (def-suite :ieee-floats) (in-suite :ieee-floats) (defmacro pairs-correspond (decode encode &body pairs) `(progn ,@(loop :for (float bits) :in pairs :collect `(is (eql ,float (,decode ,bits))) :collect `(is (eql ,bits (,encode ,float)))))) (make-float-converters encode-float64* decode-float64* 11 52 t) (make-float-converters encode-float32* decode-float32* 8 23 t) (make-float-converters encode-float16 decode-float16 5 10 nil) (test sanity-32 (pairs-correspond decode-float32 encode-float32 (0.0 #b00000000000000000000000000000000) (5.0 #b01000000101000000000000000000000) (-5.0 #b11000000101000000000000000000000) (3.3333333e20 #b01100001100100001000111101101111) (-.44e-30 #b10001101000011101100100111000101))) (test tiny-32 (pairs-correspond decode-float32 encode-float32 (9.949219e-44 #b00000000000000000000000001000111))) (test tiny-16 (dolist (n '(#b0000001111111111 #b0000001100000000 #b0000001000000000)) (is (eql n (encode-float16 (decode-float16 n)))))) (test overflow-32 (signals error (encode-float32 1.0d60))) (test specials-32 (pairs-correspond decode-float32* encode-float32* (-0.0 #b10000000000000000000000000000000) (5.0e2 #b01000011111110100000000000000000) (-5.0e-2 #b10111101010011001100110011001101) (:not-a-number #b01111111100000000000000000000001) (:positive-infinity #b01111111100000000000000000000000) (:negative-infinity #b11111111100000000000000000000000))) (test sanity-64 (pairs-correspond decode-float64 encode-float64 (0.0d0 #b0000000000000000000000000000000000000000000000000000000000000000) (42d42 #b0100100011111110001000100010111010000010011001101101001001111111) (-42d42 #b1100100011111110001000100010111010000010011001101101001001111111) (.555555555d-30 #b0011100110100110100010010011011111111110011011000100011010001000))) (test tiny-64 (pairs-correspond decode-float64 encode-float64 (4.1995579896505956d-322 #b0000000000000000000000000000000000000000000000000000000001010101))) (test specials-64 (pairs-correspond decode-float64* encode-float64* (-0d0 #b1000000000000000000000000000000000000000000000000000000000000000) (42d42 #b0100100011111110001000100010111010000010011001101101001001111111) (-42d42 #b1100100011111110001000100010111010000010011001101101001001111111) (:not-a-number #b0111111111110000000000000000000000000000000000000000000000000001) (:positive-infinity #b0111111111110000000000000000000000000000000000000000000000000000) (:negative-infinity #b1111111111110000000000000000000000000000000000000000000000000000)))