Tile Operator

Roger Hui



Based on the cut operator. The computation is sometimes referred to as tessellation, moving window, or stencil code.
 

0. Desiderata

•   Simpler than the ±3-cut.
No arbitrary numeric code operand (the 3 and ¯3 in the cut operator).
In common cases ⍴⍵ is a prefix of ⍴⍺⍺ T ⍵⍵ ⊢⍵ . In particular, if the result of ⍺⍺ is a scalar then ⍴⍵ ←→ ⍺⍺ T ⍵⍵ ⊢⍵ . (The last equivalence facilitates repeated application of ⍺⍺ T ⍵⍵ ⊢⍵ .)
The implementation should be efficient, especially on boolean and small-integer arguments.

 

1. Definition

Dyadic operator: ⍺⍺ T ⍵⍵ ⊢⍵

The left operand function ⍺⍺ is applied to (possibly overlapping) tiles. In general, the right operand ⍵⍵ is a 2-row integer matrix with up to ⍴⍴⍵ columns. The first row are the tile sizes; the second row are the “movements”, how much to move the tile in each step. The columns of ⍵⍵ apply independently to the axes of . If ⍵⍵ has fewer columns than the rank of then it applies to the leading axes. A scalar or vector ⍵⍵ is treated as ⍉(⍪⍵⍵),1 (as if the movements are 1).

If s is a tile size thenbehaves as if padded with ⌊(s-1)÷2 fill elements. ⍺⍺ is invoked dyadically with a vector left argument indicating for each axis the number of fill elements and on what side. When the movement is 1, each element of in its turn is the middle of a tile. The predominant cases are a tile size which is odd and a movement of 1.

This text is composed with ⎕io←1 . The tile operator works in either index-origin.
 

2. Examples

2.1 Common Case: Odd Size and Movement = 1

   ⎕←s←{⊂⍵}T 3 ⍳8
┌─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┐
│0 1 2│1 2 3│2 3 4│3 4 5│4 5 6│5 6 7│6 7 8│7 8 0│
└─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┘
   ⍴s
8
   {(¯2↑⍕⍺),' f ',⍕⍵}T 3 ⍳8
 1 f 0 1 2
 0 f 1 2 3
 0 f 2 3 4
 0 f 3 4 5
 0 f 4 5 6
 0 f 5 6 7
 0 f 6 7 8
¯1 f 7 8 0
⍝      ↑ middle

   {⊂⍺⍵}T 5 ⍳6
┌─────────────┬─────────────┬─────────────┬─────────────┬─
│┌─┬─────────┐│┌─┬─────────┐│┌─┬─────────┐│┌─┬─────────┐│
││2│0 0 1 2 3│││1│0 1 2 3 4│││0│1 2 3 4 5│││0│2 3 4 5 6││...
│└─┴─────────┘│└─┴─────────┘│└─┴─────────┘│└─┴─────────┘│
└─────────────┴─────────────┴─────────────┴─────────────┴─
                 ─┬─────────────┬──────────────┬──────────────┐
                  │┌─┬─────────┐│┌──┬─────────┐│┌──┬─────────┐│
              ... ││0│3 4 5 6 7│││¯1│4 5 6 7 0│││¯2│5 6 7 0 0││
                  │└─┴─────────┘│└──┴─────────┘│└──┴─────────┘│
                 ─┴─────────────┴──────────────┴──────────────┘
   {(¯2↑⍕⍺),' f ',⍕⍵}T 5 ⍳6
 2 f 0 0 1 2 3
 1 f 0 1 2 3 4
 0 f 1 2 3 4 5
 0 f 2 3 4 5 6
¯1 f 3 4 5 6 0
¯2 f 4 5 6 0 0

In contrast to the cut operator, the tile operator:

•   Each element ofin its turn is the middle of a tile.
Unless the tile size is 1, the tile operator always has shards (incomplete tiles) padded with fill elements.
Shards are symmetric on each side.
The right arguments of the operand function ⍺⍺ have uniform shape.
The operand function is invoked dyadically; the left argument indicates the number of fill elements and on what side they are missing.
It is up to the operand function to decide what to do about shards.
   {⊂⍺⍵}T 3 5 ⊢4 6⍴⍳24
   {⍵[2;3]}T 3 5 ⊢4 6⍴⍳24
 1  2  3  4  5  6
 7  8  9 10 11 12
