From: Tamas K Papp
Subject: making specialized array neatly
Date: 
Message-ID: <6mmddgFhacakU1@mid.individual.net>
Hi,

I am optimizing my code and found that instead of returning multiple 
values, SBCL likes to have them packed into a vector with a specialized 
element-type (otherwise it complains about doing float to pointer 
coercion).

I found that

(make-array 2 :element-type 'double-float :initial-contents (list x y))

is not optimal since the compiler complains.  Doing

(let ((a (make-array 2 :element-type 'double-float)))
    (setf (aref a 0) x
	  (aref a 1) y)
    a)

makes SBCL happy.  Is there a one-liner "neat" way of doing this that I 
could not figure out, or should I just pack this up in a macro (for n 
arguments)?

Thanks,

Tamas

PS.: I asked about this on the SBCL list but didn't (yet) get a reply.

From: Dimiter "malkia" Stanev
Subject: Re: making specialized array neatly
Date: 
Message-ID: <ge53tq$64v$2@registered.motzarella.org>
Tamas K Papp wrote:
> Hi,
> 
> I am optimizing my code and found that instead of returning multiple 
> values, SBCL likes to have them packed into a vector with a specialized 
> element-type (otherwise it complains about doing float to pointer 
> coercion).
> 
> I found that
> 
> (make-array 2 :element-type 'double-float :initial-contents (list x y))
> 
> is not optimal since the compiler complains.  Doing
> 
> (let ((a (make-array 2 :element-type 'double-float)))
>     (setf (aref a 0) x
> 	  (aref a 1) y)
>     a)
> 
> makes SBCL happy.  Is there a one-liner "neat" way of doing this that I 
> could not figure out, or should I just pack this up in a macro (for n 
> arguments)?
> 
> Thanks,
> 
> Tamas
> 
> PS.: I asked about this on the SBCL list but didn't (yet) get a reply.

Wouldn't that be faster (dunno for sure):

(make-array 2 :element-type 'double-float :initial-contents #(1.0d0 2.0d0))
From: Dimiter "malkia" Stanev
Subject: Re: making specialized array neatly
Date: 
Message-ID: <ge541f$64v$3@registered.motzarella.org>
Dimiter "malkia" Stanev wrote:
> Tamas K Papp wrote:
>> Hi,
>>
>> I am optimizing my code and found that instead of returning multiple 
>> values, SBCL likes to have them packed into a vector with a 
>> specialized element-type (otherwise it complains about doing float to 
>> pointer coercion).
>>
>> I found that
>>
>> (make-array 2 :element-type 'double-float :initial-contents (list x y))
>>
>> is not optimal since the compiler complains.  Doing
>>
>> (let ((a (make-array 2 :element-type 'double-float)))
>>     (setf (aref a 0) x
>>       (aref a 1) y)
>>     a)
>>
>> makes SBCL happy.  Is there a one-liner "neat" way of doing this that 
>> I could not figure out, or should I just pack this up in a macro (for 
>> n arguments)?
>>
>> Thanks,
>>
>> Tamas
>>
>> PS.: I asked about this on the SBCL list but didn't (yet) get a reply.
> 
> Wouldn't that be faster (dunno for sure):
> 
> (make-array 2 :element-type 'double-float :initial-contents #(1.0d0 2.0d0))

I think it's faster, I've just tested it under SBCL:

(declaim (optimize (speed 3) (safety 0) (debug 0) (space 0)))

(disassemble (defun test () (make-array 2 :element-type 'double-float 
:initial-contents #(1.0d0 2.0d0))))
STYLE-WARNING: redefining TEST in DEFUN

; 0A845B6A:       BA08000000       MOV EDX, 8                 ; 
no-arg-parsing entry point
;       6F:       8B3D305B840A     MOV EDI, [#xA845B30]       ; 
:ELEMENT-TYPE
;       75:       8B35345B840A     MOV ESI, [#xA845B34]       ; 
'DOUBLE-FLOAT
;       7B:       8B05385B840A     MOV EAX, [#xA845B38]       ; 
:INITIAL-CONTENTS
;       81:       8945F0           MOV [EBP-16], EAX
;       84:       8B053C5B840A     MOV EAX, [#xA845B3C]       ; #(1.0d0 
2.0d0)
;       8A:       8945EC           MOV [EBP-20], EAX
;       8D:       8B05405B840A     MOV EAX, [#xA845B40]       ; 
#<FDEFINITION object for MAKE-ARRAY>
;       93:       B914000000       MOV ECX, 20
;       98:       FF75F8           PUSH DWORD PTR [EBP-8]
;       9B:       FF6005           JMP DWORD PTR [EAX+5]
;       9E:       90               NOP
;       9F:       90               NOP
;
NIL

VS .......................

* (disassemble (defun test () (make-array 2 :element-type 'double-float 
:initial-contents (list 1.0d0 2.0d0))))
STYLE-WARNING: redefining TEST in DEFUN

; 0A870062:       8B152C041002     MOV EDX, [#x210042C]       ; 
no-arg-parsing entry point
;       68:       8B3D2800870A     MOV EDI, [#xA870028]       ; 2.0d0
;       6E:       800DCC03100204   OR BYTE PTR [#x21003CC], 4
;       75:       BB10000000       MOV EBX, 16
;       7A:       031DF0C14100     ADD EBX, [#x41C1F0]        ; 
_boxed_region
;       80:       3B1DF4C14100     CMP EBX, [#x41C1F4]
;       86:       7607             JBE L0
;       88:       E87B15BAF5       CALL #x411608              ; 
_alloc_overflow_ebx
;       8D:       EB09             JMP L1
;       8F: L0:   891DF0C14100     MOV [#x41C1F0], EBX        ; 
_boxed_region
;       95:       83EB10           SUB EBX, 16
;       98: L1:   8D5B03           LEA EBX, [EBX+3]
;       9B:       8BC3             MOV EAX, EBX
;       9D:       8950FD           MOV [EAX-3], EDX
;       A0:       83C008           ADD EAX, 8
;       A3:       8940F9           MOV [EAX-7], EAX
;       A6:       8978FD           MOV [EAX-3], EDI
;       A9:       C740010B001002   MOV DWORD PTR [EAX+1], 34603019
;       B0:       8035CC03100204   XOR BYTE PTR [#x21003CC], 4
;       B7:       7402             JEQ L2
;       B9:       CC09             BREAK 9                    ; pending 
interrupt trap
;       BB: L2:   BA08000000       MOV EDX, 8
;       C0:       8B3D2C00870A     MOV EDI, [#xA87002C]       ; 
:ELEMENT-TYPE
;       C6:       8B353000870A     MOV ESI, [#xA870030]       ; 
'DOUBLE-FLOAT
;       CC:       8B053400870A     MOV EAX, [#xA870034]       ; 
:INITIAL-CONTENTS
;       D2:       8945F0           MOV [EBP-16], EAX
;       D5:       895DEC           MOV [EBP-20], EBX
;       D8:       8B053800870A     MOV EAX, [#xA870038]       ; 
#<FDEFINITION object for MAKE-ARRAY>
;       DE:       B914000000       MOV ECX, 20
;       E3:       FF75F8           PUSH DWORD PTR [EBP-8]
;       E6:       FF6005           JMP DWORD PTR [EAX+5]
;       E9:       90               NOP
;       EA:       90               NOP
;       EB:       90               NOP
;       EC:       90               NOP
;       ED:       90               NOP
;       EE:       90               NOP
;       EF:       90               NOP
;
NIL
*
From: Tamas K Papp
Subject: Re: making specialized array neatly
Date: 
Message-ID: <6mmj84Fhhnf4U1@mid.individual.net>
On Mon, 27 Oct 2008 12:15:59 -0700, Dimiter \"malkia\" Stanev wrote:

> Dimiter "malkia" Stanev wrote:
>> Tamas K Papp wrote:
>>> Hi,
>>>
>>> I am optimizing my code and found that instead of returning multiple
>>> values, SBCL likes to have them packed into a vector with a
>>> specialized element-type (otherwise it complains about doing float to
>>> pointer coercion).
>>>
>>> I found that
>>>
>>> (make-array 2 :element-type 'double-float :initial-contents (list x
>>> y))
>>>
>>> is not optimal since the compiler complains.  Doing
>>>
>>> (let ((a (make-array 2 :element-type 'double-float)))
>>>     (setf (aref a 0) x
>>>       (aref a 1) y)
>>>     a)
>>>
>>> makes SBCL happy.  Is there a one-liner "neat" way of doing this that
>>> I could not figure out, or should I just pack this up in a macro (for
>>> n arguments)?
>>>
>>> Thanks,
>>>
>>> Tamas
>>>
>>> PS.: I asked about this on the SBCL list but didn't (yet) get a reply.
>> 
>> Wouldn't that be faster (dunno for sure):
>> 
>> (make-array 2 :element-type 'double-float :initial-contents #(1.0d0
>> 2.0d0))
> 
> I think it's faster, I've just tested it under SBCL:

Isn't SBCL just folding constants there?

(make-array 2 :element-type 'double-float :initial-contents 
	      (vector x y))

still makes SBCL complain about doing float to pointer coercion.

Tamas
From: Dimiter "malkia" Stanev
Subject: Re: making specialized array neatly
Date: 
Message-ID: <ge568e$mjc$1@registered.motzarella.org>
Tamas K Papp wrote:
> On Mon, 27 Oct 2008 12:15:59 -0700, Dimiter \"malkia\" Stanev wrote:
> 
>> Dimiter "malkia" Stanev wrote:
>>> Tamas K Papp wrote:
>>>> Hi,
>>>>
>>>> I am optimizing my code and found that instead of returning multiple
>>>> values, SBCL likes to have them packed into a vector with a
>>>> specialized element-type (otherwise it complains about doing float to
>>>> pointer coercion).
>>>>
>>>> I found that
>>>>
>>>> (make-array 2 :element-type 'double-float :initial-contents (list x
>>>> y))
>>>>
>>>> is not optimal since the compiler complains.  Doing
>>>>
>>>> (let ((a (make-array 2 :element-type 'double-float)))
>>>>     (setf (aref a 0) x
>>>>       (aref a 1) y)
>>>>     a)
>>>>
>>>> makes SBCL happy.  Is there a one-liner "neat" way of doing this that
>>>> I could not figure out, or should I just pack this up in a macro (for
>>>> n arguments)?
>>>>
>>>> Thanks,
>>>>
>>>> Tamas
>>>>
>>>> PS.: I asked about this on the SBCL list but didn't (yet) get a reply.
>>> Wouldn't that be faster (dunno for sure):
>>>
>>> (make-array 2 :element-type 'double-float :initial-contents #(1.0d0
>>> 2.0d0))
>> I think it's faster, I've just tested it under SBCL:
> 
> Isn't SBCL just folding constants there?
> 
> (make-array 2 :element-type 'double-float :initial-contents 
> 	      (vector x y))
> 
> still makes SBCL complain about doing float to pointer coercion.
> 
> Tamas

Yup, you are right. My mistake. What I did would work only for constants.

I guess then the most optimal way, would be setf-ing them one by one.

I've also tried using vector for initialization, and made the vector to 
be on the stack (where the implementation allows by using (declare 
(dynamic-extent v)) - but it still produces more code, or conses 
(depends on the lisp implementation).

Maybe some macro?
From: D Herring
Subject: Re: making specialized array neatly
Date: 
Message-ID: <ge5lst$elm$1@aioe.org>
Tamas K Papp wrote:
> I am optimizing my code and found that instead of returning multiple 
> values, SBCL likes to have them packed into a vector with a specialized 
> element-type (otherwise it complains about doing float to pointer 
> coercion).
> 
> I found that
> 
> (make-array 2 :element-type 'double-float :initial-contents (list x y))
> 
> is not optimal since the compiler complains.  Doing
> 
> (let ((a (make-array 2 :element-type 'double-float)))
>     (setf (aref a 0) x
> 	  (aref a 1) y)
>     a)
> 
> makes SBCL happy.  Is there a one-liner "neat" way of doing this that I 
> could not figure out, or should I just pack this up in a macro (for n 
> arguments)?

Something like

(defmacro fill-array (type &rest values)
   "Initialize an array with values of the given type.
Example: (fill-array 'double-float 1d0 2d0 3d0)"
   (let ((l (length values))
	(n (gensym)))
     `(let ((,n (make-array ,l :element-type ,type)))
        ,(cons 'setf
	      (loop for v in values
		 for i from 0 below l
		 appending (list (list 'aref n i) v)))
        ,n)))

? [lightly tested]

- Daniel
From: William James
Subject: Re: making specialized array neatly
Date: 
Message-ID: <gei75c0r2m@enews2.newsguy.com>
D Herring wrote:

> Tamas K Papp wrote:
> > I am optimizing my code and found that instead of returning
> > multiple  values, SBCL likes to have them packed into a vector with
> > a specialized  element-type (otherwise it complains about doing
> > float to pointer  coercion).
> > 
> > I found that
> > 
> > (make-array 2 :element-type 'double-float :initial-contents (list x
> > y))
> > 
> > is not optimal since the compiler complains.  Doing
> > 
> > (let ((a (make-array 2 :element-type 'double-float)))
> >    (setf (aref a 0) x
> > 	  (aref a 1) y)
> >    a)
> > 
> > makes SBCL happy.  Is there a one-liner "neat" way of doing this
> > that I  could not figure out, or should I just pack this up in a
> > macro (for n  arguments)?
> 
> Something like
> 
> (defmacro fill-array (type &rest values)
>   "Initialize an array with values of the given type.
> Example: (fill-array 'double-float 1d0 2d0 3d0)"
>   (let ((l (length values))
> 	(n (gensym)))
>     `(let ((,n (make-array ,l :element-type ,type)))
>        ,(cons 'setf
> 	      (loop for v in values
> 		 for i from 0 below l
> 		 appending (list (list 'aref n i) v)))
>        ,n)))
> 

Ruby:

[1.0, 2.0, 3.0]
From: D Herring
Subject: Re: making specialized array neatly
Date: 
Message-ID: <geic9c$1fj$1@aioe.org>
William James wrote:
> D Herring wrote:
>> Tamas K Papp wrote:
>>> I am optimizing my code and found that instead of returning
>>> multiple  values, SBCL likes to have them packed into a vector with
>>> a specialized  element-type (otherwise it complains about doing
>>> float to pointer  coercion).
...
> Ruby:
> 
> [1.0, 2.0, 3.0]

CL has array syntax too.  But it captures compile-time values and 
isn't optimized the way Tamas wanted.

CL-USER> #(1.0 2.0 3.0)
#(1.0 2.0 3.0)
CL-USER> (type-of *)
(SIMPLE-VECTOR 3)
CL-USER> (coerce #(1.0 2.0 3.0) '(simple-array single-float (3)))
#(1.0 2.0 3.0)
CL-USER> (type-of *)
(SIMPLE-ARRAY SINGLE-FLOAT (3))

- Daniel
From: Raffael Cavallaro
Subject: Re: making specialized array neatly
Date: 
Message-ID: <geigqn$kct$1@aioe.org>
On 2008-11-01 14:29:00 -0400, "William James" <·········@yahoo.com> said:

> Ruby:
> 
> [1.0, 2.0, 3.0]

This is a nice because when you specify the element type as float 
ruby's optimizing compiler...

oh, wait...
From: Dimiter "malkia" Stanev
Subject: Re: making specialized array neatly
Date: 
Message-ID: <gel6f3$uoj$1@registered.motzarella.org>
Raffael Cavallaro wrote:
> On 2008-11-01 14:29:00 -0400, "William James" <·········@yahoo.com> said:
> 
>> Ruby:
>>
>> [1.0, 2.0, 3.0]
> 
> This is a nice because when you specify the element type as float ruby's 
> optimizing compiler...
> 
> oh, wait...
> 

Well at least it could be implemented :) - but then again, it probably 
won't work if you want to change the type of the elements on the fly...

Doesn't V8, or some of the other new and exciting JavaScript 
implementations have something like that (run-time auto-specializing 
thingie for the arrays?)

It sounds neat :)
From: Tamas K Papp
Subject: Re: making specialized array neatly
Date: 
Message-ID: <6mmt04Fh7bgiU1@mid.individual.net>
On Mon, 27 Oct 2008 17:51:44 +0000, Tamas K Papp wrote:

> is not optimal since the compiler complains.  Doing
> 
> (let ((a (make-array 2 :element-type 'double-float)))
>     (setf (aref a 0) x
> 	  (aref a 1) y)
>     a)
> 
> makes SBCL happy.  Is there a one-liner "neat" way of doing this that I
> could not figure out, or should I just pack this up in a macro (for n
> arguments)?

Nikodemus Siivola gave me a nice compiler macro on sbcl-help which solves 
the whole issue.  See 
http://permalink.gmane.org/gmane.lisp.steel-bank.general/2149

SBCL rocks :-)

Tamas
From: Dimiter "malkia" Stanev
Subject: Re: making specialized array neatly
Date: 
Message-ID: <ge5kp3$j1c$1@registered.motzarella.org>
Tamas K Papp wrote:
> On Mon, 27 Oct 2008 17:51:44 +0000, Tamas K Papp wrote:
> 
>> is not optimal since the compiler complains.  Doing
>>
>> (let ((a (make-array 2 :element-type 'double-float)))
>>     (setf (aref a 0) x
>> 	  (aref a 1) y)
>>     a)
>>
>> makes SBCL happy.  Is there a one-liner "neat" way of doing this that I
>> could not figure out, or should I just pack this up in a macro (for n
>> arguments)?
> 
> Nikodemus Siivola gave me a nice compiler macro on sbcl-help which solves 
> the whole issue.  See 
> http://permalink.gmane.org/gmane.lisp.steel-bank.general/2149
> 
> SBCL rocks :-)
> 
> Tamas

Love it! Thanks!!!
From: Thomas A. Russ
Subject: Re: making specialized array neatly
Date: 
Message-ID: <ymiwsfqc84f.fsf@blackcat.isi.edu>
Tamas K Papp <······@gmail.com> writes:

> Hi,
> 
> I am optimizing my code and found that instead of returning multiple 
> values, SBCL likes to have them packed into a vector with a specialized 
> element-type (otherwise it complains about doing float to pointer 
> coercion).
> 
> I found that
> 
> (make-array 2 :element-type 'double-float :initial-contents (list x y))
> 
> is not optimal since the compiler complains.  Doing
> 
> (let ((a (make-array 2 :element-type 'double-float)))
>     (setf (aref a 0) x
> 	  (aref a 1) y)
>     a)
> 
> makes SBCL happy.  Is there a one-liner "neat" way of doing this that I 
> could not figure out, or should I just pack this up in a macro (for n 
> arguments)?

I think you want a macro.  Fortunately it's easy to do:

(defmacro make-typed-vector (type &rest args)
  (let ((array-var (gensym "ARRAY-")))
     `(let ((,array-var (make-array ,(length args) :element-type ',type)))
        ,@(loop for arg in args
                as index upfrom 0
                collect `(setf (aref ,array-var ,index) ,arg))
        ,array-var)))

And then you just need:

  (make-typed-vector double-float x y)


-- 
Thomas A. Russ,  USC/Information Sciences Institute