# BQN runtime part 1. Requires:
# Type Fill Log GroupLen GroupOrd _fillBy_
# +-×÷⋆⌊⌈|<>=≠≤≥≢⊢⊣⥊∾⋈↑↓↕⊏⊑!⌜˙˜¨´`∘○⊸⟜◶⊘⍟
# Filled in by runtime: glyphs and default PrimInd
# Provides: all BQN primitives
Ind1 ← { 0 Fill +`(0⌈≠-1˙)⊸↑GroupLen+`𝕩 }
/ ← Ind1 ⊘ (Ind1⊸⊏) # LIMITED to natural number list 𝕩/𝕨
Decompose ← {0‿𝕩}
PrimInd ← {𝕩}
SetPrims ← {Decompose‿PrimInd ↩ 𝕩}
SetInv ← {{swapInverse 𝕏↩}𝕨 ⋄ inverse 𝕏↩}
IsArray ← 0=Type
IsAtom ← 1≤Type
Int ← (1=Type)◶⟨0,⌊⊸=⟩
Nat ← (1=Type)◶⟨0,|∘⌊⊸=⟩
ToArray ← <⍟IsAtom
IsSimple ← 1×´IsAtom⌜
Deshape ← IsArray◶{𝕩Fill⟨𝕩⟩}‿⥊
Cell ← ↓⟜≢
MatchS ← 1×´=¨
PermInv ← 1⌜⊸GroupOrd
_qSearch ← {+´·×`𝕗(1-=)⌜<}
_glyphLookup_ ← {
{PrimInd𝕩} ⊑ ((𝕘⊑˜𝕗_qSearch)⌜glyphs)˙
}
_isGlyph ← { (glyphs _qSearch 𝕗) = {PrimInd𝕩} }
IsJoin ← '∾'_isGlyph
IsTable ← '⌜'_isGlyph
DIsConst ← (4=0⊸⊑)◶0‿('˙'_isGlyph 2⊸⊑)
Split2 ← { s←2⊸×⌜↕(≠𝕩)÷2 ⋄ ⟨s⊏𝕩,(1⊸+⌜s)⊏𝕩⟩ }
_lookup_ ← {
k‿v←Split2 𝕘 ⋄ k _glyphLookup_ (v∾⟨𝕗⟩)
}
ScalId ← @ _lookup_ ⟨
'+',0 , '-',0
'×',1 , '÷',1
'⋆',1 , '¬',1
'⌊',∞ , '⌈',¯∞
'∨',0 , '∧',1
'≠',0 , '=',1
'>',0 , '≥',1
⟩
TabId ← {
id ← (4=0⊸⊑)◶⟨0,(IsTable 2⊸⊑)⟩◶⟨@,ScalId 1⊸⊑⟩ Decompose 𝕩
"´: Identity not found" ! @>id ⋄ <id
}
Identity ← { 𝕨 @⊸=◶⟨⊢⊘Reshape,TabId𝕩˙⟩ ScalId𝕩 }
_fold←{
"´: 𝕩 must be a list" ! 1==𝕩
𝕨 (0<≠)⊘1◶⟨Identity 𝕗˙, 𝔽´⟩ 𝕩
}
_eachd←{
_d←{ # Equal ranks
"Mapping: Equal-rank argument shapes don't agree" ! 𝕨 MatchS○≢ 𝕩
𝕨𝔽¨𝕩
}
_e←{ # 𝕨 has smaller or equal rank
p←≢𝕨 ⋄ k←=𝕨 ⋄ q←≢𝕩
"Mapping: Argument shape prefixes don't agree" ! p MatchS k↑q
l←1×´k↓q
m←≠a←⥊𝕨 ⋄ b←⥊𝕩
q⥊m (⊑⟜a𝔽l⊸×⊸+⊑b˙)⌜○↕ l×m>0
}
=○=◶⟨>○=◶⟨𝔽_e⋄𝔽˜_e˜⟩⋄𝔽_d⟩
}
_perv←{ # Pervasion
R←+○IsArray◶⟨
𝔽
{R⌜𝕩}⊘(>○IsArray◶{𝕨˙⊸R⌜𝕩}‿{R⟜(𝕩˙)⌜𝕨}) _fillBy_ {𝕨R𝕩}
{𝕨R _eachd𝕩} _fillBy_ {𝕨R𝕩}
⟩
}
# Sorting
CLE ← (≤⟜∞≤·=˜⊢)≤≤ # Place NaNs after other numbers
Cmp0 ← CLE˜-CLE
Cmp1 ← (0<1×´≢∘⊢)◶⟨1, IsArray∘⊢◶(1-2×≤)‿{𝕨Cmp1𝕩}⟜(0⊑⥊)⟩
CmpLen ← {
e←𝕨-○(1×´0⊸<⌜)𝕩
𝕨(e=0)◶⟨e,0⟩‿{
SM←Cmp0 ⋈ ≥⊑⋈
c‿r←𝕨SM○≠𝕩
l←𝕨{
i←0+´×`𝕨=¨𝕩
m←1×´i↕⊸⊏𝕨
{k‿l←SM´𝕩⋄c↩k⋄m×↩l}∘(<⊑⌜𝕨‿𝕩˙)⍟(r⊸>)i
m
}○{𝕩⊏˜(¯1+≠𝕩)⊸-⌜↕r}𝕩
⟨c,l⟩
}𝕩
}
_getCellCmp ← {
Ci←𝔽⋄c←𝕨⊣0⋄l←𝕩
Cc←{
a←𝕨⋄b←𝕩
S←(l⊸=)◶{S∘(1+𝕩)⍟(0⊸=)a Ci○(𝕩⊸+)b}‿c
S 0
}
(𝕨 ⊢⊘{𝕨⍟(0⊸=)𝕏} ci˙)⍟(1=l) cc
}
Cmp ← +○IsArray◶⟨
Cmp0
IsArray∘⊣◶⟨Cmp1,-Cmp1˜⟩
{
lc←𝕨CmpLen○≢𝕩
cc ← (⊑⟜(⥊𝕨))⊸Cmp⟜(⊑⟜(⥊𝕩)) _getCellCmp´ lc
Cc˜0
}
⟩
_grade ← {
gt ← 𝕗
cmps ← {𝕏˜}⌜⍟𝕗⟨Cmp,Cmp0,Cmp≤0˙,CLE⟩
_getC_ ← { 𝕨 𝕘{(𝕨 𝕏 _getCellCmp 𝕗)≤0˙}⍟(𝕩≤1) 𝔽 𝕩⊑cmps }
0 Fill {
"⍋𝕩: 𝕩 must have rank at least 1" ! 1≤=𝕩
l←≠𝕩
(2≤l)◶⟨↕∘l,{
m1←1=m←1×´1 Cell 𝕩
𝕩↩⥊𝕩
a0←1⋄ts←0⋄{a0×↩1≤𝕩⋄ts+↩𝕩}∘Type⌜𝕩
cs←a0+2×m1
Merge ← { # Merge sort
le ← 𝕩{𝕏○(⊑⟜𝕗)} _getC_ m cs
B←l⊸≤◶⊢‿l
(↕l){
i←-d←𝕨 ⋄ j←ei←ej←0
e←3 ⋄ G←LE○(⊑⟜(m⊸×⌜⍟(1-m1)𝕩)) ⋄ c←⟨1-G,0,1,2⟩
s←(8≤d)⊑⟨+,{(𝕩-1){e↩2⋄j↩i⋄i↩𝕩}⍟G⍟(1-e)𝕩}⟩
N←{i↩d+𝕨⋄ej↩B d+ei↩B j↩d+𝕩⋄e↩l≤j⋄S ei⋄i R j}
R←{𝕨e◶c𝕩}◶{e+↩2×ei=i↩1+𝕨⋄𝕨}‿{e+↩ej=j↩1+𝕩⋄𝕩}‿N
{(i R j)⊑𝕩}⟜𝕩⌜𝕩
}´(2⋆ni-1+⊢)⌜↕ni←⌈2 Log l+l=0
}
# Counting sort for small-range ints
bl←bu←0 ⋄ Count←{GroupLen⊸GroupOrd (gt⊑⟨-⟜bl,bu⊸-⟩)⌜𝕩}
sr←((3=cs)×ts=l)◶⟨0,(1×´⌊⊸=⌜)◶0‿{((bu↩⌈´𝕩)-bl↩⌊´𝕩)≤2×l}⟩𝕩
sr◶Merge‿Count 𝕩
}⟩𝕩
}⊘{
cx←(=𝕩)-c←1-˜=𝕨
"⍋ or ⍒: Rank of 𝕨 must be at least 1" ! 0≤c
"⍋ or ⍒: Rank of 𝕩 must be at least cell rank of 𝕨" ! 0≤cx
sw←1 Cell 𝕨 ⋄ nw←≠𝕨
𝕩↩ToArray𝕩 ⋄ sx←cx Cell 𝕩 ⋄ lz←1×´sz←cx↑≢𝕩
sz ⥊ 𝕨 (0<nw)◶{𝕩⋄0⌜↕lz}‿{
a0w←IsSimple𝕨 ⋄ Gw←⊑⟜𝕨 ⋄ lw←1×´sw
lew←{𝕏○Gw} _getC_ lw a0w+2×1=lw
"⍋ or ⍒: 𝕨 must be sorted" ! 1×´LEw⟜(lw⊸+)∘(lw⊸×)⌜↕nw-1
a0←IsSimple∘𝕩⊸×⍟⊢a0w ⋄ Gx←⊑⟜𝕩
cd‿lc←sw CmpLen sx
le ← cd {Gw⊸𝕏⟜Gx}_getC_ lc a0+2×1=lc
B←lw⊸×⊸LE
BinSearch ← {
Bx ← B⟜𝕩
R ← {a←Bx m←𝕩+h←⌊𝕨÷2⋄(h+a×𝕨-2×h)R a⊑𝕩‿m}⍟(>⟜1)
1 + (nw+1) R ¯1
}
(BinSearch (1×´sx)⊸×)⌜ ↕lz
}○⥊ 𝕩
}
}
⍋ ← 0 _grade
⍒ ← 1 _grade
# Searching
_search←{ # 0 for ∊˜, 1 for ⊐
ind ← 𝕗
red ← 𝕗⊑⟨1-×´,+´×`⟩
0 Fill {
c←1-˜=𝕨
"p⊐𝕩 or 𝕨∊p: p must have rank at least 1" ! 0≤c
"p⊐n or n∊p: Rank of n must be at least cell rank of p" ! c≤=𝕩
n←≠𝕨 ⋄ k←1×´s←1 Cell 𝕨 ⋄ cx←c-˜=𝕩
lx←1×´sh←cx↑≢𝕩
sh ⥊ 𝕨 (e←0<n×k)◶⟨0,s MatchS cx⊸Cell⟩◶{𝕩⋄(ind◶⟨n⊸>,⊢⟩ n×e)⌜↕lx}‿{
cc ← (⊑⟜(⥊𝕨))⊸(1-Match)⟜(⊑⟜(⥊𝕩)) _getCellCmp k
𝕨 ×○(8<≠∘⥊)◶{𝕩
i‿j←(k⊸×⌜↕)⌜n‿lx ⋄ {Red CC⟜𝕩⌜i}⌜j
}‿{
g←Reverse⍒𝕨
i←g⊏˜(0⌈-⟜1)⌜⥊(g⊏𝕨)⍋𝕩
adj←ind⊑⟨1⊸-,⊣--⟜n⊸×⟩
i(⊣ Adj CC○(k⊸×))¨↕lx
} 𝕩
} 𝕩
}⟜ToArray
}
_self←{
"∊𝕩 or ⊐𝕩: 𝕩 must have rank at least 1" ! 1≤=𝕩
g←⍋𝕩
k←1×´1 Cell 𝕩
cc ← (1-Match)○(⊑⟜(⥊𝕩)) _getCellCmp k
0 Fill (PermInv g) ⊏ g 𝔽 0⊸<◶⟨1, -⟜1 CC○(⊑⟜(k⊸×⌜g)) ⊢⟩⌜↕≠𝕩
}
Find←{
r←=𝕨 ⋄ d←(=𝕩)-r
"𝕨⍷𝕩: Rank of 𝕨 cannot exceed rank of 𝕩" ! 0≤d
i←<0 ⋄ j←⥊⟜(↕1×´⊢)d↑s←≢𝕩
(≢𝕨) { A←×⟜𝕩⌜⊸(+⌜)⟜↕ ⋄ i A↩𝕨 ⋄ j A↩0⌈1+𝕩-𝕨 }¨ d↓s
0 Fill (𝕨 Match (⥊𝕩)⊏˜i+⌜<)⌜ j
}○ToArray
Indices←{
"/𝕩: 𝕩 must have rank 1" ! 1==𝕩
"/𝕩: 𝕩 must consist of natural numbers" ! 1×´Nat⌜𝕩
/ 𝕩
}
IndicesInv←{
IA 1==𝕩
IA 1×´Nat⌜𝕩
GroupLen 𝕩
}
SelfClas ← (PermInv∘⍋∘/˜⊏˜¯1+`⊢) _self
OccurrenceCount ← ↕∘≠⊸(⊣-¨·⌈`ר) _self
Transpose←(1<=)◶⟨ToArray,{
l←≠𝕩 ⋄ m←1×´c←1 Cell 𝕩
(⥊𝕩)⊏˜(c⥊↕m)+⟜(m⊸×)⌜↕l
}_fillBy_⊢⟩
TransposeInv←{
r←1-˜=𝕩 ⋄ s←≢𝕩 ⋄ l←r⊑s ⋄ c←r↑s
(⥊𝕩)⊏˜(↕l)+⟜(l⊸×)⌜c⥊↕1×´c
}_fillBy_⊢⍟{IX IsArray𝕩⋄1<=𝕩}
_reorderAxesSub_←{
"𝕨⍉𝕩: 𝕨 must have rank at most 1" ! 1≥=𝕨
𝕨↩Deshape𝕨 ⋄ 𝕩↩ToArray𝕩
"𝕨⍉𝕩: Length of 𝕨 must not exceed rank of 𝕩" ! (≠𝕨)≤r←=𝕩
"𝕨⍉𝕩: 𝕨 must consist of valid axis indices" ! 1∧´(Nat∧<⟜r)⌜𝕨
r𝔽↩n←GroupLen𝕨
k←≠a←𝔾 𝕨∾/0⊸=⌜n
c‿d←k(↑⋈↓)≢𝕩
l‿s←a⊸Group1⌜⋈⟜Stride c
(⌊´⌜l) (0<≠∘⊢)◶⟨∾⟜d⊸⥊,((<0)+⌜´s(<+´)⊸(×⌜)⟜↕¨⊣)⊏(⟨1×´c⟩∾d)⥊⊢⟩ ⥊𝕩
}
HandleDupAxes←{
r←𝕨-0+´(0⌈-⟜1)⌜𝕩
"𝕨⍉𝕩: Skipped result axis" ! (≠𝕩)≤r
r
}
ReorderAxes ← HandleDupAxes _reorderAxesSub_ ⊢
ReorderAxesInv ← {IA 1≥0⌈´𝕩⋄𝕨} _reorderAxesSub_ PermInv
Prefixes←{
"↑𝕩: 𝕩 must have rank at least 1" ! 1≤=𝕩
0⊸⊑⊸Fill ↕⊸⊏⟜𝕩⌜ ↕1+≠𝕩
}
Suffixes←{
"↓𝕩: 𝕩 must have rank at least 1" ! 1≤=𝕩
l←≠𝕩
l⊸⊑⊸Fill {𝕩⊸+⌜↕l-𝕩}⊸⊏⟜𝕩⌜ ↕1+l
}
NormIndP‿NormIndS←{
EI‿er←𝕩 ⋄ _cr←{⊢⊣er!𝔽}
0⊸≤◶⟨0⊸≤_cr+, >_cr⟩ ⊣ EI∘⊢
}⌜⟨
⟨"𝕨⊑𝕩: Indices in 𝕨 must consist of integers"!Int,"𝕨⊑𝕩: Index out of range"⟩
⟨"𝕨⊏𝕩: Indices in 𝕨 must be integers"!⌊⊸=,"𝕨⊏𝕩: Indices out of range"⟩
⟩
Pick0←{
"𝕨⊑𝕩: 𝕩 must be a list when 𝕨 is a number" ! 1==𝕩
𝕩⊑˜(≠𝕩)NormIndP𝕨
}
Pick1←{
"𝕨⊑𝕩: Indices in compound 𝕨 must be lists" ! 1==𝕨
"𝕨⊑𝕩: Index length in 𝕨 must match rank of 𝕩" ! 𝕨=○≠s←≢𝕩
i←0⋄𝕨{i↩(𝕩NormIndP𝕨)+𝕩×i}¨s
i⊑⥊𝕩
}⟜ToArray
Pickd←IsArray◶⟨1,IsSimple⥊⟩∘⊣◶{Pickd⟜𝕩⌜𝕨}‿Pick1
Pick←IsArray∘⊣◶Pick0‿Pickd
_multiAxis←{
gl‿Test‿d1‿aa‿Single‿Ind ← 𝕗
pre ← "𝕨"∾gl∾"𝕩: "
es ← pre∾"𝕩 must have rank at least 1 for simple 𝕨"
er ← pre∾"Compound 𝕨 must have rank at most 1"
el ← pre∾"Length of compound 𝕨 must be at most rank of 𝕩"
et ← pre∾"𝕨 must be an array of numbers or list of such arrays"
tt ← d1 ⊑ ⟨⊢ , et ! 1×´·⥊IsArray◶⟨aa,1×´·⥊(1=Type)⌜⟩⌜ ⟩
Test∘⊣◶{ # Multiple axes
er ! 1≥=𝕨 ⋄ TT 𝕨
l←≠𝕨↩⥊𝕨 ⋄ el ! l≤=𝕩
i←𝕨Ind¨p←l↑s←≢𝕩
j←i (0<1×´≠∘⥊⌜i)◶⟨{⟨⟩⥊˜Join1≢⌜𝕨}, {j←<0⋄𝕨{j↩(j×⌜<𝕩)+⌜𝕨}¨𝕩⋄j}⟩ p
j ⊏ (⟨1×´p⟩∾l↓s)⥊𝕩
}‿{
es ! 1≤=𝕩
𝕨 Single 𝕩
}
}
FirstCell←{
"⊏𝕩: 𝕩 must have rank at least 1" ! 1≤=𝕩
"⊏𝕩: 𝕩 cannot have length 0" ! 0<≠𝕩
(<0) ⊏ 𝕩
}
Select ← ⟨"⊏"
1×´·(1=Type)⌜⥊ ⋄ 1,0
{(≠𝕩)⊸NormIndS⌜𝕨} ⊏ ⊢
{𝕩⊸NormIndS⌜𝕨}
⟩_multiAxis○ToArray
First ← IsArray◶⟨⊢, (0<≠)◶⟨!∘"⊑𝕩: 𝕩 can't be empty",0⊸⊑⟩⥊⟩
Reverse←{
"⌽𝕩: 𝕩 must have rank at least 1" ! 1≤=𝕩
l←≠𝕩
((l-1)⊸-⌜↕l) ⊏ 𝕩
}
RotReduce ← {
"𝕨⌽𝕩: 𝕨 must consist of integers" ! Int𝕨
𝕩+↩0=𝕩 ⋄ r←𝕨-𝕩×⌊𝕨÷𝕩
"𝕨⌽𝕩: 𝕨 too large" ! r<𝕩
r
}
RotL ← ↓∾↑
Rot ← (1==∘⊢)◶⟨RotL⟜(↕≠)⊏⊢,RotL⟩
Rotate ← ⟨"⌽"
IsAtom, 0,0
(RotReduce⟜≠ Rot ⊢)⍟(0<≠∘⊢)
(RotReduce RotL ·↕⊢)
⟩_multiAxis⟜ToArray _fillBy_ ⊢
RepInd←(2⌊=∘⊣)◶{
𝕨↩(0⊑⥊)⍟IsArray𝕨
"𝕨/𝕩: 𝕨 must consist of natural numbers" ! Nat 𝕨
e←r←𝕨
{e+↩r⋄1+𝕩}⍟{e=𝕨}˜`↕r×𝕩
}‿{
"𝕨/𝕩: Lengths of components of 𝕨 must match 𝕩" ! 𝕩=≠𝕨
"𝕨/𝕩: 𝕨 must consist of natural numbers" ! 1×´|∘⌊⊸=⌜𝕨
/ 𝕨
}‿{
"𝕨/𝕩: Components of 𝕨 must have rank 0 or 1" ! 0˙
}
Replicate←⟨"/"
((0<≠)×´(1=Type)⌜)∘⥊, 1,1
RepInd⟜≠ ⊏ ⊢
RepInd
⟩_multiAxis○ToArray _fillBy_ ⊢
IsPure ← {d←Decompose𝕩 ⋄ 2⊸≤◶⟨≤⟜0, (ChPure×´·𝕊⌜1⊸↓)d˙⟩0⊑d}
ChPure ← (5=0⊸⊑)◶⟨1,('◶'_isGlyph 2⊸⊑)◶⟨1,1×´·IsPure⌜·⥊3⊸⊑⟩⟩
hfils ← {𝕏´{0 Fill 𝕏}‿⊢}⌜(⊢∾{𝕏˜}⌜)⊢‿{𝕎{𝕎⊘𝕏}𝕏}
HomFil ← "=≠≡≢"_glyphLookup_(1‿1‿2‿3‿0⊏hfils)⊸{𝕎𝕩}
_fillByPure_←{
𝕘 (3≤Type∘⊣)◶⟨{𝕨Fill𝕏},{(𝕨HomFil𝕩)_fillBy_𝕨}⍟(IsPure⊣)⟩ 𝕗
}
_each ← {𝕨𝔽⌜⊘(𝔽_eachd)_fillByPure_𝔽○ToArray𝕩}
_table ← {𝕨𝔽⌜_fillByPure_𝔽○ToArray𝕩}
match←{(0⊑𝕨)◶(1⊑𝕨)‿𝕩}´⟨
⟨=○IsArray, 0⟩
⟨IsArray∘⊢, =⟩
⟨=○= , 0⟩
⟨MatchS○≢ , 0⟩
{1×´⥊𝕨Match¨𝕩}
⟩
Depth←IsArray◶0‿{1+0⌈´Depth⌜⥊𝕩}
Join1←{
# List of lists
"∾𝕩: 𝕩 must have an element with rank at least =𝕩" ! 0<0+´=⌜𝕩
i←j←¯1 ⋄ e←⟨⟩ ⋄ a←𝕩
{{e↩Deshape a⊑˜i↩𝕩⋄j↩¯1}⍟(1-i⊸=)𝕩⋄(j↩j+1)⊑e}⌜/≠⌜𝕩
}
under←{
Err←{𝕩}
IsErr ← (3=Type)◶⟨0,Err˙⊸=⟩
E ← Err˙
_errIf ← {⊢⊘×○(1-𝔽)◶⟨Err˙,𝕏⟩}
SE ← IsErr _errIf⍟(3≥Type)
Expand ← {
f‿a‿i‿q←𝕩 ⋄ e←i⊑⥊a
⟨IsArray◶⟨⟨⟩,∾⟜⟨i⟩⟩f,e,IsArray◶⟨0,@Fill⥊⟜(↕1×´⊢)∘≢⟩e,q⟩
}⍟(>⟜(IsArray 2⊑⊢))
Expand2 ← {
xf‿xa‿xi‿xq ← 𝕩
E ← { f‿a‿i‿q←𝕩 ⋄ {f‿a‿𝕩‿q _s}⍟(1-IsStruct)⌜⍟(0<≠f) i }
i ← (E 1 Expand IsStruct◶{xf‿xa‿𝕩‿xq}‿(1⊑Decompose))⌜ xi
⟨⟩‿@‿i‿⟨1,1⟩
}
_s ← {
⟨st,d‿o⟩←𝕩 # Function, input depth, output is structural
f‿a‿i‿⟨q,r⟩←Expand2⍟(2=d) (0<d) Expand 𝕗 # Path, array reference, indices, info
{f‿a‿𝕩‿⟨q⌈1<o,r⟩ _s}⍟(1-IsStruct)⍟(0<o) 𝕨 St i
}
IsStruct ← (StructD←(4=0⊸⊑)◶⟨0,s˙=2⊸⊑⟩) {Decompose𝕩}
NS ← IsStruct _errIf
InitS ← {¯1‿⟨𝕩⟩‿0‿⟨0,0⟩ _s}
Nest ← {
d←0⋄r←0 ⋄ SD ← {d⌈↩IsArray𝕩⋄𝕩}
a ← Decompose⊸(1⊸⊑⊸((0<·≠0⊑⊣)◶⟨{r⌈↩1⊑3⊑𝕨⋄SD 2⊑𝕨},{r↩1⋄𝕩}⟩) ⍟(StructD⊣)) _perv 𝕩
⟨⟩‿@‿a‿⟨d,r⟩ _s
}
Es ← {f‿a‿i‿q←𝕩⋄{f‿a‿𝕩‿q _s}⌜i}
_nested ← {
p0‿p1←(⌊⋈⌈)´pw‿px←0⊸⊑⌜a←(1 Expand 1⊑Decompose)⌜ 𝕨‿𝕩
p ← 0+´×`(⊑⟜pw=⊑⟜px)⌜↕p0
(p=p1)◶⟨
Nest 𝔽○Es
{𝕩_s}(2↑⊢)∾𝔽○(2⊸⊑)⋈⌈¨○(3⊑⊢)
⟩´a
}
_withNest ← {
(0<+○IsStruct)◶⟨𝔽, Nest 𝔽○(Es∘(1 Expand 1⊑Decompose)⍟IsStruct)⟩
}
_rankStruct_ ← {
ss←↕0 ⋄ Wr←{ss∾↩⟨𝕩⟩⋄𝕩} ⋄ _rd←{i←𝕗⋄{𝕩⋄(i+↩1)⊢i⊑ss}}
_r_ ← {
Min←<◶⊢‿⊣
𝕘 {𝕏○({𝕩_s}⍟(0 _rd))}⍟(3≤Type)↩
k←𝕨(⋈○(=2⊸⊑⍟(0 _rd)) (0≤⊢)◶⟨Min⟜-,⊣-Min⟩¨ 𝔾_ranks)𝕩
c←0<+´ss⋄Enc←0 _rd◶⟨EncRank,{f‿a‿i‿q←𝕩⋄{f‿a‿𝕩‿q _s}⌜𝕨 EncRank i}⟩
c◶⟨Merge,{𝕏⟨Merge,2‿1⟩}∘Nest⟩ ((0⊑k)Enc𝕨) 𝔽_each ((1-˜≠)⊸⊑k)Enc𝕩
}
𝕨 𝔽_r_𝔾○((1 Expand 1⊑Decompose)⍟(Wr IsStruct)) 𝕩
}
_depthStruct_←{
n←𝕨𝔾_ranks𝕩 ⋄ F←𝔽 ⋄ B←{𝕏}⊘{𝕨˙⊸𝕏}
"Under ⚇: depths must be less than 0, or ∞"!1×´(∞⊸=∨0⊸>)⌜n
_tf←{𝕗⌜_withNest} ⋄ _ef←{𝕗_eachd _withNest}
a ← {(𝕨 B 𝕗)_tf𝕩}‿{𝔽⟜(𝕩˙)_tf𝕨}‿_ef
_d←{ t←2⊸×⊸+´0⊸>⌜𝕗 ⋄ 𝕗{𝕩⋄m←(t-1)⊑a⋄(+⟜1⌜𝕗)_d _m}⍟(0<t) f }
𝕨 n _d 𝕩
}
_amb ← {(IsStruct⊢)◶⟨𝕏, 𝕩‿𝕗{𝕨𝕏𝕗}⟩}
_mon ← {(𝕗_amb𝕩)⊘(NS𝕩)}
_dy ← {(NS𝕩)⊘(𝕗_amb𝕩)}
k‿v ← Split2 ⟨
"⊢⊣˜∘○⊸⟜⊘◶", ⊢ # ˙ handled specially
"´˝", {r←𝕩⋄{IsArray∘⊢◶⟨E,𝔽_r⟩}}
"=≠≢", 1‿0 _mon
"<", 0‿2 _mon
"⋈", 0‿2 {+○IsStruct◶⟨𝕏, 𝕩‿𝕗{𝕏𝕗}⊘E, Nest 𝕏⟩}
"≍", 1‿1 _mon # Dyad combines
"↕/»«", 1‿1 _dy
"⊔", 1‿2 _dy
"⥊⌽⍉⊏", 1‿1 _amb
"↑↓", {(1‿2 _amb𝕩)⊘(1‿1 _amb𝕩)}
"⊑", 1‿2 _amb
">", 2‿1 _mon
"∾", 2‿1 {+○IsStruct◶⟨𝕏, 𝕩‿𝕗{𝕏𝕗}⊘E, 𝕏_nested⟩}
"¨⌜", {m←𝕩⋄{𝔽 _m _withNest}}
"˘", {𝕩⋄{𝔽 _rankStruct_ ¯1}}
"⎉", rankStruct˙
"⚇", depthStruct˙
⟩
NSPrim ← (Type-3˙)◶⟨NS, {m←𝕩⋄{NS(𝕗_m)˙0}}, {m←𝕩⋄{NS(𝕗_m_𝕘)˙0}}⟩
SP ← (Join1 k)_glyphLookup_((k≠⌜⊸/v)∾⟨NSPrim⟩)
Recompose ← ⊣◶⟨
⊢ # 0 primitive
⊢ # 1 block
{𝕎𝕏}´⊢ # 2-train
{F‿G‿H←𝕩⋄F G H} # 3-train
{F‿m←𝕩⋄F _m} # 4 1-modifier
{F‿m‿G←𝕩⋄F _m_ G} # 5 2-modifier
⟩
Recomp ← (E˙=≥⟜3⊸⊑)◶⟨Recompose,E˙⟩
SFN ← 0⊸≤◶⟨3,2⊸≤◶⊢‿2⟩∘(0⊑⊢)◶⟨
SE · {p←SP𝕩⋄P𝕩} 1⊑⊢ # 0 primitive
E˙ # 1 block
DIsConst◶⟨SE 0⊸⊑ Recomp {SFN⌜1↓𝕩}, {(1⊑𝕩)˙}⟩ # other operation
SE 1⊑⊢ # ¯1 constant
⟩⟜{Decompose𝕩}
# Traverse indices 𝕩 and values 𝕨.
# Return flat lists ⟨indices,values⟩, or err if 𝕨 doesn't capture 𝕩.
conform ← {𝕎◶0‿𝕏}´⟨IsArray⊢, =○=, MatchS○≢⟩
GetInserts ← {
v‿d←𝕨
count←1⋄DC←IsArray◶⟨0,d◶⟨1,1+0⌈´{count+↩¯1+≠d←⥊𝕩⋄DC⌜d}⟩⟩⋄depth←DC𝕩
𝕩 (2⌊depth)◶(⋈○⋈)‿(Conform◶⟨Err˙,⋈○⥊⟩)‿{
Fail←{𝕊‿0}
# 𝕎 is parent traversal; 𝕩 is current components of ind and val
Trav←(IsArray 0⊑⊢)◶⟨⋈, Conform´∘⊢◶Fail‿{
Parent←𝕎 ⋄ n←≠0⊑a←⥊⌜𝕩 ⋄ j←¯1
Child←Trav⟜{𝕩⊸⊑⌜a}
{ j+↩1 ⋄ f←n⊸≤◶⟨𝕊˙⊸Child,Parent˙⟩j ⋄ F 0 }
}⟩
next ← 0 Trav 𝕨‿𝕩
res ← {n‿o←Next𝕩⋄next↩n⋄o}⌜ ↕count
(next=fail)◶⟨0⊸⊑⌜ ⋈ 1⊸⊑⌜, Err˙⟩ res
} v
}⍟(1-IsErr∘⊢)
_insert_ ← {
i‿v←𝕗_indRec⍟𝕘 𝕩
root‿x←𝕗
Set1←{
𝕩↩ToArray𝕩
s←≢𝕩⋄l←≠d←⥊𝕩
"Cannot modify fill with Structural Under"!1∧´@⊸>⌜i
gl←l GroupLen i ⋄ v⊏˜↩gl GroupOrd i
j←0⋄Adv←{(j+↩𝕩)-1}⊑v˙
CM←"⌾: Incompatible result elements in structural Under"!Match
s⥊(↕l)2⊸⌊◶⟨⊑⟜d,Adv,Adv{(𝕨CM(j-𝕩)⊸+⊑v˙)⌜↕𝕩-1⋄𝕨}⊢⟩¨gl
}
_at_ ← {(↕≠𝕩)𝔽⍟((𝔾𝕩)=⊣)¨𝕩}
Set ← 0⊸{ (𝕨≥≠root)◶⟨≢⥊(1+𝕨)⊸𝕊_at_(𝕨⊑root˙)∘⥊, Set1⟩ _fillBy_ ⊢ 𝕩 }
IsArray∘root◶⟨0⊑v˙, Set⟩ x
}
_indRec ← {
root‿x←𝕗 ⋄ iv←𝕩
l ← GroupLen i ← (1=Type)◶⟨0⊑0⊑1⊑Decompose,¯1⟩⌜ 0⊑iv
ind‿val ← (l GroupOrd i)⊸⊏⌜ iv ⋄ rec←0
ic ← (1<·≠0⊑⊢)◶⟨2⊑⊢,{rec↩1⋄𝕩_s}(⋈1↓0⊑⊢)∾1↓⊢⟩∘(1⊑Decompose)⌜ ind
j←0 ⋄ IJ←{(j+↩𝕩) ⊢ val ⋈⟜1⊸GetInserts○((j⊸+⌜↕𝕩)⊸⊏) ic}
m ← (⊢ ⋈ ⊑⟜(⥊x) {⟨⟩‿𝕨 _insert_ rec⍟(1-IsErr) 𝕩} ·IJ⊑⟜l)⌜ /0⊸<⌜l
t ← (/ ¯1⊸=⌜i)⊸⊏⌜ iv
{(𝕩⊸⊑⌜m)∾𝕩⊑t}⌜ ↕2
}
{
val←𝕨𝔽○𝔾𝕩
s←𝕘 SFN⊸{𝕎𝕩} InitS 𝕩
root‿ind‿⟨d,rec⟩ ← IsStruct◶⟨0‿Err‿⟨0,0⟩,0‿2‿3⊏1⊑Decompose⟩ s
IsErr◶⟨root‿𝕩 _insert_ rec, {𝕏val}·Inverse𝔾˙⟩ val‿d GetInserts ind
}
}
≡ ← Depth ⊘ Match
≢ ↩ IsArray◶(↕0)‿≢ ⊘ (1-Match)
IF ← ⊢⊣!∘≡ # Intersect fill
IEF← (0<≠)◶⟨⊢_fillBy_ Fill, ⊢_fillBy_ IF´⟩∘⥊
HasFill ← 0=·Fill⊢_fillBy_(@⍟(3≤Type∘⊣))⟜(↕0)
_fillMerge_ ← {(0<≠∘⥊)◶⟨(𝔾○≢⥊⟨⟩˙)_fillBy_⊢⟜Fill⍟HasFill, 𝔽 ⊣_fillBy_⊢ IEF⟩}
Merge←{
c←≢0⊑⥊𝕩
(">𝕩: Elements of 𝕩 must have matching shapes" ! c =○≠◶0‿MatchS ≢)⌜⥊𝕩
(Deshape⌜𝕩)⊑˜⌜c⥊↕1×´c
}_fillMerge_∾⍟IsArray
JoinTo←(1<⌈○=)◶(∾○⥊)‿{
a←1-˜𝕨⌈○=𝕩
s←𝕨⋈○≢𝕩
"𝕨∾𝕩: Rank of 𝕨 and 𝕩 must differ by at most 1" ! 1×´(a≤≠)⌜s
c←(≠-a˙)⊸↓⌜s
"𝕨∾𝕩: Cell shapes of 𝕨 and 𝕩 must match" ! MatchS´c
l←0+´(a<≠)◶1‿(0⊑⊢)⌜s
(⟨l⟩∾0⊑c)⥊𝕨∾○⥊𝕩
}○ToArray _fillBy_ IF
_s0←{s←𝕨⋄F←𝔽⋄{o←s⋄s F↩𝕩⋄o}⌜𝕩}
Stride←Reverse 1 ×_s0 Reverse
JoinM←{
# Multidimensional
n←≠z←⥊𝕩 ⋄ s←≢⌜z ⋄ r←=𝕩
sh←≢𝕩 ⋄ p←1 ⋄ i←j←he←<0
(Stride sh){
q←𝕨
a←𝕩⊑sh
h←-⟜(1-˜0⌈´rr)⌜rr←=⌜z⊏˜q⊸×⌜↕a
"∾𝕩: Incompatible element ranks" ! 1×´0⊸≤⌜h
hl←≠ih←q⊸×⌜/h
sf←s⊏˜⥊((a×q)⊸×⌜↕p)+⌜ih+⌜↕q
si←⥊he⊣⌜↕hl×q
"∾𝕩: Incompatible element ranks" ! 1×´si<⟜≠¨sf
m←si⊑¨sf
lf←m⊏˜q⊸×⌜↕hl
"∾𝕩: 𝕩 element shapes must be compatible" ! m MatchS ⥊(↕p)⊢⌜lf⊣⌜↕q
k ← / l←{i←¯1⋄⊢◶1‿{(i+↩𝕩)⊑lf}⌜h}
c ← (↕≠k)-¨k ⊏ 0+_s0 l
he↩ he +⌜ h
i ↩ (i ×⌜ k⊏l) +¨ i⊢⌜c
j ↩ j ×⟜a⊸+⌜ k
p×↩a
}¨↕r
d←(=0⊑z)-0⊑he↩⥊he
"∾𝕩: 𝕩 element trailing shapes must match" ! he MatchS (=-d˙)⌜z
G←(Deshape⌜z){𝕨⊑𝕩⊑𝕗}¨
i (0<d)◶G‿{
Tr←(≠-d˙)⊸↓⋄t←Tr 0⊑s
"∾𝕩: 𝕩 element trailing shapes must match" ! 1×´(t MatchS Tr)⌜s
ti←t⥊↕tp←×´t⋄(𝕨tp⊸×⊸+⌜ti)G𝕩⊣⌜ti
} j
}
Join←(2⌊=)◶⟨
Merge, (1×´(1≥=)⌜)◶JoinM‿Join1, JoinM
⟩_fillMerge_{
r←≠𝕨 ⋄ d←≠𝕩
"∾𝕩: empty 𝕩 fill rank must be at least argument rank" ! d≥r
(↕d)(r≤⊣)◶⟨⊑⟜𝕨⊸×,⊢⟩¨𝕩
} ⊣ "∾𝕩: 𝕩 must be an array"!IsArray
_takeDrop←{
take ← 1 - 𝕗
gl ← 𝕗⊑"↑"‿"↓"
noop ← 𝕗⊑⟨1-=⟜|, 1-0⊸=⟩
inds ← 𝕗⊑⟨
{ 𝔽⍟(𝕨⊸<)a←|𝕩 ⋄ (0<𝕩)◶⟨¯∞⍟(<⟜0)⌜+⟜(𝕨+𝕩)⌜, ¯∞⍟(𝕨⊸≤)⌜⟩↕a }
{ 𝔽 ⋄ 0⊸<◶⟨↕0⌈+,<∘⊢+⌜·↕0⌈-⟩ }
⟩
pre ← "𝕨"∾gl∾"𝕩: 𝕨 must "
ernk ← pre∾"have rank at most 1"
eint ← pre∾"consist of integers"
IsArray∘⊣◶{
eint ! Int 𝕨
p←0≤𝕨
l←𝕨p◶⟨0⌈+,⌊⟩≠𝕩
F←𝕩{(Fill𝕗)˙⌜↕𝕩}
k←1⋄S←⊢ ⋄ 𝕨⊸{k×´↩c←1 Cell𝕩 ⋄ S↩(⟨(0⌈(≠𝕩)-⊢)⍟(1-take)|𝕨⟩∾c)⊸⥊}⍟(1<=) 𝕩
S ((|∘𝕨-≠∘𝕩){𝕩p◶⟨∾˜,∾⟩F𝕨×k}⍟(>⟜0)⊢)⍟take (l×k) (take=p)◶↓‿↑ ⥊𝕩
}‿{
ernk ! 1≥=𝕨
𝕨 ↩ ⥊𝕨
eint ! 1×´Int⌜𝕨
r ← ≠𝕨
s ← r {(1⌜∘↕𝕨-≠𝕩)∾𝕩}⍟(>⟜≠) ≢𝕩
_c ← { (×⟜𝕗⌜𝕨) +⌜ 𝕩 }
i←<0 ⋄ k←1 ⋄ UIk←{ i (k×𝕨)_c↩ k ↕⊸(𝕨_c)⍟(1-=⟜1) 𝕩 ⋄ k↩1 ⋄ ≠𝕩 }
doFil←0
sh ← (r↑s) Noop◶{k×↩𝕨⋄𝕨}‿(⊣ UIk {𝕩⋄doFil↩1}_inds)¨ 𝕨
(0<=i)◶(s⊸⥊)‿{
sh ∾↩ t ← r↓s
{i 𝕩_c↩ ↕𝕩}⍟(1-1⊸=) k×´t
Sel ← ⊑⟜(⥊𝕩)
𝕩{Sel↩0⊸≤◶⟨(Fill𝕨)˙,Sel⟩}⍟⊢doFil
Sel⌜ sh ⥊ i
} 𝕩
}_fillBy_⊢ ⟜ ToArray
}
Take ← 0 _takeDrop
Drop ← 1 _takeDrop
ShiftCheck←{
"« or »: 𝕩 must have rank at least 1" ! 1≤=𝕩
s←1 Cell 𝕩
𝕨 { # Only if called with two arguments
"« or »: 𝕨 must not have higher rank than 𝕩" ! 0≤𝕩
"« or »: Rank of 𝕨 must be at least rank of 𝕩 minus 1" ! 1≥𝕩
"« or »: 𝕨 must share 𝕩's major cell shape" ! s MatchS (1-𝕩)↓≢𝕨
} 𝕩-○=𝕨
(𝕨1⊘{(𝕩≤○=⊢)◶1‿≠𝕨}𝕩) ×´ s
}
ShiftBefore←{
n←𝕨 ShiftCheck 𝕩
m←n⌊l←≠d←⥊𝕩
(≢𝕩) ⥊ (𝕨{(Fill𝕩)⌜↕𝕨}⍟(0<l)⟜𝕩⊘(↑⟜Deshape˜)m) ∾ (l-m)↑d
} _fillBy_ (⊢⊘IF)
ShiftAfter←{
n←𝕨 ShiftCheck 𝕩
m←n⌊l←≠d←⥊𝕩
(≢𝕩) ⥊ (m↓d) ∾ 𝕨{(Fill𝕩)⌜↕𝕨}⍟(0<l)⟜𝕩⊘(n⊸-⊸↓⟜Deshape˜)m
} _fillBy_ (⊢⊘IF)
RangeCheck ← "↕𝕩: 𝕩 must consist of natural numbers"!Nat
Range ← IsArray◶(↕⊣RangeCheck)‿{
"↕𝕩: 𝕩 must be a number or list"!1==𝕩 ⋄ RangeCheck⌜𝕩
(0⌜𝕩)Fill 0⊸Fill⌜(0<1×´⊢)◶⟨⥊⟜⟨⟩,(<⟨⟩)⋈⊸∾⌜´↕⌜⟩𝕩
}
Windows←{
"𝕨↕𝕩: 𝕨 must have rank at most 1" ! 1≥=𝕨
r←≠𝕨↩Deshape 𝕨 ⋄ 𝕩↩ToArray𝕩
𝕨{
"𝕨↕𝕩: Length of 𝕨 must be at most rank of 𝕩" ! r≤=𝕩
"𝕨↕𝕩: 𝕨 must consist of natural numbers" ! ×´Nat⌜𝕨
s←≢𝕩
l←(r↑s)(1+-)¨𝕨
"𝕨↕𝕩: Window length 𝕨 must be at most axis length plus one" ! ×´0⊸≤⌜l
k←1×´t←r↓s
Win ← {
str ← Reverse ×`⟨k⟩∾s⊏˜{𝕩⊸-⌜↕𝕩}r-1
(⥊𝕩) ⊏˜ k +⌜⟜(t⥊↕)˜⍟(1-=⟜1) l +⌜○(+⌜´str{𝕨⊸×⌜↕𝕩}¨⊢) 𝕨
}
𝕨 (0<(k×´l)×´⊣)◶⟨{⟨⟩⥊˜l∾𝕨∾t},Win⟩ 𝕩
}_fillBy_⊢⍟(0<r)𝕩
}
EncCell ← {
f←𝕨↑≢𝕩 ⋄ c←1×´s←𝕨Cell𝕩 ⋄ d←⥊𝕩
i←s⥊↕c
E←{e←Fill d⊢_fillBy_(0⍟(3≤Type)⊣)↕0 ⋄ (d⊣_fillBy_⊢˜e˙⌜i)Fill𝕩}
f⥊ E⍟(0=≠) {d⊏˜(c×𝕩)⊸+⌜i}⌜↕1×´f
}
EncRank ← (>⟜0×1+≥⟜=)◶⟨<⊢,EncCell,<⌜_fillBy_<⊢⟩
_cells ← {
F←𝔽 ⋄ _m←{𝔽⌜⊘(𝔽¨)_fillByPure_𝔽○(1⊸EncCell)}
D←{ "˘: Argument lengths don't agree" ! 𝕩=○≠𝕨 ⋄ 𝕨 F _m 𝕩 }
Merge 𝕨 2⊸×⊸+○(0<=)◶⟨<F,{𝕨˙⊸F _m𝕩},{F⟜(𝕩˙)_m𝕨},D⟩ 𝕩
}
_insert←{
"˝: 𝕩 must have rank at least 1" ! 1≤=𝕩
F←𝔽
Id ← {
s ← 1↓≢𝕩
JoinSh ← {"˝: Identity does not exist"!0<≠𝕨 ⋄ 𝕨×⟜(0⊸<)¨↕≠𝕨}
s (1-IsJoin∘⊢)◶⟨JoinSh⥊𝕩˙, Identity⟩ f
}
𝕨 (0<≠)⊘1◶Id‿{𝕨F´1 EncCell 𝕩} 𝕩
}
ReshapeT ← "∘⌊⌽↑"_glyphLookup_(↕5)
Reshape←{
"𝕨⥊𝕩: 𝕨 must have rank at most 1" ! 1≥=𝕨
s←Deshape 𝕨
sp←0+´p←Nat◶⟨1,∞⊸=⟩⌜s
"𝕨⥊𝕩: 𝕨 must consist of natural numbers" ! 1≥sp
n←≠d←Deshape 𝕩
l←sp◶(1×´⊢)‿{
lp←1×´p⊣◶⊢‿1¨𝕩
"𝕨⥊𝕩: Can't compute axis length when rest of shape is empty" ! 0<lp
i←0+´pר↕≠p
t←ReshapeT i⊑s
"𝕨⥊𝕩: 𝕨 must consist of natural numbers or ∘ ⌊ ⌽ ↑" ! t<4
Chk ← ⊢ ⊣ "𝕨⥊𝕩: Shape must be exact when reshaping with ∘" ! ⌊⊸=
a←(2⌊t)◶⟨Chk,⌊,⌈⟩n÷lp
s↩p⊣◶⊢‿a¨s
{d∾↩(Fill d)⌜↕𝕩-n⋄n}⍟(n⊸<)⍟(3=t)lp×a
} s
s⥊{
"𝕨⥊𝕩: Can't produce non-empty array from empty 𝕩" ! 0<n
l >⟜≠◶⟨↑, ⊣(⊢∾-⟜≠↑⊢)÷⟜2⊸{𝕨𝕊⟜(∾˜)⍟(>⟜≠)𝕩}⟩ 𝕩
}_fillBy_⊢⍟(1-l=n) d
}
_group←{
"⊔: Grouping argument must consist of integers" ! 1×´Int⌜𝕩
"⊔: Grouping argument values cannot be less than ¯1" ! 1×´¯1⊸≤⌜𝕩
GL←GroupLen⋄𝕩↩𝕨(-˜⟜≠{GL↩(0⌈𝕨⊑𝕩)GL⊢⋄𝕨↑𝕩}⊢)⍟(0⊘⊣)𝕩
d←(l←GL𝕩)GroupOrd𝕩
i←0⋄(𝔽d⊏˜{(i+↩𝕩)⊢i⊸+⌜↕𝕩})⌜l
}
GroupInds←{
"⊔𝕩: 𝕩 must be a list" ! 1==𝕩
G←⊢_group
(1<≡)◶⟨
↕∘0 Fill G
((⊢Fill⥊⟜⟨⟩)0⌜) Fill (<<⟨⟩) ∾⌜⌜´ {⊏⟜(⥊Range≢𝕩)⌜ G⥊𝕩}∘ToArray⌜
⟩ 𝕩
}
Group1←{
n←=𝕨
"𝕨⊔𝕩: Rank of simple 𝕨 must be at most rank of 𝕩" ! n≤=𝕩
ld←(≢𝕨)-¨n↑s←≢𝕩
dr←(1=n)◶⟨0,1=0⊸⊑⟩ld
"𝕨⊔𝕩: Lengths of 𝕨 must equal to 𝕩, or one more only in a rank-1 component" ! dr◶⟨1×´0⊸=⌜,1⟩ld
SX←((n==𝕩)◶{c←1×´t←n↓s⋄𝕩⊏˜(c⊸×⊸+)⌜⟜(t⥊↕c)}‿{⊏⟜𝕩} ⥊𝕩)∘⊣ _fillBy_ ⊢⟜𝕩
(SX⟨⟩) Fill dr SX _group ⥊𝕨
}○ToArray
GroupM←{
"𝕨⊔𝕩: Compound 𝕨 must be a list" ! 1==𝕨
n←0+´r←=⌜𝕨
"𝕨⊔𝕩: Total rank of 𝕨 must be at most rank of 𝕩" ! n≤=𝕩
ld←(Join1≢⌜𝕨)-¨n↑≢𝕩
"𝕨⊔𝕩: Lengths of 𝕨 must equal to 𝕩, or one more only in a rank-1 component" ! 1×´ld((0≤⊣)×≤)¨r/1⊸=⌜r
dr←r⌊¨(0+_s0 r)⊏ld∾⟨0⟩
l←dr-˜⟜≠¨𝕨↩Deshape⌜𝕨 ⋄ LS←∾⟜(n Cell 𝕩) Reshape 𝕩˙
S←⊏⟜(LS⟨1×´l⟩)
(LS 0⌜𝕨) Fill dr (1≠≠∘⊢)◶⟨
S _group○(0⊸⊑)
S⌜ ·+⌜⌜´ (Stride l) {𝕨⊸×⌜⌜𝕩}¨ ⊢_group¨
⟩ 𝕨
}
GroupGen←{
"𝕨⊔𝕩: 𝕩 must be an array" ! IsArray 𝕩
𝕨(2≤≡𝕨)◶Group1‿GroupM𝕩
}
GroupIndsInv ← {
IA 1==𝕩
IX 1×´(1==)⌜𝕩
j←Join1 𝕩
IA 1×´(1≠=)⌜j
IX 1×´Nat⌜j
{IX𝕨<𝕩⋄𝕨}´⍟(0<≠)⌜𝕩
g←GroupLen j
IX 1×´≤⟜1⌜g
o←/1⊸-⌜g
(PermInv j∾o)⊏(/≠⌜𝕩)∾¯1⌜o
}
GroupInv ← {
IA 1==𝕨
IA 1×´Nat⌜𝕨
l←GroupLen𝕨
IX l=○≠𝕩
IX l MatchS ≠⌜𝕩
(PermInv l GroupOrd 𝕨) ⊏ Join 𝕩
}
ValidateRanks←{
"⎉ or ⚇: 𝔾 result must have rank at most 1" ! 1≥=𝕩
𝕩↩Deshape𝕩
"⎉ or ⚇: 𝔾 result must have 1 to 3 elements" ! (1⊸≤×≤⟜3)≠𝕩
"⎉ or ⚇: 𝔾 result must consist of integers" ! 1×´Int⌜𝕩
𝕩 ⊏˜ (≠𝕩)⊸(-+1-˜⌊∘÷˜×⊣)⌜ 𝕨
}
_ranks ← {⟨2⟩⊘⟨1,0⟩ ValidateRanks 𝔽}
_depthOp_←{
neg←0⊸>⌜n←𝕨𝔾_ranks𝕩 ⋄ F←𝔽 ⋄ B←{𝕏}⊘{𝕨˙⊸𝕏}
fb←0 ⋄ SFB←{𝕩⋄sfb↩0⋄fb↩((3≤Type)◶1‿IsPure f)⊑{𝕘⋄𝔽}‿{𝔽_fillBy_𝔾}}
_tf←{𝕗⌜_fb_𝕗} ⋄ _ef←{𝕗_eachd _fb_ 𝕗}
_d←{
r←0 ⋄ GR←𝕗{SFB𝕩⋄gr↩0⋄R↩(𝕗+¨neg)_d}
Tw‿Tx←⟨0⟩⊸∾⍟(2>≠)neg{(𝕨×0≤𝕩)⊑⟨(0⌈𝕩)<≡,0⟩}¨𝕗
(2×Tw)⊸+⟜Tx◶⟨
F, {GR 0⋄(𝕨 B r)_tf𝕩}, {GR 0⋄R⟜(𝕩˙)_tf𝕨}, {GR 0⋄𝕨R _ef𝕩}
⟩
}
𝕨 n _d 𝕩
}
_rankOp_←{
Min←<◶⊢‿⊣
k←𝕨(⋈○= (0≤⊢)◶⟨Min⟜-,⊣-Min⟩¨ 𝔾_ranks)𝕩
Merge ((0⊑k)EncRank𝕨) 𝔽_each ((1-˜≠)⊸⊑k)EncRank𝕩
}
_repeat_←{
F←𝔽 ⋄ b←𝕨{𝕏⊣}˙⊘{𝕨˙{𝔽𝕏⊣}}0
n←𝕨𝔾𝕩
Multi←{
l←u←0
{"⍟: 𝕨𝔾𝕩 must consist of integers"!Int𝕩⋄l⌊↩𝕩⋄u⌈↩𝕩}_perv n
i←⟨𝕩⟩⋄P←B⊸{𝕎`i∾↕𝕩}
pos←f P u
neg←f 0⊸<◶⟨i,Inverse⊸P⟩ -l
(|⊑<⟜0⊑pos‿neg˙)_perv n
}
(Nat n)◶Multi‿{𝕩(B f)∘⊢´↕n} 𝕩
}
÷ ↩ ÷ _perv
⋆ ↩ ⋆ _perv
√ ← ⋆⟜(÷2) ⊘ (⋆⟜÷˜)
| ← (| ⊘ (>○|◶{𝕩-𝕨×⌊𝕩÷𝕨}‿(+⍟(<⟜0◶⟨0⊸>,0⊸<⟩))) ) _perv
⌊ ↩ (⌊ ⊘ (⊣⍟<)) _perv
⌈ ↩ (-∘⌊∘- ⊘ (⊣⍟>)) _perv
∧ ← ⍋⊸⊏ ⊘ (× _perv)
∨ ← ⍒⊸⊏ ⊘ ((+-×) _perv)
× ↩ (0⊸(<->) ⊘ ×) _perv
< ↩ < ⊘ ((1-≥) _perv)
> ↩ Merge ⊘ ((1-≤) _perv)
≠ ↩ ≠ ⊘ ((1-=) _perv)
= ↩ = ⊘ (= _perv)
≥ ← !∘"≥: Needs two arguments" ⊘ (≥ _perv)
≤ ↩ !∘"≤: Needs two arguments" ⊘ (≤ _perv)
+ ↩ + _perv
- ↩ - _perv
¬ ← 1+-
⊐ ← SelfClas ⊘ (1 _search)
ProgressiveIndexOf ← 0 Fill {
c←1-˜=𝕨
"⊒: Rank of 𝕨 must be at least 1" ! 0≤c
"⊒: Rank of 𝕩 must be at least cell rank of 𝕨" ! c≤=𝕩
𝕨⊐○(⋈¨⟜(≢⥊OccurrenceCount∘⥊) 𝕨⊸⊐)𝕩
}
⁼ ← {Inverse 𝕗}
IsConstant ← (3≤Type)◶⟨1 ⋄ DIsConst∘{Decompose𝕩}⊢⟩
AtopInverse ← {(𝕏𝕎)⊘(𝕏⟜𝕎)}○{Inverse𝕩}
TrainInverse ← {
t‿f‿g‿h←𝕩
K←¬IsConstant
f K∘⊣◶⟨{𝕏⁼{𝕨𝔽𝔾𝕩}(𝕨G⁼⊢)},K∘⊢◶⟨{𝕎⁼𝕩G{SwapInverse𝕗}⊢},INF˙⟩⟩ h
}
FuncInverse ← (0⊸⊑ ⊣◶⟨
{PrimInverse𝕩} 1⊸⊑ # 0 primitive
(!∘"Can't invert blocks (add an undo header?)")˙ # 1 block
1⊸⊑ AtopInverse 2⊸⊑ # 2-train
TrainInverse # 3-train
1⊸⊑ {𝕏𝕨}⟜{Mod1Inverse𝕩} 2⊸⊑ # 4 1-modifier
1‿3⊸⊏ {𝕏´𝕨}⟜{Mod2Inverse𝕩} 2⊸⊑ # 5 2-modifier
⟩ ⊢) {Decompose𝕩}
Inverse ← Type◶(3‿1‿2/{⊢⊣𝕩IX∘≡⊢}‿FuncInverse‿(!∘"Cannot invert modifier"))
IA ← "⁼: Inverse failed"⊸!
IX ← "⁼: Inverse does not exist"⊸!
INF← "⁼: Inverse not found"!0˙
_invChk_ ← {i←𝕨𝔽𝕩⋄IX 𝕩≡𝕨𝔾i⋄i}
↕ ↩ Range ⊘ Windows
⊏ ↩ FirstCell ⊘ Select _fillBy_ ⊢
⌽ ← Reverse ⊘ Rotate
↑ ↩ Prefixes ⊘ Take
↓ ↩ Suffixes ⊘ Drop
PrimInverse ← INF _lookup_ ⟨
'+', +⊘(-˜)
'-', -
'×', ⊢_invChk_×⊘(÷˜)
'÷', ÷
'⋆', Log _perv
'√', ט⊘(⋆˜)
'∧', ⊢_invChk_∧⊘(÷˜)
'∨', ⊢_invChk_∨⊘(-˜÷1-⊣)
'¬', ¬
'≠', {B←0⊸=∨1⊸=⋄IX B𝕩⋄IA B𝕨⋄𝕩≠𝕨} _perv
'<', {IX IsArray𝕩⋄IX 0==𝕩⋄0⊑⥊𝕩}⊘(IA∘0)
'⊢', ⊢
'⊣', ⊢⊘(⊢⊣IX∘≡)
'∾', IA∘0 ⊘ {d←𝕩-○=𝕨⋄IX(0⊸≤∧≤⟜1)d⋄l←d◶≠‿1𝕨⋄IX l≤≠𝕩⋄IX (ToArray𝕨)≡d◶⟨l⊸↑,⊏⟩𝕩⋄l↓𝕩}
'≍', {IX 1 =≠𝕩⋄ ⊏𝕩} ⊘ {IX 2 =≠𝕩⋄IX 𝕨≡ ⊏𝕩⋄1⊏𝕩}
'⋈', {IX ⟨1⟩≡≢𝕩⋄0⊑𝕩} ⊘ {IX ⟨2⟩≡≢𝕩⋄IX 𝕨≡0⊑𝕩⋄1⊑𝕩}
'↑', ¯1⊸⊑_invChk_↑ ⊘ (IA∘0)
'↓', 0⊸⊑_invChk_↓ ⊘ (IA∘0)
'↕', ≢_invChk_↕ ⊘ (IA∘0) # Should trace edge and invChk
'⌽', ⌽ ⊘ (-⊸⌽ ⊣ IX∘IsArray∘⊢)
'⍉', TransposeInv ⊘ ReorderAxesInv
'/', IndicesInv ⊘ (IA∘0)
'⊔', GroupIndsInv ⊘ GroupInv
⟩
SwapInverse ← INF _lookup_ ⟨
'+', ÷⟜2⊘(-˜)
'-', IA∘0⊘+
'×', √⊘(÷˜)
'÷', IA∘0⊘×
'⋆', IA∘0⊘√
'√', IA∘0⊘(÷Log)
'∧', √⊘(÷˜)
'∨', (¬√∘¬)⊘(-˜÷1-⊣)
'¬', IA∘0⊘(+-1˙)
⟩
⌜ ↩ _table
¨ ↩ _each
∾ ↩ Join ⊘ JoinTo
» ← ShiftBefore
« ← ShiftAfter
Mod1Inverse ← INF˙ _lookup_ ⟨
'⁼', ⊢
'˜', {SwapInverse𝕩}
'¨', {𝕏⁼¨ ⊣·IX 0<≡∘⊢}
'⌜', {𝕏⁼⌜⊘(IA∘0) ⊣·IX 0<≡∘⊢}
'˘', {(IX∘IsArray⊸⊢𝕏⁼)˘ ⊣·IX 0<=∘⊢}
'`', {(⊏∾¯1⊸↓𝕏1⊸↓)⍟(1<≠)⊘(»𝕏⊢)⊣·IX 0<=∘⊢}∘{𝕏⁼¨}
⟩
⍟ ↩ _repeat_
⌾ ← _under_
Mod2Inverse ← INF˙ _lookup_ ⟨
'∘', AtopInverse
'○', {Fi←𝕎⁼⋄𝕏⁼ Fi⊘(𝕏⊸Fi)}
'⌾', {𝕎⁼⌾𝕏} # Need to verify for computational Under
'⍟', Int∘⊢◶⟨IA∘0˙,{𝕎⍟(-𝕩)}⟩
'⊘', {(𝕎⁼)⊘(𝕏⁼)}
'⊸', IsConstant∘⊣ ⊣◶{INF⊘𝕏}‿⊢ {𝕎⊸(𝕏⁼)}
'⟜', {(𝕨IsConstant∘⊢◶⟨IA∘0˙,{𝕩𝕎{SwapInverse𝕗}⊢}⟩𝕩)⊘(𝕏⁼𝕎⁼)}
⟩
´ ↩ _fold
˝ ← _insert
⁼ ↩ {i←Inverse𝕗⋄𝕨I𝕩}
˘ ← _cells
⊑ ↩ First ⊘ Pick
◶ ↩ {𝕨((𝕨𝔽𝕩)⊑𝕘){𝔽}𝕩} # Same definition, new Pick
⚇ ← _depthOp_
⎉ ← _rankOp_
⥊ ↩ Deshape ⊘ Reshape
≍ ← >∘⋈ _fillBy_ (⊢⊘IF)
⋈ ↩ {𝕩Fill⟨𝕩⟩} ⊘ (⋈○⊑ _fillBy_ IF○<)
⊔ ← GroupInds ⊘ GroupGen
⍉ ← Transpose ⊘ ReorderAxes
∊ ← ⊢_self ⊘ (0 _search˜)
⍷ ← ∊⊸/ ⊘ Find
⊒ ← OccurrenceCount⊘ ProgressiveIndexOf
/ ↩ Indices ⊘ Replicate