13 14 15 16 17 18
19 20 21 22 23 24

   dot←{('.',⎕a)[(' ',⎕a)⍳⍵]}
   {⊂(2 0 3 0⍕⍺)(dot ⍵)}T 3 5 ⊢ 4 6⍴⎕a

   {⍵[2;3]}T 3 5 ⊢ 4 6⍴⎕a
ABCDEF
GHIJKL
MNOPQR
STUVWX

2.2 Even Size

For even tile sizes, the “middle” consists of two elements which are moved according to the movement parameter (equal to 1 in these examples).

   ⎕←s←{⊂⍵}T 2 ⍳8
┌───┬───┬───┬───┬───┬───┬───┐
│1 2│2 3│3 4│4 5│5 6│6 7│7 8│
└───┴───┴───┴───┴───┴───┴───┘
   ⍴s
7
   {(¯2↑⍕⍺),' f ',⍕⍵}T 2 ⍳8
 0 f 1 2
 0 f 2 3
 0 f 3 4
 0 f 4 5
 0 f 5 6
 0 f 6 7
 0 f 7 8
⍝    ↑ ↑ middle

   ⎕←s←{⊂⍵}T 4 ⍳8
┌───────┬───────┬───────┬───────┬───────┬───────┬───────┐
│0 1 2 3│1 2 3 4│2 3 4 5│3 4 5 6│4 5 6 7│5 6 7 8│6 7 8 0│
└───────┴───────┴───────┴───────┴───────┴───────┴───────┘
   ⍴s
7
   {(¯2↑⍕⍺),' f ',⍕⍵}T 4 ⍳8 
 1 f 0 1 2 3  
 0 f 1 2 3 4
 0 f 2 3 4 5
 0 f 3 4 5 6
 0 f 4 5 6 7
 0 f 5 6 7 8
¯1 f 6 7 8 0
⍝      ↑ ↑ middle

   ⎕←s←{⊂⍵}T 6 ⍳8
┌───────────┬───────────┬───────────┬───────────┬─
│0 0 2 3 4 5│0 2 3 4 5 6│2 3 4 5 6 7│3 4 5 6 7 8│...
└───────────┴───────────┴───────────┴───────────┴─
                       ─┬───────────┬───────────┬───────────┐
                    ... │4 5 6 7 8 9│5 6 7 8 9 0│6 7 8 9 0 0│
                       ─┴───────────┴───────────┴───────────┘
   ⍴s
7
   {(¯2↑⍕⍺),' f ',⍕⍵}T 6 ⍳8 
 2 f 0 0 1 2 3 4    
 1 f 0 1 2 3 4 5  
 0 f 1 2 3 4 5 6
 0 f 2 3 4 5 6 7
 0 f 3 4 5 6 7 8
¯1 f 4 5 6 7 8 0 
¯2 f 5 6 7 8 0 0    
⍝        ↑ ↑ middle

2.3 Movement ≠ 1

   {⊂⍵}T(⍪3 2) ⍳8
┌─────┬─────┬─────┬─────┐
│0 1 2│2 3 4│4 5 6│6 7 8│
└─────┴─────┴─────┴─────┘
   {(¯2↑⍕⍺),' f ',⍕⍵}T(⍪3 2) ⍳8
 1 f 0 1 2  
 0 f 2 3 4
 0 f 4 5 6
 0 f 6 7 8
⍝      ↑ middle

   {⊂⍵}T(⍪5 2) ⍳8
┌─────────┬─────────┬─────────┬─────────┐
│0 0 1 2 3│1 2 3 4 5│3 4 5 6 7│5 6 7 8 0│
└─────────┴─────────┴─────────┴─────────┘
   {(¯2↑⍕⍺),' f ',⍕⍵}T(⍪5 2) ⍳8
 2 f 0 0 1 2 3
 0 f 1 2 3 4 5
 0 f 3 4 5 6 7
¯1 f 5 6 7 8 0
⍝        ↑ middle

The last results are not symmetric with respect to the shards, but that is a “fault” of the right argument. A symmetric result obtains from a right argument with an appropriate length.

   {⊂⍵}T(⍪5 2) ⍳9
