in APL how do I turn a vector (of length n) into a diagonal matrix (nxn)?
Asked Answered
S

5

5

I had a J program I wrote in 1985 (on vax vms). One section was creating a diagonal matrix from a vector.

a=(n,n)R1,nR0
b=In
a=bXa

Maybe it wasn't J but APL in ascii, but these lines work in current J (with appropriate changes in the primitive functions). But not in APL (gnu , NARS2000 or ELI). I get domain error in the last line. Is there an easy way to do this without looping?

Superfine answered 28/12, 2017 at 16:17 Comment(2)
Related.Guelph
@osmanfb1: can you pls. accept one of the replies (so that the q no longer shows as "Open")?Remindful
S
6

Your code is an ASCII transliteration of APL. The corresponding J code is:

a=.(n,n)$1,n$0
b=.i.n
a=.b*a

Try it online! However, no APL (as of yet — it is being considered for Dyalog APL) has major cell extension which is required on the last line. You therefore need to specify that the scalars of the vector b should be multiplied with the rows of the matrix a using bracket axis notation:

a←(n,n)⍴1,n⍴0
b←⍳n
a←b×[1]a

Try it online! Alternatively, you can use the rank operator (where available):

a←(n,n)⍴1,n⍴0
b←⍳n
a←b(×⍤0 1)a

Try it online!

Seng answered 28/12, 2017 at 18:26 Comment(1)
Just for interest, a more natural J coding of this might be: (* =@i.@#) 4 5 2 6 where 4 5 2 6 is the vector that you are wanting to put on the diagonal.Spada
P
4

A more elegant way to address diagonals is ⍉ with repeated axes:

      n←5 ◊ z←(n,n)⍴0 ◊ (1 1⍉z)←⍳n ◊ z
1 0 0 0 0
0 2 0 0 0
0 0 3 0 0
0 0 0 4 0
0 0 0 0 5
Proscription answered 29/12, 2017 at 11:9 Comment(3)
Thanks Jurgen. I need to study this a bit more to understand how it works. I understand all but the line next to the last one. When I type whats in the parens, I get a vector of zeros, and iota n is assigned to that?? But it seems work if type both at the same time. Maybe I understood these 30 yrs ago but now seems harder :-(Superfine
Holy crap, that is elegant! And just as a note, in some APL's, you would use not , and if you index arrays starting at 0 (⎕IO←0), then it's (0 0⍉z)←⍳nMidbrain
In most APL dialects, when you use an expression that selects elements from an array, such as (1 1⍉z) here, and then assign something to that expression (placed in parens), the elements of the array that the expression would have selected are assigned whatever is on the right of the assignment arrow. This is known as "selective specification" and it is a very powerful and handy feature. Thus (1 1⍉z)←⍳n assigns the first n positive integers to the result of the transpose, which is in this case the main diagonal of the n by n matrix.Simulator
M
1

Given an input vector X, the following works in all APLs, (courtesy of @Adám in chat):

(2⍴S)⍴((2×S)⍴1,-S←⍴X)\X

And here's a place where you can run it online.

Here are my old, inefficient versions that use multiplication and the outer product (the latter causes the inefficiency):

((⍴Q)⍴X)×Q←P∘.=P←⍳⍴X
((⍴Q)⍴X)×Q←P Pρ1,(P←≢X)ρ0
Midbrain answered 28/12, 2017 at 18:27 Comment(2)
Thanks Zachary. I tried in gnu apl but got domain error.Superfine
yes, I am getting DOMAIN ERROR in gnu apl. But worked on Dyalog on iot.run.Superfine
O
0

Or another way:

(n∘.=n)×(2ρρn)ρn←⍳5

should give you the following in most APLs

1 0 0 0 0
0 2 0 0 0
0 0 3 0 0
0 0 0 4 0
0 0 0 0 5
Overbalance answered 29/12, 2017 at 11:31 Comment(1)
I don't know if this is more efficient as the answer by Adam but is also easy to understand. It worked on gnu apl. Thanks.Superfine
P
0

This solution works in the old ISO Apl:

a←(n,n)⍴v,(n,n)⍴0
Periosteum answered 8/1, 2018 at 22:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.