Rank/Atop: Difference between revisions

From NARS2000
Jump to navigationJump to search
(New page: This feature is implemented via several internal magic functions: '''Monadic Derived Function''' <apll>    ∇ Z←(LO F X) R;O</apll><br /> <apll>[1]  &nbs...)
 
No edit summary
 
(24 intermediate revisions by 2 users not shown)
Line 1: Line 1:
This feature is implemented via several internal magic functions:
==Rank Monadic Derived Function==


'''Monadic Derived Function'''
<table border="1" cellpadding="5" cellspacing="0" rules="none" summary="">
<tr>
  <td>
    <table border="0" cellpadding="5" cellspacing="0" summary="">
    <tr>
      <td valign="top"><apll>Z←<i>f</i>⍤[X] Y R</apll></td>
      <td></td>
      <td></td>
      <td>Applies the monadic function <apll><i>f</i></apll> to the rank-<apll><i>r</i></apll> cells of <apll>R</apll>, where <apll><i>r</i></apll> is defined by <apll>Y</apll> and restores the cells to the result as per <apll>X</apll>.</td>
    </tr>
    </table>
  </td>
</tr>
<tr>
  <td><apll>R</apll> is an arbitrary array, <apll><i>f</i></apll> is an arbitrary monadic function, <apll>X</apll> is an origin-sensitive integer scalar or vector, and <apll>Y</apll> is an integer scalar or vector.</td>
</tr>
<tr>
  <td>If <apll>1&lt;⍴⍴Y</apll>, signal a <apll>RANK ERROR</apll>.</td>
</tr>
<tr>
  <td>If <apll>1=⍴⍴Y</apll> and <apll>~(⍴Y)∊1 2 3</apll>, signal a <apll>LENGTH ERROR</apll>.</td>
</tr>
<tr>
  <td><apll>Y</apll> is a scalar or one-, two-, or three-element integer vector that describes the cell size of the arguments.  When it is a three-element vector, the first element specifies the cell size of the right argument when the derived function is called monadically; the second and third elements specify the left and right argument cell sizes when the derived function is called dyadically.  When it is a two-element vector, the two values are used for the left and right arguments cell sizes when the derived function is called dyadically; if the derived function is called monadically, the cell size is the second value of the two.  When it is a scalar or one-element vector, the single value is used for all three cell sizes.  Moreover, the value of <apll>Y</apll> for the monadic derived function case may be positive or negative with an absolute value no larger than <apll>⍴⍴R</apll>.  In this case (first element only), the above rules may be summarized by setting <apll>Y</apll> to the one-element integer vector <apll>(-⍴⍴R)⌈(⍴⍴R)⌊1↑⌽3⍴⌽Y</apll>.</td>
</tr>
<tr>
  <td>The cells from <apll>R</apll> are of rank <apll>|Y</apll>.</td>
</tr>
<tr>
  <td>If <apll>Y</apll> is positive, the cells from <apll>R</apll> are taken from the right end of the shape vector; if negative, the cells are taken from the left end of the shape vector.  In particular, <apll>CR←(-Y)↑⍴R</apll> is the shape of the righthand cells, and <apll>FR←(-Y)↓⍴R</apll> is the shape of the righthand frame.</td>
</tr>
<tr>
  <td>Loop through the frame applying <apll><i>f</i></apll> to the shape <apll>CR</apll> cells from <apll>R</apll>.</td>
</tr>
<tr>
  <td>The result <apll>Z</apll> is the <b>conforming</b> disclose of the above, using <apll>[X]</apll>, if present.</td>
</tr>
</table>
<br />
<p>The monadic derived function of this dyadic operator is implemented by calling an internal magic function similar to the following:</p>


