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?

Micha Wiedenmann
  • 19,979
  • 21
  • 92
  • 137
osmanfb1
  • 53
  • 2

5 Answers5

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!

Adám
  • 6,573
  • 20
  • 37
  • 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. – Tikkanz Jan 08 '18 at 23:06
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
  • 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 :-( – osmanfb1 Dec 31 '17 at 02:14
  • 1
    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)←⍳n` – Adalynn Dec 31 '17 at 15:40
  • 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. – David Siegel Feb 13 '18 at 23:11
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
Adalynn
  • 139
  • 7
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
Graham
  • 101
  • 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. – osmanfb1 Dec 31 '17 at 02:03
0

This solution works in the old ISO Apl:

a←(n,n)⍴v,(n,n)⍴0
rnso
  • 23,686
  • 25
  • 112
  • 234
GilVib
  • 51
  • 2