﻿http://wiki.dyalog.bramley/index.php/Rank_and_Key_Speed-Ups

x←?1e6⍴1000                                    
s←x[⍋x]  

a.  ¯1+{≢⍵}⌸(⍳1000),x              → 4.64E¯3 |    0% ⎕⎕⎕⎕⎕                                   
b.  ¯1+{≢⍵}⌸(⍳1+⌈/x),x             → 5.62E¯3 |  +21% ⎕⎕⎕⎕⎕⎕                                  
c.  count⊣count[x]+←1⊣count←1000⍴0 → 7.32E¯3 |  +57% ⎕⎕⎕⎕⎕⎕⎕⎕                                
d.  t-¯1↓¯1,t←(s≠1↓s,⍴s)/⍳⍴s       → 1.17E¯2 | +152% ⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕                           
e.  -2-/¯1,(s≠1↓s,⍴s)/⍳⍴s          → 1.14E¯2 | +144% ⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕                           
f.  -2-/¯1,(s≠1↓s,⍴s)/⍳⍴s←{⍵[⍋⍵]}x → 1.49E¯2 | +220% ⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕                       
g.  -2-/¯1,(s≠1↓s,⍴s)/⍳⍴s←x[⍋x]    → 3.49E¯2 | +652% ⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕

u←(⎕A,⎕D)[?200 29⍴36]
x←u[?2000⍴1↑⍴u;]     
y←u[?2000⍴1↑⍴u;]
   
  x≡⍤1⊢y → 2.58E¯5 |    0% ⎕⎕⎕⎕⎕⎕⎕                                 
  ∧/x=y  → 1.56E¯4 | +507% ⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕

__________________________________________________________________________________

e-mail to Dick Bowman, 2013-09-13

The "atop" definition for 2-trains makes it possible to write a large class of expressions as trains.  In an APL expression, when you encounter a dyadic function, write it as a 3-train; when you encounter a monadic function, write it as a 2-train.

More practically, some 2-trains are expected to be very useful in practical applications, and we have implemented special code for them.  For example:

Let x and y be vectors.  x(⍳∘1>)y ←→ ⍳∘1(x>y) ←→ (x>y)⍳1.  That is, x(⍳∘1>)y is the first place where x>y.  In general, the pattern (idiom) is x(⍳∘b c)y where b is 0 or 1 and c is < ≤ = ≠ ≥ >.  If you are "lucky", the "hit" happens near the beginning of the vector, and the special code is "infinitely" faster.  Even if the hit happens near the end, you save on not generating the boolean vector and then searching it.

Similarly, x(∨/>)y ←→ ∨/x>y, that is, whether some element of x is greater than its corresponding element in y.  And in general, x(f/c)y where f is ∨ ∧ + and c is < ≤ = ≠ ≥ >.

A benchmark to demonstrate the benefits of the special code:

      x←?1e6⍴2e4
      y←?1e6⍴2e4
      y1←99999+y
            
      cmpx 'x(⍳∘1>)y' 'x(⍳∘1>)y1' '(x>y)⍳1'
  x(⍳∘1>)y  → 4.88E¯7 |       0%                                         
* x(⍳∘1>)y1 → 7.33E¯4 | +150000% ⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕             
  (x>y)⍳1   → 1.08E¯3 | +220600% ⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕

The first expression demonstrates a hit near the beginning.  The second (non-equivalent) expression demonstrates a hit at the end.  The third, equivalent to the first, is the conventional expression.

The above expressions also demonstrate another opportunity for special code: ?1e6⍴2e4 ←→ 1e6(?⍴)2e4.  The latter expression suggests that we can avoid generating 1e6⍴2e4.  This would be especially striking for ?x⍴2 and ⎕io←0 (random bits).

The special codes could have been done for dfns, {(⍺>⍵)⍳1} and {?⍺⍴⍵}, but in all the years of dfns nobody thought to do these special codes.  I suggest that trains and function composition make one more sensitive to such possibilities, an argument for trains as a tool of thought.  Of course, now that we recognize them, we may in the future also implement {(⍺>⍵)⍳1} and {?⍺⍴⍵} with special code, for people who prefer dfns.