<apll>&nbsp;&nbsp;&nbsp;&nbsp;∇ Z←(LO F X) R;O</apll><br />
<apll><pre>
<apll>[1]&nbsp;&nbsp;&nbsp;X←1⍴X</apll><br />
    ∇ Z←(LO #MonRank[X] Y) R;YR
<apll>[2]&nbsp;&nbsp;&nbsp;O←⍴⍴R</apll><br />
[1]   YR←(1↑⌽3⍴⌽Y)⌊⍴⍴R
<apll>[3]&nbsp;&nbsp;&nbsp;X←(-O)⌈O⌊X</apll><br />
[2]   if 0>YR ⋄ YR←0⌈YR+⍴⍴R ⋄ :end
<apll>[4]&nbsp;&nbsp;&nbsp;Z←LO¨⊂[⍳-X]R⋄→0</apll><br />
[3]   Z←LO¨⊂[(-YR)↑⍳⍴⍴R] R ⋄ →L1
<apll>[5]&nbsp;&nbsp;&nbsp;⎕PROTOTYPE:Z←⊃LO¨¨⊂[-X]¨0⍴⊂R</apll><br />
[4]   ⎕PRO:YR←(1↑⌽3⍴⌽Y)⌊⍴⍴R
<apll>&nbsp;&nbsp;&nbsp;&nbsp;∇</apll>
[5]   :if 0>YR ⋄ YR←0⌈YR+⍴⍴R ⋄ :end
[6]   Z←⊃LO¨¨⊂[(-YR)↑⍳⍴⍴R]¨0⍴⊂R
[7]  L1::if 0=⎕NC 'X' ⋄ Z←⊃Z ⋄ :else ⋄ Z←⊃[X] Z ⋄ :end
    ∇</pre></apll>


'''Dyadic Derived Function'''
<br />


<apll>&nbsp;&nbsp;&nbsp;&nbsp;∇ Z←L (LO F X) R;O</apll><br />
==Rank Dyadic Derived Function==
<apll>[1]&nbsp;&nbsp;&nbsp;X←1↓⌽3⍴⌽X</apll><br />
<apll>[2]&nbsp;&nbsp;&nbsp;O←(⍴⍴L),⍴⍴R</apll><br />
<apll>[3]&nbsp;&nbsp;&nbsp;X←(-O)⌈O⌊X</apll><br />
<apll>[4]&nbsp;&nbsp;&nbsp;Z←(⊂[⍳-1↑X]L)LO¨⊂[⍳-1↓X]R⋄→0</apll><br />
<apll>[5]&nbsp;&nbsp;&nbsp;⎕PROTOTYPE:Z←⊃(⊂[⍳-1↑X]¨0⍴⊂L)LO¨¨⊂[⍳-1↓X]¨0⍴⊂R</apll><br />
<apll>&nbsp;&nbsp;&nbsp;&nbsp;∇</apll>


Both of the above functions implement their respective derived function except for some final processing which is essentially a disclose but one which allows for mismatched ranks. That part is implemented by the following function where <apll>L</apll> has already been calculated as the maximum rank across all items:
<table border="1" cellpadding="5" cellspacing="0" rules="none" summary="">
<tr>
  <td>
    <table border="0" cellpadding="5" cellspacing="0" summary="">
    <tr>
      <td valign="top"><apll>Z←L <i>f</i>⍤[X] Y R</apll></td>
      <td></td>
      <td></td>
      <td>Applies the dyadic function <apll><i>f</i></apll> between the rank-<apll><i>l</i></apll> cells of <apll>L</apll> and the rank-<apll><i>r</i></apll> cells of <apll>R</apll> and restores the cells to the result as per <apll>X</apll>, where <apll><i>l</i></apll> and <apll><i>r</i></apll> are defined by <apll>Y</apll>.</td>
    </tr>
    </table>
  </td>
</tr>
<tr>
  <td><apll>L</apll> and <apll>R</apll> are arbitrary arrays, <apll><i>f</i></apll> is an arbitrary dyadic function, <apll>X</apll> is an origin-sensitive integer scalar or vector, and <apll>Y</apll> is an integer scalar or vector.</td>
</tr>
<tr>
  <td>If <apll>1&lt;⍴⍴Y</apll>, signal a <apll>RANK ERROR</apll>.</td>
</tr>
<tr>
  <td>If <apll>1=⍴⍴Y</apll> and <apll>~(⍴Y)∊1 2 3</apll>, signal a <apll>LENGTH ERROR</apll>.</td>
</tr>
<tr>
  <td><apll>Y</apll> is a scalar or one-, two-, or three-element integer vector that describes the cell size of the arguments.  When it is a three-element vector, the first element specifies the cell size of the right argument when the derived function is called monadically; the second and third elements specify the left and right argument cell sizes when the derived function is called dyadically.  When it is a two-element vector, the two values are used for the left and right arguments cell sizes when the derived function is called dyadically; if the derived function is called monadically, the cell size is the second value of the two.  When it is a scalar or one-element vector, the single value is used for all three cell sizes. 


'''Internal Conform Function'''
Moreover, the values of <apll>Y</apll> for the dyadic derived function case may be positive or negative with an absolute value no larger than <apll>(⍴⍴L),⍴⍴R</apll>.  In this case (second and third elements only), the above rules may be summarized by setting <apll>Y</apll> to the two-element integer vector <apll>(-(⍴⍴L),⍴⍴R)⌈((⍴⍴L),⍴⍴R)⌊1↓⌽3⍴⌽Y</apll>.</td>
</tr>
<tr>
  <td>The cells from <apll>L</apll> are of rank <apll>|1↑Y</apll>; the cells from <apll>R</apll> are of rank <apll>|1↓Y</apll>.</td>
</tr>
<tr>
  <td>If <apll>1↑Y</apll> is positive, the cells from <apll>L</apll> are taken from the right end of the shape vector; if negative, the cells are taken from the left end of the shape vector.  In particular, <apll>CL←(-1↑Y)↑⍴L</apll> is the shape of the lefthand cells, and <apll>FL←(-1↑Y)↓⍴L</apll> is the shape of the lefthand frame.</td>
</tr>
<tr>
  <td>If <apll>1↓Y</apll> is positive, the cells from <apll>R</apll> are taken from the right end of the shape vector; if negative, the cells are taken from the left end of the shape vector.  In particular, <apll>CR←(-1↓Y)↑⍴R</apll> is the shape of the righthand cells, and <apll>FR←(-1↓Y)↓⍴R</apll> is the shape of the righthand frame.</td>
</tr>
<tr>
  <td>If <apll>FL</apll> and <apll>FR</apll> are both non-empty and <apll>(⍴FL)≠⍴FR</apll>, signal a <apll>RANK ERROR</apll>; if the shapes of <apll>FL</apll> and <apll>FR</apll> are the same, but their values differ, signal a <apll>LENGTH ERROR</apll>.</td>
</tr>
<tr>
  <td>Loop through the frames (scalar extending as necessary) applying <apll><i>f</i></apll> between the shape <apll>CL</apll> cells from <apll>L</apll> and the shape <apll>CR</apll> cells from <apll>R</apll>.</td>
</tr>
<tr>
  <td>The result <apll>Z</apll> is the <b>conforming</b> disclose of the above, using <apll>[X]</apll>, if present.</td>
</tr>
</table>
<br />
<p>The dyadic derived function of this dyadic operator is implemented by calling an internal magic function similar to the following:</p>


<apll>&nbsp;&nbsp;&nbsp;&nbsp;∇ Z←L F R</apll><br />
<apll><pre>
<apll>[1]&nbsp;&nbsp;&nbsp;Z←⊃(((L-∊⍴∘⍴¨R)⍴¨1),¨⍴¨R)⍴¨R</apll><br />
    ∇ Z←L (LO #DydRank[X] Y) R;YL;YR
<apll>&nbsp;&nbsp;&nbsp;&nbsp;∇</apll>
[1]  (YL YR)←(1↓⌽3⍴⌽Y)⌊(⍴⍴L),⍴⍴R
[2]  :if 0>YL ⋄ YL←0⌈YL+⍴⍴L ⋄ :end
[3]  :if 0>YR ⋄ YR←0⌈YR+⍴⍴R ⋄ :end
[4]  Z←(⊂[(-YL)↑⍳⍴⍴L] L) LO¨⊂[(-YR)↑⍳⍴⍴R] R ⋄ →L1
[5]  ⎕PRO:(YL YR)←(1↓⌽3⍴⌽Y)⌊(⍴⍴L),⍴⍴R
[6]  :if 0>YL ⋄ YL←0⌈YL+⍴⍴L ⋄ :end
[7]  :if 0>YR ⋄ YR←0⌈YR+⍴⍴R ⋄ :end
[8]  Z←⊃(⊂[(-YL)↑⍳⍴⍴L]¨0⍴⊂L) LO¨¨⊂[(-YR)↑⍳⍴⍴R]¨0⍴⊂R
[9]  L1::if 0=⎕NC 'X' ⋄ Z←⊃Z ⋄ :else ⋄ Z←⊃[X] Z ⋄ :end
    </pre></apll>
 
For example, the rank operator can emulate laminate between the following two vectors to produce the first result, but not the second without help from the axis operator:
 
<apll><pre>
      L←'abcdef' {diamond} R←⍳⍴L
      L ,⍤0 R                  a.k.a. L,[1.5] R
a 1
b 2
c 3
d 4
e 5
f 6
      L ,⍤[1] 0 R              a.k.a. L,[0.5] R
a b c d e f
1 2 3 4 5 6</pre></apll>
 
==Atop Monadic Derived Function==
 
<table border="1" cellpadding="5" cellspacing="0" rules="none" summary="">
<tr>
  <td>
    <table border="0" cellpadding="5" cellspacing="0" summary="">
    <tr>
      <td valign="top"><apll>Z←<i>f</i>⍤<i>g</i> R</apll></td>
      <td></td>
      <td></td>
      <td>Applies the monadic functions <apll><i>f</i></apll> and <apll><i>g</i></apll> to <apll>R</apll> as in <apll> f g R</apll>.</td>
    </tr>
    </table>
  </td>
</tr>
<tr>
  <td><apll>R</apll> is an arbitrary array, <apll><i>f</i></apll> and <apll><i>g</i></apll> are both arbitrary monadic functions.</td>
</tr>
</table>
 
<br />
<p>The monadic and dyadic derived functions of this dyadic operator are implemented by calling an internal magic function similar to the following:</p>
 
<apll><pre>
#Atop←{⍺←⊢ ⋄ ⍺⍺ ⍺ ⍵⍵ ⍵}
</pre></apll>
 
For example,
 
<apll><pre>      ⌈⍤-¯1.1      ⍝ where f⍤g R ←→ f g R
2
</pre></apll>
 
==Atop Dyadic Derived Function==
 
<table border="1" cellpadding="5" cellspacing="0" rules="none" summary="">
<tr>
  <td>
    <table border="0" cellpadding="5" cellspacing="0" summary="">
    <tr>
      <td valign="top"><apll>Z←L <i>f</i>⍤<i>g</i> R</apll></td>
      <td></td>
      <td></td>
      <td>Applies the monadic function <apll><i>f</i></apll> to the result of applying the dyadic function <apll><i>g</i></apll> between <apll>L</apll> and the <apll>R</apll>.  That is, it is equivalent to <apll><i>f</i> L <i>g</i> R</apll>.</td>
    </tr>
    </table>
  </td>
</tr>
<tr>
  <td><apll>L</apll> and <apll>R</apll> are arbitrary arrays, <apll><i>f</i></apll> is an arbitrary monadic function, <apll><i>g</i></apll> is an arbitrary dydadic function.</td>
</tr>
</table>
 
<br />
<p>The monadic and dyadic derived functions of this dyadic operator are implemented by calling an internal magic function similar to the following:</p>
 
<apll><pre>
#Atop←{⍺←⊢ ⋄ ⍺⍺ ⍺ ⍵⍵ ⍵}
</pre></apll>
 
For example,
 
<apll><pre>      2⌈⍤-¯1.1      ⍝ where L f⍤g R ←→ f L g R
4
</pre></apll>
 
== Acknowledgments ==
 
The APL functions for the Rank operator shown above were originally based upon those found in the paper J. Philip Benkhard, "[http://portal.acm.org/citation.cfm?id=114058&dl=GUIDE&coll=GUIDE&CFID=98347615&CFTOKEN=27795431 Extending structure, type, and expression in APL2]", ACM SIGAPL APL Quote Quad, v.21 n.4, p.20-38, Aug. 1991, but later was modified to reflect the definition of the Rank operator in the ISO-IEC 13751 Extended APL Standard.
 
The Atop operator was defined by the developers at Dyalog APL.

Latest revision as of 06:11, 14 October 2023

Rank Monadic Derived Function

Z←f⍤[X] Y R Applies the monadic function f to the rank-r cells of R, where r is defined by Y and restores the cells to the result as per X.
R is an arbitrary array, f is an arbitrary monadic function, X is an origin-sensitive integer scalar or vector, and Y is an integer scalar or vector.
If 1<⍴⍴Y, signal a RANK ERROR.
If 1=⍴⍴Y and ~(⍴Y)∊1 2 3, signal a LENGTH ERROR.
Y is a scalar or one-, two-, or three-element integer vector that describes the cell size of the arguments. When it is a three-element vector, the first element specifies the cell size of the right argument when the derived function is called monadically; the second and third elements specify the left and right argument cell sizes when the derived function is called dyadically. When it is a two-element vector, the two values are used for the left and right arguments cell sizes when the derived function is called dyadically; if the derived function is called monadically, the cell size is the second value of the two. When it is a scalar or one-element vector, the single value is used for all three cell sizes. Moreover, the value of Y for the monadic derived function case may be positive or negative with an absolute value no larger than ⍴⍴R. In this case (first element only), the above rules may be summarized by setting Y to the one-element integer vector (-⍴⍴R)⌈(⍴⍴R)⌊1↑⌽3⍴⌽Y.
The cells from R are of rank |Y.
If Y is positive, the cells from R are taken from the right end of the shape vector; if negative, the cells are taken from the left end of the shape vector. In particular, CR←(-Y)↑⍴R is the shape of the righthand cells, and FR←(-Y)↓⍴R is the shape of the righthand frame.
Loop through the frame applying f to the shape CR cells from R.
The result Z is the conforming disclose of the above, using [X], if present.


The monadic derived function of this dyadic operator is implemented by calling an internal magic function similar to the following:

    ∇ Z←(LO #MonRank[X] Y) R;YR
[1]   YR←(1↑⌽3⍴⌽Y)⌊⍴⍴R
[2]   if 0>YR ⋄ YR←0⌈YR+⍴⍴R ⋄ :end
[3]   Z←LO¨⊂[(-YR)↑⍳⍴⍴R] R ⋄ →L1
[4]   ⎕PRO:YR←(1↑⌽3⍴⌽Y)⌊⍴⍴R
[5]   :if 0>YR ⋄ YR←0⌈YR+⍴⍴R ⋄ :end
[6]   Z←⊃LO¨¨⊂[(-YR)↑⍳⍴⍴R]¨0⍴⊂R
[7]   L1::if 0=⎕NC 'X' ⋄ Z←⊃Z ⋄ :else ⋄ Z←⊃[X] Z ⋄ :end
    ∇


Rank Dyadic Derived Function

Z←L f⍤[X] Y R Applies the dyadic function f between the rank-l cells of L and the rank-r cells of R and restores the cells to the result as per X, where l and r are defined by Y.
L and R are arbitrary arrays, f is an arbitrary dyadic function, X is an origin-sensitive integer scalar or vector, and Y is an integer scalar or vector.
If 1<⍴⍴Y, signal a RANK ERROR.
If 1=⍴⍴Y and ~(⍴Y)∊1 2 3, signal a LENGTH ERROR.
Y is a scalar or one-, two-, or three-element integer vector that describes the cell size of the arguments. When it is a three-element vector, the first element specifies the cell size of the right argument when the derived function is called monadically; the second and third elements specify the left and right argument cell sizes when the derived function is called dyadically. When it is a two-element vector, the two values are used for the left and right arguments cell sizes when the derived function is called dyadically; if the derived function is called monadically, the cell size is the second value of the two. When it is a scalar or one-element vector, the single value is used for all three cell sizes. Moreover, the values of Y for the dyadic derived function case may be positive or negative with an absolute value no larger than (⍴⍴L),⍴⍴R. In this case (second and third elements only), the above rules may be summarized by setting Y to the two-element integer vector (-(⍴⍴L),⍴⍴R)⌈((⍴⍴L),⍴⍴R)⌊1↓⌽3⍴⌽Y.
The cells from L are of rank |1↑Y; the cells from R are of rank |1↓Y.
If 1↑Y is positive, the cells from L are taken from the right end of the shape vector; if negative, the cells are taken from the left end of the shape vector. In particular, CL←(-1↑Y)↑⍴L is the shape of the lefthand cells, and FL←(-1↑Y)↓⍴L is the shape of the lefthand frame.
If 1↓Y is positive, the cells from R are taken from the right end of the shape vector; if negative, the cells are taken from the left end of the shape vector. In particular, CR←(-1↓Y)↑⍴R is the shape of the righthand cells, and FR←(-1↓Y)↓⍴R is the shape of the righthand frame.
If FL and FR are both non-empty and (⍴FL)≠⍴FR, signal a RANK ERROR; if the shapes of FL and FR are the same, but their values differ, signal a LENGTH ERROR.
Loop through the frames (scalar extending as necessary) applying f between the shape CL cells from L and the shape CR cells from R.
The result Z is the conforming disclose of the above, using [X], if present.


The dyadic derived function of this dyadic operator is implemented by calling an internal magic function similar to the following:

    ∇ Z←L (LO #DydRank[X] Y) R;YL;YR
[1]   (YL YR)←(1↓⌽3⍴⌽Y)⌊(⍴⍴L),⍴⍴R
[2]   :if 0>YL ⋄ YL←0⌈YL+⍴⍴L ⋄ :end
[3]   :if 0>YR ⋄ YR←0⌈YR+⍴⍴R ⋄ :end
[4]   Z←(⊂[(-YL)↑⍳⍴⍴L] L) LO¨⊂[(-YR)↑⍳⍴⍴R] R ⋄ →L1
[5]   ⎕PRO:(YL YR)←(1↓⌽3⍴⌽Y)⌊(⍴⍴L),⍴⍴R
[6]   :if 0>YL ⋄ YL←0⌈YL+⍴⍴L ⋄ :end
[7]   :if 0>YR ⋄ YR←0⌈YR+⍴⍴R ⋄ :end
[8]   Z←⊃(⊂[(-YL)↑⍳⍴⍴L]¨0⍴⊂L) LO¨¨⊂[(-YR)↑⍳⍴⍴R]¨0⍴⊂R
[9]   L1::if 0=⎕NC 'X' ⋄ Z←⊃Z ⋄ :else ⋄ Z←⊃[X] Z ⋄ :end
    ∇

For example, the rank operator can emulate laminate between the following two vectors to produce the first result, but not the second without help from the axis operator:

      L←'abcdef' ⋄ R←⍳⍴L
      L ,⍤0 R                   a.k.a. L,[1.5] R
 a 1
 b 2
 c 3
 d 4
 e 5
 f 6
      L ,⍤[1] 0 R               a.k.a. L,[0.5] R
 a b c d e f
 1 2 3 4 5 6

Atop Monadic Derived Function

Z←fg R Applies the monadic functions f and g to R as in f g R.
R is an arbitrary array, f and g are both arbitrary monadic functions.


The monadic and dyadic derived functions of this dyadic operator are implemented by calling an internal magic function similar to the following:

#Atop←{⍺←⊢ ⋄ ⍺⍺ ⍺ ⍵⍵ ⍵}

For example,

      ⌈⍤-¯1.1      ⍝ where f⍤g R ←→ f g R
2

Atop Dyadic Derived Function

Z←L fg R Applies the monadic function f to the result of applying the dyadic function g between L and the R. That is, it is equivalent to f L g R.
L and R are arbitrary arrays, f is an arbitrary monadic function, g is an arbitrary dydadic function.


The monadic and dyadic derived functions of this dyadic operator are implemented by calling an internal magic function similar to the following:

#Atop←{⍺←⊢ ⋄ ⍺⍺ ⍺ ⍵⍵ ⍵}

For example,

      2⌈⍤-¯1.1      ⍝ where L f⍤g R ←→ f L g R
4

Acknowledgments

The APL functions for the Rank operator shown above were originally based upon those found in the paper J. Philip Benkhard, "Extending structure, type, and expression in APL2", ACM SIGAPL APL Quote Quad, v.21 n.4, p.20-38, Aug. 1991, but later was modified to reflect the definition of the Rank operator in the ISO-IEC 13751 Extended APL Standard.

The Atop operator was defined by the developers at Dyalog APL.