;;; There recently was a discussion about using arrays with suitably-declared
;;; element-type s to store floats without needing boxing and unboxing.
;;; This is obviously quite a hassle, as and when one wants to use.
;;;
;;; But, this is lisp and macros are (as always) ready to leap to the rescue.
;;; This code is Copyright Ingvar Mattsson, 2005 <ingvar(a)hexapodia.net>
;;; You are free to use and/or modify this code as you see fit, as long
;;; as this comment block is retained and modifications noted by at least
;;; the modifyer's name.
(defpackage #:net.hexapodia.fastfloats
(:nicknames #:fastfloats)
(:use #:cl)
(:export #:double-float-let #:single-float-let :float-let))
(in-package #:net.hexapodia.fastfloats)
(defun float-let-expander (type initform body)
(let ((syms (loop for spec in initform
for n from 0
if (symbolp spec)
collect (cons spec n)
else
collect (cons (car spec) n)))
(inits (loop for spec in initform
unless (symbolp spec)
collect (list (gensym) spec)))
(storage (gensym)))
`(let ,(loop for (sym spec) in inits
collect (list sym (cadr spec)))
(let ((,storage (make-array ,(length syms)
:element-type ',type
:initial-element (coerce 0.0 ',type))))
(symbol-macrolet ,(loop for (sym . n) in syms
collect (list sym (list 'aref storage n)))
; Init section
,@(loop for (sym val) in inits
collect (list 'setf (car val) sym))
,@body)))))
(defmacro double-float-let (initform &body body)
(float-let-expander 'double-float initform body))
(defmacro single-float-let (initform &body body)
(float-let-expander 'single-float initform body))
(defmacro float-let (initform &body body)
(float-let-expander *read-default-float-format* initform body))
;;; //Ingvar