┌─────────┬─────────┬─────────┬─────────┬─────────┐
│0 0 1 2 3│1 2 3 4 5│3 4 5 6 7│5 6 7 8 9│7 8 9 0 0│
└─────────┴─────────┴─────────┴─────────┴─────────┘
   {(¯2↑⍕⍺),' f ',⍕⍵}T(⍪5 2) ⍳9
 2 f 0 0 1 2 3    
 0 f 1 2 3 4 5
 0 f 3 4 5 6 7
 0 f 5 6 7 8 9
¯2 f 7 8 9 0 0  
⍝        ↑ middle

2.4 Even Size and Movement ≠ 1

   {⊂⍵}T(⍪4 2) ⍳8
┌───────┬───────┬───────┬───────┐
│0 1 2 3│2 3 4 5│4 5 6 7│6 7 8 0│
└───────┴───────┴───────┴───────┘
   {(¯2↑⍕⍺),' f ',⍕⍵}T(⍪4 2) ⍳8
 1 f 0 1 2 3  
 0 f 2 3 4 5
 0 f 4 5 6 7
¯1 f 6 7 8 0
⍝      ↑ ↑ middle

   {⊂⍵}T(⍪6 2) ⍳8
┌───────────┬───────────┬───────────┬───────────┐
│0 0 1 2 3 4│1 2 3 4 5 6│3 4 5 6 7 8│5 6 7 8 0 0│
└───────────┴───────────┴───────────┴───────────┘
   {(⍕⍺),' f ',⍕⍵}T(⍪6 2) ⍳8
 2 f 0 0 1 2 3 4    
 0 f 1 2 3 4 5 6
 0 f 3 4 5 6 7 8
¯2 f 5 6 7 8 0 0
⍝        ↑ ↑ middle
   {⊂⍵}T(⍪5 4) ⍳16
┌─────────┬─────────┬───────────┬──────────────┐
│0 0 1 2 3│3 4 5 6 7│7 8 9 10 11│11 12 13 14 15│
└─────────┴─────────┴───────────┴──────────────┘
   {(¯2↑⍕⍺),' f',3 0⍕⍵}T(⍪5 4) ⍳16
 2 f  0  0  1  2  3      
 0 f  3  4  5  6  7
 0 f  7  8  9 10 11
 0 f 11 12 13 14 15
⍝           ↑ middle

   {⊂⍵}T(⍪5 4) ⍳17
┌─────────┬─────────┬───────────┬──────────────┬────────────┐
│0 0 1 2 3│3 4 5 6 7│7 8 9 10 11│11 12 13 14 15│15 16 17 0 0│
└─────────┴─────────┴───────────┴──────────────┴────────────┘
   {(¯2↑⍕⍺),' f',3 0⍕⍵}T(⍪5 4) ⍳17
 2 f  0  0  1  2  3      
 0 f  3  4  5  6  7
 0 f  7  8  9 10 11
 0 f 11 12 13 14 15
¯2 f 15 16 17  0  0     
⍝           ↑ middle

3. Model

assert←{⍺←'assertion failure' ⋄ 0∊⍵:⍺ ⎕SIGNAL 8 ⋄ shy←0}

T←{
  (⍺⍺{f←⍺⍺ ⋄ (3.2=⎕nc⊂,'f')>'⍺'∊⎕cr'f'}⍬)⍺⍺{⍺ ⍺⍺ ⍵}{
    ⎕io←0                        ⍝ ⎕io delenda est
    assert 0<⍴⍴⍵:
    assert 2≥⍴⍴⍵⍵:
    assert(2>⍴⍴⍵⍵)∨2=≢⍵⍵:
    assert 0<⍵⍵:
    assert ⍵⍵≡⌊⍵⍵:
    (s m)←↓(⍉1,⍨⍪)⍣(2>≢⍴⍵⍵)⊢⍵⍵   ⍝ size and movement
    assert(≢s)≤⍴⍴⍵:
    assert s≤(≢s)↑⍴⍵:

    ws←(≢s)↑⍴⍵
    n←⌈m÷⍨ws-~2|s
    j←⊃∘.,/⊂⍤0¨↓¨(m×⍳¨n)∘.+¨⍳¨s  ⍝ indices for each cell
    c←⌊2÷⍨s-1
    y←(ws+2×c)↑(-ws+c)↑⍵         ⍝ argument padded with fills
    ⍺:↑⍺⍺{⍬ ⍺⍺ ⍵⌷y}¨j            ⍝ left arg ⍬ if ⍺⍺ is a dfn ...
    d←0⌈((m×n-1)+s-1)-ws+c-1     ⍝ ... and ⍺ does not occur in it
    p←0~⍨¨0⌈c-   m×⍳¨c           ⍝ # pad elements on the left
    q←0~⍨¨0⌊d-⍨⌽¨m×⍳¨d           ⍝ # pad elements on the right
    i←,¨⍣(1=≢⍴⍵)⊃∘.,/p,¨((n-(≢¨p)+≢¨q)⍴¨0),¨q
    ↑i ⍺⍺{⍺ ⍺⍺ ⍵⌷y}¨j
  }⍵⍵⊢⍵
}

