Newsgroups: comp.lang.apl
From: bernecky@eecg.toronto.edu (Robert Bernecky)
Subject: Re: help on J please
Message-ID: <1994Sep14.170420.17660@jarvis.cs.toronto.edu>
Nntp-Posting-Host: algonquin.eecg.toronto.edu
Organization: University of Toronto, Computer Engineering
References: <353upd$659@deimos.rz.Uni-Osnabrueck.DE>
Date: 14 Sep 94 21:04:20 GMT
Lines: 73

In article <353upd$659@deimos.rz.Uni-Osnabrueck.DE> bfaust@saratoga.physik.Uni-Osnabrueck.DE (Bernd Faust) writes:
>Hello!
>
>I need a function to create diagonal matrices like the "diag" function in
>matlab.
>e.g. a call: diag 2 3 5 should create a matrix 2 0 0
>                                               0 3 0
>                                               0 0 5
>( this problem is solved: diag=.'y.*((i.#y.)=/(i.#y.))' : '' )
>but a call: 1 diag 2 3 5 should create 0 2 0 0
>                                       0 0 3 0
>                                       0 0 0 5
>                                       0 0 0 0
>
>           -1 diag 2 3 5 should create 0 0 0 0
>                                       2 0 0 0
>                                       0 3 0 0
>                                       0 0 5 0
>
>           you see: "0 diag x" is equivalent to "diag x"
>
Well, here's a start that comes close to what you desire.
Start by realizing that you get a skewed table by reshaping a vector
into a table, with a vector whose shape differs from the # columns in the
table by the skew factor. In APL, the traditional way to generate
an identity matrix FAST {as opposed to the outer product you show
above} is:
    id: (2 reshape y.) reshape (1+y.) take 1
with   id 3
returning
1 0 0
0 1 0
0 0 1


In J, this is:
    id: (2 reshape y.) reshape (1+y.) take 1
    (2   $         y.) $,       (1+y.) {."0  (1)
Above "take rank 0" ( {. " 0) gives us one result row per element of y.
Ravel is needed because reshape works on items.


For your example, let's give it the diagonal explicitly. Then, we
need item count of y. instead of y. to get the shapes correct:
   T =.  (2 $ # y. )  $ ,(1+ # y.) {."0 y.

   T 1 2 3
1 0 0
0 2 0
0 0 3

If we rotate things a bit with the left argument, we get almost what you
want:
 T2=.  (2 $# y.) $ (-.x) |."1 (1+#y.) {."0 y.

  0 T2 10 20 30
10  0  0
 0 20  0
 0  0 30

  1 T2 10 20 30
0 10  0  0
0  0 20  0
0  0  0 30
0  0  0  0

   _1 T2 10 20 30  NB. Not what you asked for
 0  0 0
10  0 0
 0 20 0

This should get you started. Bob