3.1 Tests

 z←test_tile io;⎕io;f;g;h;i;x
⍝ tests on the tile operator

 ⎕io←io

 x←1+?17⍴100
 f←{⎕io←0 ⋄ ↓(c,⍵,c←(⌊⍺÷2)⍴0)[(⍳≢⍵)∘.+⍳⍺]}

 h←{i←⎕io+⌊⍺÷2 ⋄ ⍵≡{⍵[i]}T ⍺⊢⍵}
 assert 1 3 5 7 9 h⍤0 1⊢x

 h←{(⍺ f ⍵)≡⍺⍺ T ⍺⊢⍵}
 assert 1 3 5 7 9{⊂⍵}h⍤0 1⊢x

 h←{(↑⍺ f ⍵)≡⍺⍺ T ⍺⊢⍵}
 assert 1 3 5 7 9{⍵}h⍤0 1⊢x
 assert 1 3 5 7 9⊢h⍤0 1⊢x

 g←{,¨(⌽i),(0⍴⍨(≢⍵)-2×≢i),-i←(⍳⌊⍺÷2)+~⎕io}
 h←{(⍺(g,(⍪f))⍵)≡⍺⍺ T ⍺⊢⍵}
 assert 1 3 5 7 9{⍺ ⍵}h⍤0 1⊢x
 assert 1 3 5 7 9((⊂⊣),(⊂⊢))h⍤0 1⊢x

 f←{t←k↓(-k←0,⌊2÷⍨⍺-1)↓⊢T ⍺⊢⍵ ⋄ 1=2|⍺:t≡⍪⍵ ⋄ t≡(¯1↓⍵),⍪1↓⍵}
 assert 1 2 3 4 5 6 7 8 f⍤0 1⊢x

 f←{∧/,(0=¯1↓t)∨(0=1↓t)∨(⊃⌽⍺)=-2-⌿t←{⍵}T(⍪⍺)⊢⍵}
 assert(↑1 2 3 4 5 6 7 8∘.,2 3 4)f⍤1⊢1+⍳≢x

 f←{
   t←{⍺ ⍵}T(⍪⍺)⊢⍵ 
   i←,↑t[;⎕io] ⋄ y←t[;1+⎕io]
   ((⍒i)≡⍳≢i)∧∧/∧/¨0=i↑¨y
 }
 assert(↑1 2 3 4 5 6 7 8∘.,2 3 4)f⍤1⊢x

 x←?12 17 5 7⍴100
 assert(⍴x)≡⍴{⊂⍵}T 3 7 5 3⊢x
 assert x≡{⍵[1+⎕io;3+⎕io;2+⎕io;1+⎕io]}T 3 7 5 3⊢x

 z←1⊣2 ⎕nq'.' 'wscheck'

4. Symbol

(Unicode 0x229E) is a possible symbol for the tile operator.
 

5. Optimizations

•   Sizes are odd and movements are 1.
Right argument is a matrix.
Right argument is boolean.
Sizes are odd, movements are 1,is boolean, and the operand function is {+/,A×⍵} (weighted sum or weighted average).
Sizes are odd, movements are 1,is boolean, and the operand function is {d<+/,A×⍵} .

 

created:  2016-07-19 15:25
updated: