Advertisement
Alhadis

GitHub Lightshow - Toronto Toolkit.apl

Mar 31st, 2016
338
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 114.03 KB | None | 0 0
  1. ⍝ Author: Toronto ACM Special Interest Group (SIG) on APL and others
  2. ⍝ Date: 2015-7-19 and see toolkit.txt below
  3. ⍝ Copyright: see files after ]NEXTFILE below
  4. ⍝ License: see files after ]NEXTFILE below
  5. ⍝ Support email:
  6. ⍝ Portability: L1 (ISO APL portability)
  7. ⍝ Purpose:
  8. ⍝ A collection of useful APL functions
  9. ⍝ Description:
  10. ⍝ This workspace is an adaptation of the Toronto Toolkit to GNU APL, kindly
  11. ⍝ provided by Fred Weigel. See also Fred's notes after ]NEXTFILE below
  12.  
  13. ⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝
  14. ⍝ ./toolkit 2015-07-19 06:19:28 (GMT-4)
  15. ⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝
  16.  
  17. ⎕PW←10000
  18.  
  19. ∇y←x adjust d;⎕IO;ex;i;line;lmrg;pw;w
  20. ⍝adjust each row of matrix <d> according to parameters <x>
  21. ⍝.e ('/' ∆box 'please do not / enter') = 15 adjust 'please do not enter'
  22. ⍝.k formatting
  23. ⍝.n rml
  24. ⍝.t 1992.4.24.14.4.17
  25. ⍝.v 1.0 / 05jan82
  26. ⍝.v 2.0 / 05apr88 / change order of <x>, use subroutines
  27. ⍝.v 2.1 / 24apr92 / using signalerror
  28. ⍝ x[1] width of result in columns
  29. ⍝ x[2] width of left margin (i.e. number of blank columns)
  30. ⍝ x[3] number of blank lines to insert between each row
  31. ⎕IO←1
  32. 'adjust' checksubroutine '∆dtb split'
  33. →(2<⍴⍴d)signalerror '/y/adjust rank error/right arg has rank greater than 2'
  34. d←(¯2↑1 1,⍴d)⍴d
  35. x←3↑x
  36. pw←x[1]
  37. lmrg←x[2]
  38. ex←x[3]
  39. ⍝result will have w columns
  40. w←pw-lmrg
  41. →(w<1)signalerror '/y/adjust domain error/text width (',(⍕w),') should be greater than 0'
  42. y←(0,w)⍴''
  43. i←0
  44. l1:→((1↑⍴d)<i←i+1)/end
  45. ⍝remove blanks at end of line
  46. line←∆dtb d[i;]
  47. ⍝if line is empty, treat as line (with one blank)
  48. y←y,[1]w split line,(0=⍴line)⍴' '
  49. →l1
  50. end:
  51. ⍝prepend lmrg blank columns
  52. y←(((1↑⍴y),lmrg)⍴' '),y
  53. ⍝insert ex blank lines between each row (except at bottom)
  54. y←(((-ex)+(1↑⍴y)×1+ex)⍴1,ex⍴0)⍀y
  55.  
  56. ∇Y←Funs after Ts;⎕IO;g∆sort∆columns;B;Tags
  57. ⍝get all functions in <Funs> with timestamp greater than <Ts>
  58. ⍝.e 'after' = ,'after' after 1989 1 1
  59. ⍝.k library-utility
  60. ⍝.n rml
  61. ⍝.t 1992.4.23.0.31.11
  62. ⍝.v 1.0 / 19oct83
  63. ⍝.v 2.0 / 02may88 / added left argument
  64. ⍝.v 2.1 / 27mar92 / localized g∆sort∆columns and ⎕IO, simplified conversion
  65. ⍝<Funs> is namelist of functions
  66. ⎕IO←1
  67. Y←0 0⍴''
  68. Funs←'' ∆box ∆db,' ',Funs
  69. →L10 ∆if∼0∈⍴Funs
  70. Funs←⎕NL 3
  71. L10:
  72. ⍝-----get functions with non-empty t taglines
  73. Tags←'t' gettag Funs
  74. B←∨/Tags≠' '
  75. ⍝quit if all taglines are empty
  76. →(∼∨/B)/0
  77. Tags←B⌿Tags
  78. Funs←B⌿Funs
  79. ⍝-----make numeric, compare, and sort
  80. ⍝assume that all timestamps are well-formed (i.e. each with 6 numbers only)
  81. Tags←(10000,5⍴100)⊥⍉((1↑⍴Tags),6)⍴⍎,' ',(⍴Tags)⍴(Tags='.')⊖Tags,[0.5]' '
  82. Ts←(10000,5⍴100)⊥6↑Ts
  83. Y←(' ',⎕AV)sort(Ts≤Tags)⌿Funs
  84.  
  85. ∇y←amortize w;amortized;debt;i;interest;m;months;payment;rate;⎕IO
  86. ⍝amortization schedule based on <w> = debt, rate, months
  87. ⍝.e 1 50000 50625 50000 625 = ,amortize 50000 .15 1
  88. ⍝.k computation
  89. ⍝.t 1985.8.8.16.46.11
  90. ⍝source: adapted from the handbook of techniques (ibm)
  91. ⍝w[1] debt in total units (e.g. dollars)
  92. ⍝w[2] rate as yearly interest expressed as fraction
  93. ⍝ e.g. 10.5 per cent is .15
  94. ⍝w[3] time period in months
  95. ⍝<y> is 5 column matrix:
  96. ⍝(1)period (2)current debt (3)monthly payment (4)amortized (5)debt
  97. ⎕IO←1
  98. debt←w[1]
  99. rate←w[2]÷12
  100. months←w[3]
  101. m←(months,5)⍴i←0
  102. payment←debt×rate÷1-÷(1+rate)⋆months
  103. l10:→((debt≤0)∨i=1↑⍴m)/end
  104. i←i+1
  105. amortized←payment-interest←debt×rate
  106. m[i;]←i,debt,payment,amortized,interest
  107. debt←debt-amortized
  108. →l10
  109. end:
  110. y←m
  111.  
  112. ∇y←arabic x;⎕IO;a
  113. ⍝returns arabic (base 10) equivalent for character roman numeral <x>
  114. ⍝.e 14 = arabic 'xiv'
  115. ⍝.k translation
  116. ⍝.t 1992.3.28.18.15.14
  117. ⍝.v 1.0 / 04apr88
  118. ⍝.v 1.1 / 28may92 / signalerror used
  119. ⎕IO←1
  120. →(∼(⍴⍴x)∈0 1)signalerror '/y/arabic rank error'
  121. x←∆db x
  122. →(∼∧/x∈'ivxlcdm')signalerror '/y/arabic domain error'
  123. a←(1 5 10 50 100 500 1000)['ivxlcdm'⍳x]
  124. y←a+.ׯ1+2×a≥(a,0)[1+⍳⍴a]
  125.  
  126. ∇r←del array str;⎕IO;mask;p;shape
  127. ⍝general vector reshape. reshape vector <str> using delimiters <del>
  128. ⍝.e 2 3 4 = ⍴'/,' array 'fred,2,xx/joe,,zzz'
  129. ⍝.k reshape
  130. ⍝.n andreas werder
  131. ⍝.t 1988.4.8.3.11.42
  132. ⍝.v 1.0 / 15dec79
  133. ⎕IO←0
  134. r←0,(,del)∘.=str
  135. p←∨⍀((¯1↑⍴r)↑1),[0]r
  136. r←+\r,[0]∼(¯1,¯1↑⍴r)↑p
  137. r←r-⌈\p×0 ¯1↓0,r
  138. shape←1+⌈/r
  139. mask←(⍳×/shape)∈shape⊥r
  140. r←((-⍴shape)↑1)↓shape⍴mask\' ',str
  141.  
  142. ∇Z←J bal N;⎕IO;M;T
  143. ⍝display balance (nesting levels) in lines <J> of function <N>
  144. ⍝.e 'bal[21]'=7⍴21 bal 'bal'
  145. ⍝.k programming-tools
  146. ⍝.t 1992.4.4.14.52.37
  147. ⍝.v 1.0 / 18apr88
  148. ⍝.v 2.0 / 04apr92 / switched args, simplified function, using signalerror
  149. ⎕IO←1
  150. 'bal' checksubroutine 'on balance'
  151. ⍝ ----- left argument
  152. →(' '≠1↑0⍴N)signalerror '/Z/bal domain error/right arg not character.'
  153. →(3≠⎕NC N)signalerror '/Z/bal domain error/(',N,') not a function.'
  154. M←⎕CR N
  155. →(0∈⍴M)signalerror '/Z/bal domain error/function (',N,') locked.'
  156. ⍝ ----- right argument
  157. J←,J
  158. →((⌈/J)>¯1+1↑⍴M)signalerror '/bal index error/right arg greater than last line number ',⍕¯1+1↑⍴M
  159. Z←0 1⍴''
  160. L10:
  161. →(0=⍴J)/Lend
  162. Z←Z on(N,'[',(⍕J[1]),']')on(balance M[1+J[1];])on ' '
  163. J←1↓J
  164. →L10
  165. Lend:
  166. ⍝remove separator line after last display
  167. Z←¯1 0↓Z
  168.  
  169. ∇y←balance n;⎕IO;k;km;l;m;ma;mb;t;xt
  170. ⍝display balance (nesting levels) in text vector <n>
  171. ⍝.e (2 13⍴'(...)⍴(...),x 5,2 2↑y ') = balance '(5,2)⍴(2↑y),x'
  172. ⍝.k formatting
  173. ⍝.t 1992.4.4.15.15.42
  174. ⍝.v 1.0 / 18apr88
  175. ⍝.v 1.1 / 04apr92 / improved arg checking
  176. ⎕IO←0
  177. →(0 1∧.≠⍴⍴n)signalerror '/y/balance rank error/right arg not rank 0 or 1.'
  178. n←,n
  179. n←(-(' '≠⌽n)⍳1)↓n
  180. l←n
  181. k←l=''''
  182. l[(≠\k)/⍳⍴l]←' '
  183. t←l∈'(['
  184. m←(+\t)-+\l∈')]'
  185. xt←k\(+/k)⍴1 ¯1
  186. ma←((-1=xt)++\xt)+m-t
  187. mb←ma-⌊/ma
  188. km←⌈/mb
  189. n←(-mb)⊖n,[0](km,⍴n)⍴'.'
  190. y←(⍴n)⍴((⍳1+km)∘.>mb)⊖n,[¯0.5]' '
  191.  
  192. ∇r←cs base text;⎕IO
  193. ⍝encodes <text> to an integer using collating sequence <cs>
  194. ⍝.e 13='abcd' base 'cd'
  195. ⍝.k translation
  196. ⍝.t 1992.3.28.18.26.54
  197. ⍝.v 1.0 / 15jul83
  198. ⍝.v 1.1 / 15apr88 / matrix argument allowed for <text>
  199. ⍝,v 1,2 / 28mar92 / signalerror used.
  200. ⍝each row of <text> will be encoded into an integer
  201. ⎕IO←1
  202. →(2<⍴⍴text)signalerror '/r/base rank error'
  203. r←text
  204. →(0∈⍴text)/0
  205. text←(¯2↑1 1,⍴text)⍴text
  206. ⍝collating sequence <cs> defaults to ⎕AV
  207. cs←((0∈⍴cs)/⎕AV),(∼0∈⍴cs)/cs
  208. ⍝allow for unknown characters to be mapped into 1+⍴cs
  209. r←(1+⍴cs)⊥⍉¯1+cs⍳text
  210.  
  211. ∇y←a beside b;row
  212. ⍝catenate array <a> to array <b> (maximum rank 2) on last coordinate
  213. ⍝.e (4 3⍴'abbabba a ') = 'aaaa' beside 2 2⍴'b'
  214. ⍝.k catenation
  215. ⍝.t 1989.7.23.21.57.52
  216. ⍝.v 1.1 / 24apr88 (vector treated as 1-column matrix, not 1-row)
  217. a←(2↑(⍴a),1 1)⍴a
  218. b←(2↑(⍴b),1 1)⍴b
  219. row←⌈/1 0 1 0/(⍴a),⍴b
  220. y←((row,¯1↑⍴a)↑a),(row,¯1↑⍴b)↑b
  221.  
  222. ∇r←sep box1 x;len;m;pos;⎕IO
  223. ⍝return matrix <r> from vector <x> delimited by separator <sep>
  224. ⍝.e (3 5⍴'applebettycat ') = '/' box1 'apple/betty/cat'
  225. ⍝.k reshape
  226. ⍝.t 1985.9.22.11.21.22
  227. ⍝.v 1.1 / 13jul83
  228. ⍝note: <sep> is a one-character vector specifying separator character
  229. ⍝ box1 always fills with blank/zero
  230. ⎕IO←1
  231. r←0 0⍴x
  232. →(0∈⍴x)/0
  233. ⍝sep=separator character; default is blank/zero
  234. sep←(1 0=0∈⍴sep)/(1↑0⍴x),1↑sep
  235. ⍝append separator only if no ending separator
  236. ⍝one trailing sep (e.g. 'apple/betty/cat/') does not make extra line
  237. x←x,(sep≠¯1↑x)/sep
  238. pos←(x=sep)/⍳⍴x
  239. m←⌈/len←¯1+pos-0,¯1↓pos
  240. r←((⍴len),m)⍴(,len∘.≥⍳m)\(x≠sep)/x
  241. ⍝note: append this line to delete 'extra' rows caused by multiple sep
  242. ⍝ r←(∨/len∘.≥⍳m)/[1]r
  243.  
  244. ∇y←w boxf v;m;⎕IO
  245. ⍝box fields. <y[i;]> is a field of vector <v> specifed by width <w[i]>
  246. ⍝.e (3 5⍴'applebettycat ') = 5 5 3 boxf 'applebettycat'
  247. ⍝.k reshape
  248. ⍝.t 1989.7.23.23.32.16
  249. ⍝.v 1.1 / 14jul83
  250. ⎕IO←1
  251. ⍝ensure v has +/w elements, else algorithm fails.
  252. v←(+/w)↑v
  253. m←⌈/w
  254. y←((⍴,w),m)⍴(,w∘.>(⍳m)-⎕IO)\v
  255.  
  256. ∇y←bp x
  257. ⍝search for 'break points' based on beginning of identical sequences in <x>
  258. ⍝.e 1 0 1 0 0 1 0 0 0 0 = bp 'aabbbccccc'
  259. ⍝.k searching
  260. ⍝.t 1992.3.19.11.48.59
  261. ⍝.v 1.0 / 18jul83
  262. ⍝treat vector as n×1 matrix (each element is a row)
  263. x←(2↑(⍴x),1 1)⍴x
  264. y←1,¯1↓∨/x≠1⊖x
  265.  
  266. ∇Y←S browse X;⎕IO;C;Flag;I;J;Text
  267. ⍝list occurrences of string <S> (name or any string) in functions <X>
  268. ⍝.k programming-tools
  269. ⍝.n rml
  270. ⍝.t 1992.4.22.23.12.1
  271. ⍝.v 1.0 / 22apr92
  272. ⍝format of search string <S> is: n=string, s=string, string
  273. ⍝example: 'n=X' browse 'ff'; 'abc' browse 'ff'
  274. ⍝result <Y> is report showing function lines containing string <S>
  275. ⎕IO←1
  276. 'browse' checksubroutine 'on ss ssn ∆dtb'
  277. X←'' ∆box ∆db,' ',X
  278. ⍝browse type is arbitrary string (s=) or name (n=)
  279. C←2 2⍴'s=n='
  280. ⍝compute browse type <Flag> (default is S)
  281. Flag←1↑(,(C∧.=2↑S)⌿C),'s'
  282. ⍝remove browse type specification if present
  283. S←(2×∨/C∧.=2↑S)↓S
  284. Y←('... browsing with (',Flag,'=',S,')')on ''
  285. J←0
  286. L10:
  287. →((1↑⍴X)<J←J+1)/Lend
  288. Text←⎕CR X[J;]
  289. →((3≠⎕NC X[J;]),0∈⍴Text)/Err1,Err2
  290. ⍝find locations <I> of search string <S> in ravelled <Text>
  291. ⍝<ssn> and <ss> take vector args. delimiter ⎕AV[1] avoids line run-on.
  292. →('ns'=Flag)/Ln,Ls
  293. Ln:I←(,Text,⎕AV[1])ssn S
  294. →Lsend
  295. Ls:I←(,Text,⎕AV[1])ss S
  296. →Lsend
  297. Lsend:
  298. ⍝ignore 'not found'. not necessary, confusing when common, report too long
  299. →(0=⍴I)/L10
  300. ⍝convert to row numbers (subtract 1, encode, add 1 to rows - ignore columns)
  301. I←(1+(1+⍴Text)⊤¯1+I)[1;]
  302. ⍝remove duplicate row numbers
  303. I←((I⍳I)=⍳⍴I)/I
  304. ⍝select rows and label with line number
  305. Text←(⍕((⍴I),1)⍴I-1),' ',Text[I;]
  306. L30:
  307. ⍝label result <Text> with function name, search type, and search string
  308. Y←Y on('... ',X[J;],' (',Flag,'=',S,')')on Text on 1 0⍴''
  309. →L10
  310. Lend:
  311. ⍝remove trailing blank lines after last Text, and trailing blanks
  312. Y←∆dtb ¯1 0↓Y
  313. →0
  314. Err1:Text←'... not a defined function.'
  315. →L30
  316. Err2:Text←'... locked function.'
  317. →L30
  318.  
  319. ∇Y←catoffun X;g∆sort∆columns;T
  320. ⍝return categories represented by functions <X>
  321. ⍝.e 'library-utility' = ,catoffun 'catoffun'
  322. ⍝.k library-utility
  323. ⍝.n rml
  324. ⍝.t 1992.4.23.0.33.25
  325. ⍝.v 1.0 / 22may85
  326. ⍝.v 1.1 / 22apr92 / using new version of <sort>
  327. ⍝<X> is a vector or matrix of function names
  328. X←'' ∆box ∆db,' ',X
  329. T←'k' gettag X
  330. Y←(' ',⎕AV)sort(bp T)⌿T
  331.  
  332. ∇y←cdays n;⎕IO;d;m;p;r
  333. ⍝convert Gregorian day counts <n> to date format (mm dd yyyy)
  334. ⍝.e 5 13 1988 = ,cdays 725870
  335. ⍝.k date
  336. ⍝.t 1992.4.9.16.47.9
  337. ⍝.v 1.0 / 17may77
  338. ⍝.v 2.0 / 09apr92 / changed name from <dates> to <cdays>
  339. ⍝convert a day count (starting from 1/1/1) to format (mm dd yyyy)
  340. ⍝assume use of Gregorian calendar from 1/1/1
  341. ⎕IO←1
  342. d←,n
  343. y←(⌊(364+d)÷365.242499999999893)∘.+0 1
  344. m←(0,[0.0999999999999999778]4 100 400)⊤y
  345. p←=⌿0=m[2;;;]
  346. m←(365×y-1)+-⌿m[1;;;],[1]p
  347. r←d>m[;2]
  348. d←d-,0 ¯1↓r⌽m
  349. p←(r⌽p)[;1]
  350. d←30+d+(d>59+p)×2-p
  351. m←⌊d÷30.5599999999999916
  352. d←d-⌊30.5599999999999916×m
  353. y←((⍴n),3)⍴m,d,0 ¯1↓r⌽y
  354.  
  355. ∇Y←S change X;⎕IO;C;Flag;J;Text;Z
  356. ⍝change occurrences of Text (name or any string) in functions <X>
  357. ⍝.k programming-tools
  358. ⍝.n rml
  359. ⍝.t 1992.4.22.23.12.51
  360. ⍝.v 1.0 / 25apr88 / change names only, one function only
  361. ⍝.v 2.0 / 22apr92 / args switched, name or substring, many functions
  362. ⍝format of change specification <S> is: n=/old/new, S=/old/new, /old/new
  363. ⍝example: 'n=/X/y' change 'ff'; '/abc/xyz' change 'ff'
  364. ⍝result <Y> is summary report of changes
  365. ⍝underscored variable names to avoid name shadowing
  366. ⎕IO←1
  367. 'change' checksubroutine 'on sr srn ss ssn'
  368. X←'' ∆box ∆db,' ',X
  369. ⍝change type is arbitrary string (s=) or name (n=)
  370. C←2 2⍴'s=n='
  371. ⍝compute change type <Flag> (default is 's')
  372. Flag←1↑(,(C∧.=2↑S)⌿C),'s'
  373. ⍝remove change type specification if present
  374. S←(2×∨/C∧.=2↑S)↓S
  375. ⍝define first line of report
  376. Y←'... changing with (',Flag,'=',S,')'
  377. J←0
  378. L10:
  379. →((1↑⍴X)<J←J+1)/0
  380. Text←⎕CR X[J;]
  381. →((3≠⎕NC X[J;]),0∈⍴Text)/Err1,Err2
  382. ⍝substitute new Text for old (name or arbitrary substring)
  383. ⍝<ssn> and <ss> have vector arguments, ⎕AV[1] is line delimiter
  384. →('ns'=Flag)/Ln,Ls
  385. Ln:Text←(,Text,⎕AV[1])srn S
  386. →Lsend
  387. Ls:Text←(,Text,⎕AV[1])sr S
  388. →Lsend
  389. Lsend:
  390. Z←⎕FX ⎕AV[1]∆box Text
  391. →(0=1↑0⍴Z)/Err3
  392. Text←'... ok (',Z,')'
  393. L30:
  394. ⍝report with function name and result
  395. Y←Y on X[J;],' ',Text
  396. →L10
  397. Err1:Text←'... not a defined function.'
  398. →L30
  399. Err2:Text←'... locked function.'
  400. →L30
  401. Err3:Text←'... not changed (⎕FX = ',(⍕Z),')'
  402. →L30
  403.  
  404. ∇Y←checksize List;⎕IO;Data;I;T
  405. ⍝return report showing sizes of objects in <List>, sorted by size
  406. ⍝.e 1=4⍴=⌿checksize 'checksize'
  407. ⍝.k programming-tools
  408. ⍝.n rml
  409. ⍝.t 1989.7.27.23.19.7
  410. ⎕IO←1
  411. 'checksize' checksubroutine 'vtype'
  412. Y←⍳0
  413. →(2=⍴⍴List)/L10
  414. List←'' ∆box ∆db(,' ',List)
  415. L10:
  416. →(0∈⍴List)/0
  417. I←0
  418. L20:→((1↑⍴List)<I←I+1)/L20end
  419. →((2=⎕NC List[I;])∧2≠⎕SVO List[I;])/L20a
  420. →(3=⎕NC List[I;])/L20b
  421. ⍝some other object. assign size 0.
  422. Y←Y,0
  423. →L20
  424. L20a:
  425. Data←⍎List[I;]
  426. Y←Y,0.125 1 4 8[vtype Data]××/⍴Data
  427. →L20
  428. L20b:
  429. ⍝this is a close-enough approximation for our purposes
  430. Y←Y,+/' '≠,⎕CR List[I;]
  431. →L20
  432. L20end:
  433. ⍝compute total line and label it
  434. Y←(+/Y),Y
  435. List←'-',[1]List
  436. ⍝sort
  437. T←⍒Y
  438. ⍝report
  439. Y←(⍕((1↑⍴List),1)⍴Y[T]),' ',List[T;]
  440.  
  441. ∇N checksubroutine L;B;F
  442. ⍝check workspace for subroutines <L> used by function <N>
  443. ⍝.k programming
  444. ⍝.t 1988.4.28.1.42.16
  445. ⍝.v 1.0 / 28apr88
  446. ⍝.v 2.0 / 03apr92 / function suspends within itself, issues )pcopy message
  447. ⍝example: 'func' checksubroutine 'f1 f2 f3'
  448. B←3=⎕NC F←'' ∆box ∆db,' signalerror ',L
  449. →(∧/B)/0
  450. ⎕←'... ',N,' subroutine warning'
  451. ⎕←'... (1) please copy the toolkit functions listed below into this workspace.'
  452. ⎕←'... (2) resume execution.'
  453. ⎕←' )pcopy toolkit ',∆db,' ',(∼B)⌿F
  454. ⎕←' →⎕LC'
  455. ⍝the next line may have to be modified with ⎕stop in this APL system
  456. s∆checksubroutine←1+1↑⎕LC
  457. Suspend: ⍝suspend here, copy functions, resume execution here
  458.  
  459. ∇z←cjulian js;c;d;j;k;m;s;y
  460. ⍝convert Julian day numbers <js> to (mm dd yyyy style)
  461. ⍝.e (2 4⍴5 12 1988 1 5 17 1977 1) = cjulian 2447294 2443281
  462. ⍝.k date
  463. ⍝.t 1992.4.6.2.34.29
  464. ⍝.v 1.0 / 15apr78
  465. ⍝<js>
  466. ⍝ scalar or vector of julian dates
  467. ⍝ an n×2 array, where js[;1]=julian dates, js[;2]=styles
  468. js←(2↑(⍴js),1 1)⍴js
  469. j←js[;⎕IO]
  470. s←(j>2423434)∨(j>2299171)∧(js,2361221<j)[;⎕IO+1]
  471. j←j-1684595
  472. c←⌊j÷36524.25
  473. j←j+((∼s)×(2-c)+⌈c÷4)-⌈36524.25×c
  474. y←⌊(j+1)÷365.25024999999988
  475. j←j+31-⌊365.25×y
  476. d←j-⌊30.5874999999999915×m←⌊j÷30.5874999999999915
  477. m←m+2-12×k←⌊m÷11
  478. z←m,d,(k+y+100×c-1),[⎕IO+0.5]s
  479.  
  480. ∇Y←comments X;⎕IO;M
  481. ⍝return header and header comments (i.e. initial comments) in function <X>
  482. ⍝.e 9 = 1↑⍴comments 'comments'
  483. ⍝.k library-utility
  484. ⍝.n rml
  485. ⍝.t 1992.4.16.17.31.3
  486. ⍝.v 1.0 / 24jul89
  487. ⍝.v 2.0 / 16apr92 / formerly function <header>
  488. ⍝underscored variables to avoid shadowed names
  489. ⎕IO←1
  490. 'header' checksubroutine '∆dtb on'
  491. →(∼(⍴⍴X)∈0 1)signalerror '/Y/comments rank error/right arg not rank 0 or 1'
  492. →(3≠⎕NC X)signalerror '/Y/comments domain error/function (',X,') not in workspace.'
  493. M←⎕CR X
  494. Y←(∧\M[1;]≠';')/M[1;]
  495. M←1 0↓M
  496. Y←∆dtb Y on(∧\M[;1]='⍝')⌿M
  497.  
  498. ∇y←d condense v;b
  499. ⍝remove redundant blanks and blanks around characters specified in <d>
  500. ⍝.d 1985.6.20.10.10.10
  501. ⍝.e 'apple,betty,cat,,dog' = ',' condense ' apple, betty, cat, , dog'
  502. ⍝.k delete-characters
  503. ⍝.t 1992.3.10.20.19.23
  504. ⍝.v 1.1
  505. ⍝v is character vector (rank 1) only
  506. ⍝remove leading, trailing, and multiple internal blanks
  507. y←∆db,v
  508. ⍝remove blanks around characters specified in <d>
  509. ⍝e.g. if <d> =<,>, blanks are removed around commas in 'a , b , d'
  510. b←y∈d
  511. y←(∼(y=' ')∧(1⌽b)∨¯1⌽b)/y
  512.  
  513. ∇y←d condense1 x;b
  514. ⍝remove redundant blanks and blanks around characters specified in <d>
  515. ⍝.d 1985.6.20.10.10.10
  516. ⍝.e 'apple,''betty , cat'',,dog' = ',' condense1 'apple, ''betty , cat'', , dog'
  517. ⍝.k delete-characters
  518. ⍝.t 1992.3.10.20.28.58
  519. ⍝.v 1.1
  520. ⍝note: same as condense, but does not remove blanks within quotes
  521. ⍝remove leading, trailing, multiple internal blanks, but not in quotes
  522. b←' '≠x←' ',x
  523. ⍝note: ≠\ is the same as 2|+\
  524. y←1↓((≠\''''=x)∨b∨1⌽b)/x
  525. ⍝remove blanks around delimiters, not in quotes
  526. b←y∈d
  527. y←((≠\''''=y)∨∼(y=' ')∧(1⌽b)∨¯1⌽b)/y
  528.  
  529. ∇Y←contents X;⎕IO;BL;Heads;How;I;J;Keys;N;Purpose;S;T
  530. ⍝formatted report of functions <X> by category (with line 1 and header)
  531. ⍝.e (100⍴'-') ∧.= 100↑(contents '∆box')[2;]
  532. ⍝.k library-utility
  533. ⍝.n rml
  534. ⍝.t 1992.4.16.12.3.17
  535. ⍝.v 1.0 / 20jul83
  536. ⍝.v 1.1 / 15may89 / ⎕IO localized, checksubroutine added
  537. ⍝.v 1.2 / 16apr92 / name changes, simplifications, performance improvements
  538. ⍝report is useful for any functions (even without category information)
  539. ⎕IO←1
  540. 'contents' checksubroutine 'bp gettag gradeup on ∆dtb'
  541. Y←0 1⍴''
  542. X←'' ∆box ∆db,' ',X
  543. →(0∈⍴X)/0
  544. Keys←'k' gettag X
  545. ⍝first sort by X
  546. S←'' gradeup X
  547. X←X[S;]
  548. Keys←Keys[S;]
  549. ⍝second sort by Keys (ensure that blank is sorted to the beginning)
  550. S←(' ',⎕AV)gradeup Keys
  551. X←X[S;]
  552. Keys←Keys[S;]
  553. ⍝now get headers and purpose line for report (in order of X)
  554. Heads←0 gettag X
  555. Purpose←1 gettag X
  556. ⍝clean Heads (remove characters after ';', i.e. list of local variables)
  557. I←,∧\Heads≠';'
  558. Heads←(⍴Heads)⍴I\I/,Heads
  559. ⍝compute breakpoints of Keys
  560. N←bp Keys
  561. ⍝for each function determine if how variable is in workspace.
  562. ⍝then change to ⋆ or blank.
  563. How←2=⎕NC(((1↑⍴X),3)⍴'how'),X
  564. How←' ⋆'[1+How]
  565. ⍝now prepare report
  566. I←0
  567. l10:→((⍴N)<I←I+1)/End
  568. →(∼N[I])/l20
  569. ⍝print title of category. precede each title by <BL> blank lines
  570. BL←2
  571. Y←Y on((BL,0)⍴'')on Keys[I;]on 100⍴'-'
  572. l20:
  573. ⍝delete trailing blanks from name of function.
  574. ⍝extend name to 10 spaces or nearest multiple of 3 if
  575. ⍝not enough space to fit name
  576. T←⍴∆dtb X[I;]
  577. J←10⌈((T+2)>10)×3×⌈(2+T)÷3
  578. Y←Y on ' ',How[I],' ',(J↑X[I;]),(∆dtb Heads[I;]),'. ',1↓Purpose[I;]
  579. →l10
  580. End:
  581. ⍝remove blank lines before title of first category
  582. Y←(BL,0)↓Y
  583.  
  584. ∇Y←contents1 X;⎕IO;How;I;Keys;S
  585. ⍝quick condensed report of functions <X> by category (with line 1)
  586. ⍝.e 5=1↑⍴contents1 '∆box ∆db foofunc'
  587. ⍝.k library-utility
  588. ⍝.n rml
  589. ⍝.t 1992.4.16.11.22.1
  590. ⍝.v 1.0 / 23may85
  591. ⍝.v 1.1 / 14apr92 / function rewritten, comments clarified, how var ⋆ added
  592. ⍝report lists (category, function, purpose) sorted by function within category
  593. ⎕IO←1
  594. 'contents1' checksubroutine 'bp expandbe gettag gradeup on ∆dtb'
  595. Y←0 0⍴''
  596. X←'' ∆box ∆db,' ',X
  597. →(0∈⍴X)/0
  598. Keys←'k' gettag X
  599. ⍝sort by function
  600. S←(' ',⎕AV)gradeup X
  601. X←X[S;]
  602. Keys←Keys[S;]
  603. ⍝sort again by category. (data will be sorted by function within category.)
  604. S←(' ',⎕AV)gradeup Keys
  605. X←X[S;]
  606. Keys←Keys[S;]
  607. ⍝find break points (beginning of each category)
  608. I←bp Keys
  609. ⍝determine if how variable is in workspace. then change to ⋆ or blank.
  610. How←' ⋆'[1+2=⎕NC(((1↑⍴X),3)⍴'how'),X]
  611. ⍝now get line 1 (purpose line) and remove leading comment symbol,
  612. ⍝catenate with function names, and category names without duplicates,
  613. ⍝insert a blank line before each new category, remove first blank line
  614. Y←1 0↓(expandbe I)⍀(I⍀I⌿Keys),How,X,' ',0 1↓1 gettag X
  615.  
  616. ∇z←cpucon;ot
  617. ⍝returns elapsed cpu and connect time since function last executed
  618. ⍝.e 1 ∆ cpucon
  619. ⍝.k timing
  620. ⍝.t 1992.3.28.15.21.51
  621. ⍝.v 1.0 / 20oct83
  622. ⍝check for old time (ot)
  623. ⍎(0=⎕NC 'g∆cpucon∆ot')/'g∆cpucon∆ot←⎕AI'
  624. ot←g∆cpucon∆ot
  625. ⍝cpu,connect is ⎕AI[2 3]
  626. ⍝find cpu and connect since last call
  627. z←(2↑1↓⎕AI)-2↑1↓ot
  628. ⍝reset global
  629. g∆cpucon∆ot←⎕AI
  630.  
  631. ∇y←date
  632. ⍝return today's date in format (monthname dd, yyyy)
  633. ⍝.e 1 ∆ date
  634. ⍝.k date
  635. ⍝.t 1992.4.9.10.28.25
  636. ⍝.v 1.0 / 19nov86
  637. ⍝.v 1.1 / 09apr92 / replace detailed code with call to <fdate>
  638. 'date' checksubroutine 'fdate'
  639. y←'e' fdate ⎕TS[2 3 1]
  640.  
  641. ∇y←days d;⎕IO;n;p
  642. ⍝compute Gregorian day count for dates <d> = (mm dd yyyy)
  643. ⍝.e 725870 = days 5 13 1988
  644. ⍝.k date
  645. ⍝.t 1992.4.9.16.30.9
  646. ⍝.v 1.0 / 17may77
  647. ⍝.v 1.1 / 09apr92 / using signalerror
  648. ⍝<d> can be 3-element vector (1 date), or matrix of dates
  649. ⍝<y> is number of days elapsed from 1/1/1 to <d>
  650. ⎕IO←1
  651. d←(¯2↑1 1,⍴d)⍴d
  652. →(3≠¯1↑⍴d)signalerror '/y/days length error/last coordinate of right arg not equal to 3.'
  653. n←(0,[0.0999999999999999778]4 100 400)⊤d[;3]
  654. p←=⌿0=n[2;;]
  655. n←(365×d[;3]-1)+-⌿n[1;;],[1]p
  656. y←n+d[;2]+(⌊30.5599999999999916×d[;1])-30+(d[;1]≥3)×2-p
  657.  
  658. ∇y←ddup x
  659. ⍝delete duplicate elements from vector or matrix <x>
  660. ⍝.e 'abcd' = ddup 'aabbccddaabb'
  661. ⍝.k delete-elements
  662. 'ddup' checksubroutine 'first'
  663. y←(first x)⌿x
  664.  
  665. ∇Y←Code deltag Fns;⎕IO;Fn;I;J;Mat;T
  666. ⍝delete tag line labelled with <Code> from functions <Fns>
  667. ⍝.k library-utility
  668. ⍝.n rml
  669. ⍝.t 1989.7.24.18.17.10
  670. ⍝.v 1.0 / 04nov83
  671. ⍝.v 1.1 / 24jul89 / error message changes, ⎕IO localized
  672. ⎕IO←1
  673. Y←⍳0
  674. ⍎(2≠⍴⍴Fns)/'Fns←'' '' ∆box ∆db Fns'
  675. ⍝----- do it for every function
  676. J←0
  677. L10:→((J←J+1)>1↑⍴Fns)/End
  678. Mat←⎕CR Fn←Fns[J;]
  679. ⍝----- make sure Mat has at least one line
  680. →((0=1↑⍴Mat)/L15),L0
  681. ⍝no line. cannot get cr.
  682. L15:
  683. ⎕←'...deltag domain error.'
  684. ⎕←'...cannot get canonical form for ',Fn
  685. →Blend
  686. L0: ⍝this Mat has at least one line. search for tag line
  687. I←Mat[;⍳4]∧.='⍝.',2↑Code
  688. →(0=∨/I)/L1
  689. ⍝found it. so remove it and fix function
  690. T←⎕FX(∼I)⌿Mat
  691. →(0≠1↑0⍴T)/Lend
  692. ⎕←'...deltag error'
  693. ⎕←'...error when fixing function = ',Fn,' line = ',(⍕T),' ',Mat[T;]
  694. →Blend
  695. L1: ⍝did not find it. so skip it
  696. →Lend
  697. Lend:
  698. Y←Y,1
  699. →L10
  700. Blend:
  701. Y←Y,0
  702. →L10
  703. End:
  704.  
  705. ∇describe;⎕IO;x
  706. ⍝driver menu function for overall description of toolkit workspace
  707. ⍝.k library-utility
  708. ⍝.n rml
  709. ⍝.t 1992.4.27.14.50.40
  710. ⍝.v 1.0 / 27apr92
  711. ⎕IO←1
  712. l10:
  713. ⎕←' '
  714. ⎕←howdescribeindex
  715. x←⎕
  716. →l10 ∆if 0=(∼x∈0,⍳9)signalerror '//Please enter a listed topic number.'
  717. →0 ∆if x=0
  718. ⍝delete potential leading blank (in case APL implementation appends it)
  719. ⎕←⍎'howdescribe',∆db⍕x
  720. →l10
  721.  
  722. ∇describe∆cr2lf
  723. 'cr2lf string'
  724. ' '
  725. 'converts cr (13) characters in string to lf (10). Old APL2'
  726. 'used cr to terminate lines, while GNU APL needs lf (unix'
  727. 'convention).'
  728.  
  729. ∇y←dfh x;⎕IO;n
  730. ⍝return decimal values of hex numbers <x>
  731. ⍝.e 10 274 = dfh 2 3⍴'00a112'
  732. ⍝.k translation
  733. ⍝.t 1992.4.16.21.9.44
  734. ⍝.v 1.0 / 00sep85
  735. ⍝.v 1.1 / 12apr88 / arg checking and reshaping improved
  736. ⍝.v 1.2 / 16apr92 / signalerror used
  737. ⍝each hex number is one row of a matrix
  738. ⍝warning: hex numbers must be zero-padded on the right if necessary
  739. ⎕IO←0
  740. →((⍴⍴x)>2)signalerror '/y/dfh rank error/right arg greater than rank 2'
  741. →(0∈⍴y←x)/0
  742. x←(¯2↑1 1,⍴x)⍴x
  743. y←16⊥'0123456789abcdef'⍳⍉x
  744.  
  745. ∇r←rcm dimension m;⎕IO;c;j;k;l;z
  746. ⍝compute (n-1) dimension array from coordinate/data matrix <m>
  747. ⍝.k reshape
  748. ⍝.n dan king
  749. ⍝.t 1992.4.25.17.36.18
  750. ⍝.v 1.0 / 23may85
  751. ⍝.v 1.1 / 25apr92 / using signalerror
  752. ⍝<m> has (n-1) attribute columns and 1 data column
  753. ⎕IO←1
  754. →((¯1↑⍴m)<2)signalerror '/r/dimension length error/last coordinate of right arg < 2'
  755. →((1↑⍴rcm)≠¯1+¯1↑⍴m)signalerror '/r/dimension length error/left and right args not conformable.'
  756. c←1
  757. z←0 1⍴0
  758. do:
  759. m←(m[;c]∈rcm[c;])⌿m
  760. j←rcm[c;]⍳m[;c]
  761. j←(¯2↑1 1,⍴j)⍴j
  762. z←(¯2↑1 1,⍴z)⍴z
  763. k←⌈/(⍴j)[2],(⍴z)[2]
  764. z←(((1↑⍴z),k)↑z),[1]((1↑⍴j),k)↑j
  765. →((¯1↑⍴m)≥1+c←c+1)/do
  766. z←z-1
  767. z[1↑⍴z;]←z[1↑⍴z;]+1
  768. j←+/rcm≠0
  769. k←j⊥z
  770. l←(×/j)⍴0
  771. l[k]←(0,¯1+¯1↑⍴m)↓m
  772. r←j⍴l
  773.  
  774. ∇y←e displayfunction a;⎕IO;b;n;r;z
  775. ⍝display of canonical matrix <a> using exdents <e>
  776. ⍝.e 'display'=7↑13↓20⍴4 displayfunction ⎕CR 'displayfunction'
  777. ⍝.k formatting
  778. ⍝.t 1992.3.13.20.59.55
  779. ⍝.v 1.0 / 13may88
  780. ⍝.v 2.0 / 13mar92 / new left argument, more comments, removed displayfunction1
  781. ⍝<e> = exdents for comments, branches, labels respectively
  782. ⎕IO←1
  783. y←0 0⍴''
  784. →(0∈⍴a)/0
  785. a←(¯2↑1 1,⍴a)⍴a
  786. ⍝compute left argument with defaults (defaults are usual system settings)
  787. e←e,(×/⍴e)↓1 0,1↑e,1
  788. ⍝compute location b of labelled lines (contains : not in quotes or comment)
  789. z←a=':'
  790. b←∨/z
  791. b←(a[;1]≠'⍝')∧b\(+/∨\b⌿z)>+/∨\''''=b⌿a
  792. ⍝compute rotations for comment lines, branch lines, labelled lines
  793. r←(e[1]×a[;1]='⍝')+(e[2]×a[;1]='→')+e[3]×b
  794. ⍝compute line numbers and rotations for 1-digit, 2-digit, etc.
  795. n←¯1+1↑⍴a
  796. z←n↑((n⌊9)⍴2),(0⌈90⌊n-9)⍴1
  797. ⍝form the complete function display
  798. y←((' ',[1]'[',z⌽(3 0⍕(n,1)⍴⍳n),']'),r⌽(((1↑⍴a),⌈/e)⍴' '),a),[1]' '
  799. y[1,n+2;5]←'∇'
  800.  
  801. ∇r←u dround v;e;n;⎕CT;⎕IO
  802. ⍝distributive rounding of a vector <v> to arbitrary scalar unit <u>
  803. ⍝.e (.01 dround +/100.982 100.973 100.966) = +/.01 dround 100.982 100.973 100.966
  804. ⍝.k computation
  805. ⍝.t 1989.7.23.22.15.9
  806. ⎕CT←⎕IO←0
  807. v←,v÷u
  808. e←1|v
  809. n←(⌊0.5++/v)-+/⌊v
  810. r←u×(⌊v)+n>⍋⍒e
  811.  
  812. ∇z←ds x;⎕IO
  813. ⍝set of descriptive statistics for data <x>
  814. ⍝.e 5.5 = (ds ⍳10)[2]
  815. ⍝.k computation
  816. ⍝.n k.w.smillie
  817. ⍝.t 1992.4.14.21.21.1
  818. ⍝.v 1.0 / 15feb69 / original Statpack2 version slightly modified
  819. ⎕IO←1
  820. z←10⍴0
  821. z[1]←⍴x←x[⍋x]
  822. z[2]←(+/x)÷z[1]
  823. z[3]←(+/(x-z[2])⋆2)÷z[1]-1
  824. z[4]←z[3]⋆0.5
  825. z[5]←z[4]÷z[1]⋆0.5
  826. z[6]←(+/|x-z[2])÷z[1]
  827. z[7]←0.5×+/x[(⌈z[1]÷2),1+⌊z[1]÷2]
  828. z[8 9]←x[z[1],1]
  829. z[10]←-/z[8 9]
  830.  
  831. ∇dstat x;z
  832. ⍝labelled set of descriptive statistics for data <x>
  833. ⍝.k computation
  834. ⍝.n k. w. smillie
  835. ⍝.t 1992.4.14.21.26.39
  836. ⍝.v 1.0 / 15feb69 / original Statpack2 version slightly modified
  837. 'dstat' checksubroutine 'ds'
  838. z←ds x
  839. 'sample size.......... ',⍕z[1]
  840. 'mean................. ',⍕z[2]
  841. 'variance............. ',⍕z[3]
  842. 'standard deviation... ',⍕z[4]
  843. 'standard error....... ',⍕z[5]
  844. 'mean deviation....... ',⍕z[6]
  845. 'median............... ',⍕z[7]
  846. 'maximum.............. ',⍕z[8]
  847. 'minimum.............. ',⍕z[9]
  848. 'range................ ',⍕z[10]
  849.  
  850. ∇y←a duparray m;⎕IO;newarray;shape
  851. ⍝duplicate array <m>. duplicate <a[1]> times along coordinate <a[2]>
  852. ⍝.e (2 6⍴'abababcdcdcd') = 3 2 duparray 2 2⍴'abcd'
  853. ⍝.k reshape
  854. ⍝.n rml
  855. ⍝.t 1992.4.25.17.28.1
  856. ⍝.v 1.0 / 14feb84
  857. ⍝.v 1.1 / 25apr92 / using signalerror
  858. ⍝a[2] must be in the range (1,⍴⍴m)
  859. ⍝note: the algorithm consists of applying <reparray> to
  860. ⍝ (1,⍴m)⍴m and then reshaping the result.
  861. ⎕IO←1
  862. 'duparray' checksubroutine 'reparray'
  863. ⍝default a[2] to last coordinate
  864. a←2↑a,⍴⍴m
  865. →(∼(1≤a[2])∧a[2]≤⍴⍴m)signalerror '/y/duparray domain error/coordinate specification (',(⍕a[2]),') outside range (1,',(⍕⍴⍴m),')'
  866. newarray←a reparray(1,⍴m)⍴m
  867. shape←×/(⍴m),[1.5](a[2]≠⍳⍴⍴m)+(a[2]=⍳⍴⍴m)×a[1]
  868. y←shape⍴newarray
  869.  
  870. ∇y←n duparray1 m
  871. ⍝duplicate array <m>. duplicate <n> times along coordinate 1
  872. ⍝.e (6 2⍴'abcdabcdabcd') = 3 duparray1 2 2⍴'abcd'
  873. ⍝.k reshape
  874. ⍝.n rml
  875. ⍝.v 1.0 / 10feb84
  876. ⍝simplified version of duparray which handles first dimension only
  877. y←((n×1↑⍴m),1↓⍴m)⍴(n,⍴m)⍴m
  878.  
  879. ∇z←easter ys;c;epact;g;n;s;x;y
  880. ⍝compute date of Easter (mm dd yyyy) for years <ys> = (yyyy style)
  881. ⍝.e 4 15 1990 = ,easter 1990
  882. ⍝.k date
  883. ⍝.t 1992.4.5.23.19.47
  884. ⍝.v 1.0 / 05may88
  885. ⍝.v 1.1 / 05apr92 / matrix result in format (mm dd yyyy), signalerror used
  886. ⍝ys can be a vector of years or an array of years and styles.
  887. ys←(2↑(⍴ys),1 1)⍴ys
  888. y←ys[;⎕IO]
  889. →(y∨.<33)signalerror '/z/easter domain error/Easter was not celebrated before 33 A.D.'
  890. s←(y>1922)∨(y>1583)∧(ys,1752<y)[;⎕IO+1]
  891. c←1+⌊0.00999999999999999674×y
  892. x←s×2-⌊0.75×c
  893. g←1+19|y
  894. epact←30|20+(s×10+⌊0.319999999999999896×c-15)+x+11×g
  895. n←44-epact+s×(epact=24)∨(epact=25)∧g>11
  896. n←n+30×n<21
  897. n←n+7-7|n+7|x+⌊1.25×y
  898. ⍝n[i] represents day of easter within march or april for ys[i;]
  899. ⍝return decoded matrix with z[i;] in format mm dd yyyy
  900. z←⍉(3,⍴n)⍴((3×n≤30)+4×n≥31),(1+31|¯1+n),y
  901.  
  902. ∇Y←X example N;⎕IO;B;C;I;L;Name;R;Result;Trace
  903. ⍝display and execute an example for functions <N>. <X> specifies options.
  904. ⍝.e '1' = (2 example '∆box')[1;1]
  905. ⍝.k library-utility
  906. ⍝.t 1992.4.16.20.11.31
  907. ⍝.v 1.0 / 12apr88 / terminal output and result of example line of one function
  908. ⍝.v 2.0 / 15jul89 / first version of example with explicit result
  909. ⍝.v 3.0 / 16apr92 / combined <test> and <example>, new left arg
  910. ⍝<example> executes the .e example for each function in the list <N>.
  911. ⍝<X> specifies options for trace messages and result.
  912. ⍝X=1 -- display trace, X=2 -- return report, X=3 -- do both, X=0 -- do neither
  913. ⍝Note two situations:
  914. ⍝(1) if execution suspends, the function or the example could be wrong.
  915. ⍝(2) if an error is noted, then something is wrong enough to give an
  916. ⍝ incorrect result, but not bad enough to cause suspension.
  917. ⍝in either case, the example in question caused the problem and should be
  918. ⍝reviewed. either the example or the function code could be the
  919. ⍝cause of the problem. if <example> successfully executed examples for other
  920. ⍝functions, it is unlikely that there is an error in <example> itself.
  921. ⎕IO←1
  922. ⍝check and decode left arg (an encoding of 2-element binary vector)
  923. X←1↑X,1
  924. →(∼∧/X∈0,⍳3)signalerror '/Y/example domain error/left arg not a member of 0 1 2 3'
  925. X←,2 2⊤X
  926. Trace←X[2]
  927. Result←X[1]
  928. Y←0 1⍴''
  929. N←'' ∆box ∆db,' ',N
  930. I←0
  931. L10:
  932. →((1↑⍴N)<I←I+1)/0
  933. Name←N[I;]
  934. ⍝L is blank line if function locked, not found, or no example 'e' found
  935. L←,'e' gettag Name
  936. →Skip1 ∆if∼Trace
  937. ⎕←Name
  938. →Skip1 ∆if∧/L=' '
  939. ⍝example text indented 6 positions in apl terminal style
  940. ⎕←' ',L
  941. Skip1:
  942. →L15 ∆if 3≠⎕NC Name
  943. →L20 ∆if∧/L=' '
  944. ⍝execute exampleline. exampleline should have form: result = expression
  945. ⍝∧/,examplelline returns 1 if the expression gives the result we expect
  946. ⍝if it returns 0 or suspends, check it out! function or example may be wrong.
  947. B←⍎L
  948. →(1 0=∧/,B)/Lok,Lnok
  949. Lok:
  950. R←'1: ',L
  951. C←'... ok'
  952. →L99
  953. Lnok:
  954. R←'0: ',L
  955. C←'... example returns unexpected result. review function ',Name
  956. →L99
  957. L15:
  958. R←'9: function ',Name,' not found.'
  959. C←'... ',3↓R
  960. →L99
  961. L20:
  962. R←'8: no .e example found in ',Name
  963. C←'... ',3↓R
  964. →L99
  965. L99:
  966. ⍝non-empty explicit result depends on option chosen
  967. →L100 ∆if∼Result
  968. Y←Y on R
  969. L100:
  970. ⍝do not display ending message if trace is off
  971. ⍝note: to suppress display of ok ending message, append ∨'1'=1↑R to line
  972. →L10 ∆if∼Trace
  973. ⎕←' ',C
  974. →L10
  975.  
  976. ∇r←expandaf w
  977. ⍝<r> is expansion vector to insert <w[i]⍴0> after the i-th position
  978. ⍝.e 1 0 2 0 0 3 0 0 0 = (expandaf 1 2 3 )\1 2 3
  979. ⍝.k expansion
  980. ⍝.t 1988.4.5.18.44.4
  981. ⍝.v 1.0 / 12may88
  982. 'expandaf' checksubroutine 'expandbe'
  983. r←¯1↓expandbe 0,w
  984.  
  985. ∇r←expandbe w
  986. ⍝<r> is expansion vector to insert <w[i]⍴0> before the i-th position
  987. ⍝.e 0 1 0 0 2 0 0 0 3 = (expandbe 1 2 3 )\1 2 3
  988. ⍝.k expansion
  989. ⍝.t 1988.4.5.18.44.4
  990. ⍝.v 1.0 / 12may88
  991. r←(⍳⍴w)++\w
  992. r←(⍳¯1↑r+∼⎕IO)∈r
  993.  
  994. ∇Y←explain X;⎕IO;I
  995. ⍝explain functions <x>. return how documents for specified functions
  996. ⍝.e 1 ∆ explain '∆box'
  997. ⍝.k library-utility
  998. ⍝.n rml
  999. ⍝.t 1992.4.1.23.59.18
  1000. ⍝.v 2.0 / 22may85 / first published version
  1001. ⍝.v 2.1 / 14jul89 / revised based on explain and makedoc
  1002. ⍝.v 3.0 / 01apr92 / no longer using <script> and script documents
  1003. ⍝underscored variables to avoid shadowing function names
  1004. ⍝how documents are vectors delimited by returns (<g∆cr>)
  1005. ⎕IO←1
  1006. Y←''
  1007. X←'' ∆box ∆db,' ',X
  1008. I←0
  1009. L10:
  1010. →((1↑⍴X)<I←I+1)/Lend
  1011. →((3≠⎕NC X[I;]),(2≠⎕NC 'how',X[I;]),1)/L2nf,L2nh,L2ok
  1012. L2nf:
  1013. Y←Y,X[I;],': function not in workspace.'
  1014. →L2end
  1015. L2nh:
  1016. Y←Y,X[I;],': how document not in workspace.'
  1017. →L2end
  1018. L2ok:
  1019. Y←Y,⍎'how',X[I;]
  1020. →L2end
  1021. L2end:
  1022. ⍝2 blank lines after each document
  1023. Y←Y,2⍴g∆cr
  1024. →L10
  1025. Lend:
  1026. ⍝remove the two blank lines after last document
  1027. Y←¯2↓Y
  1028.  
  1029. ∇Buffer←fagl X;⎕IO;B
  1030. ⍝find all global referents in function <X> and functions called by <X>
  1031. ⍝.e '⎕EX'=3⍴fagl 'signalerror'
  1032. ⍝.k programming-tools
  1033. ⍝.t 1992.4.4.13.31.48
  1034. ⍝.v 1.0 / 30jul89
  1035. ⍝.v 1.1 / 04apr92 / improved arg checking and passing to fglr, signalerror used
  1036. ⍝requires ⎕IO←1 because of <gradeup>
  1037. ⎕IO←1
  1038. 'fagl' checksubroutine 'fgl fglr global gradeup on ∆rowmem'
  1039. →(0 1∧.≠⍴⍴X)signalerror '/Buffer/fagl rank error/right arg not rank 0 or 1.'
  1040. →(3≠⎕NC X)signalerror '/Buffer/fagl domain error/(',X,') not a function.'
  1041. →(0∈⍴⎕CR X)signalerror '/Buffer/fagl domain error/function (',X,') locked.'
  1042. Buffer←0 0⍴''
  1043. ⍝<fglr> requires matrix argument
  1044. fglr(1,⍴X)⍴X
  1045. Buffer←Buffer['' gradeup Buffer;]
  1046.  
  1047. ∇z←fcpucon x;a;b;con;cpu;⎕IO
  1048. ⍝format cpu and connect time integers <x>
  1049. ⍝.e 1 ∆ fcpucon cpucon
  1050. ⍝.k timing
  1051. ⍝.t 1989.7.31.9.6.27
  1052. ⍝.v 1.0 / 20oct83
  1053. ⎕IO←1
  1054. cpu←,0 60000⊤x[1]
  1055. con←,0 60000⊤x[2]
  1056. ⍝format minutes to a minimum of two spaces (99)
  1057. a←(-2⌈⍴a)↑a←,⍕cpu[1]
  1058. b←(-2⌈⍴b)↑b←,⍕con[1]
  1059. z←'cpu=',a,' m ',(6 3⍕cpu[2]÷1000),' s connect=',b,' m ',(6 3⍕con[2]÷1000),' s'
  1060.  
  1061. ∇y←lc fdate t;⎕IO;mo
  1062. ⍝format dates <t> = (mm dd yyyy) as <y> = (monthname dd, yyyy)
  1063. ⍝.e 'november 19, 1986' = ,'e' fdate 11 19 1986
  1064. ⍝.k date
  1065. ⍝.t 1992.4.5.23.15.29
  1066. ⍝.v 1.0 / 19nov86
  1067. ⍝.v 2.0 / 05apr92 / right arg now matrix (mm dd yyyy), added language code
  1068. ⍝<t> is vector or matrix of dates in format (mm dd yyyy)
  1069. ⍝<lc> is language code. 'e'=english, 'f'=french
  1070. ⎕IO←1
  1071. ⍝reshape arg <t> to matrix (possibly one-row)
  1072. t←(¯2↑1 1,⍴t)⍴t
  1073. ⍝check months (for one argument check, this is as good as any!)
  1074. →(∼∧/t[;1]∈⍳12)signalerror '/y/fdate domain error/right arg (month) not in the set ⍳12'
  1075. →(∼lc∈'ef')signalerror '/y/fdate domain error/left arg (language code) not in the set (ef).'
  1076. ⍝define month names in specified language.
  1077. mo←'january/february/march/april/may/june/july/august/september/october/november/december'
  1078. →(lc='e')/next
  1079. mo←'janvier/fevrier/mars/avril/mai/juin/juillet/aout/septembre/octobre/novembre/decembre'
  1080. next:mo←'/' ∆box mo
  1081. ⍝create character matrix, ravel, remove redundant blanks, recreate matrix
  1082. y←'/' ∆box ∆db,mo[t[;⎕IO];],' ',(⍕t[;,⎕IO+1]),',',' ',(⍕t[;,⎕IO+2]),'/'
  1083.  
  1084. ∇y←fdmy t;⎕IO;mon
  1085. ⍝format dates <t> = (mm dd yyyy) as <y> = (dd mon yy)
  1086. ⍝.e '20 jun 47' = ,fdmy 6 20 1947
  1087. ⍝.k date
  1088. ⍝.n rml
  1089. ⍝.t 1992.4.9.9.18.48
  1090. ⍝.v 1.0 / 31oct83
  1091. ⍝.v 2.0 / 09apr92 / right arg now matrix in format (mm dd yyyy)
  1092. ⎕IO←1
  1093. ⍝reshape arg <t> to matrix (possibly one-row)
  1094. t←(¯2↑1 1,⍴t)⍴t
  1095. ⍝check months (for one argument check, this is as good as any!)
  1096. →(∼∧/t[;1]∈⍳12)signalerror '/y/fdmy domain error/right arg (month) not in the set ⍳12'
  1097. mon←12 3⍴'janfebmaraprmayjunjulaugsepoctnovdec'
  1098. ⍝get last 2 digits of each year (e.g. 1947 is 47). ensure 1-column matrix
  1099. ⍝create character matrix, one row for each date, in new format
  1100. y←(2 0⍕t[;,2]),' ',mon[t[;1];],' ',2 0⍕⍉(100 100⊤t[;3])[,2;]
  1101.  
  1102. ∇Z←fgl X;T
  1103. ⍝find global referents of function <X>
  1104. ⍝.e '⎕CR' = 3↑(fgl 'fgl')[⎕IO;]
  1105. ⍝.k programming-tools
  1106. ⍝.t 1992.3.27.21.34.19
  1107. ⍝.v 1.0 / 05may88 / first version
  1108. ⍝.v 1.1 / 30jul89 / better right arg checking
  1109. ⍝.v 1.2 / 27mar92 / revised error checking, signalerror used
  1110. 'fgl' checksubroutine 'global'
  1111. →(0 1∧.<⍴⍴X)signalerror '/Z/fgl rank error/right arg not rank 0 or 1.'
  1112. →(3≠⎕NC X)signalerror '/Z/fgl domain error/(',X,') not a function.'
  1113. T←⎕CR X
  1114. →(0∈⍴T)signalerror '/Z/fgl domain error/function (',X,') locked.'
  1115. ⍝X must be exactly the name of the function (no blanks)
  1116. Z←((X≠' ')/X)global T
  1117.  
  1118. ∇fglr X;Y
  1119. ⍝subroutine. find global referents recursively for objects specified in <X>
  1120. ⍝.k programming-tools
  1121. ⍝.t 1992.4.4.13.44.53
  1122. ⍝.v 1.0 / 30jul89
  1123. ⍝.v 1.1 / 04apr92 / minor changes to arg passing and comments
  1124. ⍝recursive subroutine for <fagl>
  1125. ⍝<X> is always a matrix (possibly empty)
  1126. →(0∈⍴X)/0
  1127. →(1 0=1=1↑⍴X)/L1,L2
  1128. L1:
  1129. ⍝one name
  1130. X←,X
  1131. ⍝global referent may be a variable, not function. quit now.
  1132. →(3≠⎕NC X)/0
  1133. ⍝global referent may be a locked function. can't go further. quit now.
  1134. →(0∈⍴⎕CR X)/0
  1135. Y←fgl X
  1136. ⍝if names already on buffer, remove them.
  1137. ⍝this situation occurs if there is a recursive global referent, that is,
  1138. ⍝some function calls another function recursively at some level.
  1139. Y←(∼Y ∆rowmem Buffer)⌿Y
  1140. Buffer←Buffer on Y
  1141. ⍝a recursive step!
  1142. ⍝get global referents for all the global objects found
  1143. fglr Y
  1144. →0
  1145. L2:
  1146. ⍝more than one name
  1147. ⍝a recursive step!
  1148. ⍝ (1) get global referents of first object
  1149. ⍝ (2) get global referents of all the other objects
  1150. fglr X[,⎕IO;]
  1151. fglr 1 0↓X
  1152.  
  1153. ∇r←fi a;m;⎕IO
  1154. ⍝fix (translate) text input <a> to numeric vector
  1155. ⍝.e 1 2 0 0 123.35 = fi '1 2 1a 3.3.3 123.35'
  1156. ⍝.k translation
  1157. ⍝.n jeffrey multach
  1158. ⍝.t 1989.7.27.23.11.43
  1159. ⍝.v 1.0 / dec80
  1160. ⎕IO←1
  1161. 'fi' checksubroutine 'vi'
  1162. r←vi ' ',a
  1163. →(∧/0=r)/0
  1164. ⍝form mask for characters to convert
  1165. m←a≠' '
  1166. m←m>0,¯1↓m
  1167. ⍝mask out and convert valid numbers
  1168. r[r/⍳⍴r]←⍎(≠\m\r[1],(1↓r)≠¯1↓r)/a
  1169.  
  1170. ∇m←a fibspiral b;c
  1171. ⍝fibonacci spiral. choose neighbouring pairs <a>,<b> from fibonacci series
  1172. ⍝.e (3 5⍴' ○○ ○ ○ ○○ ○ ') = 3 fibspiral 5
  1173. ⍝.k graphics
  1174. ⍝.t 1985.9.20.19.37.50
  1175. ⍝choose <a>,<b> ∈ 1 1 2 3 5 8 13 21 34 ... where a immediately precedes b
  1176. c←'○'
  1177. →(a>1)/l1
  1178. m←1 2⍴c
  1179. →0
  1180. l1:m←(b-a)fibspiral a
  1181. m←⊖⍉m
  1182. m←m,(a,a)⍴c,a⍴' '
  1183.  
  1184. ∇a←n field m;i;j
  1185. ⍝subroutine for <tower>
  1186. ⍝.k plotting
  1187. ⍝return 'ground' or 'field' for the tower chart
  1188. a←((7×n)+1,17×m)⍴' '
  1189. j←1+i←0
  1190. l1:
  1191. a[1+7×n-i;(i×7)+⍳m×17]←'_'
  1192. →(n≥i←i+1)/l1
  1193. l2:
  1194. a[(7×n)+2-j;j,j+17×⍳m]←'/'
  1195. →((7×n)≥j←j+1)/l2
  1196.  
  1197. ∇z←m findcoords s;coord;match
  1198. ⍝find coordinates of sequence <s> in matrix <m>
  1199. ⍝.e (6 2⍴1 2 1 3 3 1 4 2 4 3 6 1) = (6 5⍴'applebettypie ') findcoords 'p'
  1200. ⍝.k searching
  1201. ⍝.t 1989.7.27.22.15.47
  1202. ⍝use outer product to find every occurrence of substring present in matrix.
  1203. ⍝if substring is present, there will be a sequence of 1's in the first
  1204. ⍝dimension, that is, result[1;x;y], result[1;x;y+1], result[1;x;y+2] etc.,
  1205. ⍝will be 1.
  1206. match←(,s)∘.=m
  1207. ⍝the phrase (...)⌽match lines up sequences. each successive row is
  1208. ⍝rotated one more than the previous row.
  1209. ⍝the phrase ∧⌿ finds if there were any sequences.
  1210. coord←∧⌿(⍉(⌽¯1↓⍴match)⍴-⎕IO-⍳⍴,s)⌽match
  1211. z←⎕IO+⍉(⍴coord)⊤-⎕IO-(,coord)/⍳⍴,coord
  1212.  
  1213. ∇y←a findut b;z
  1214. ⍝find position of unique truncation <b> in vector <a>
  1215. ⍝.e 4=' apple betty cat boop' findut 'bo'
  1216. ⍝.k searching
  1217. ⍝.n j.p. benyi
  1218. ⍝.t 1992.4.16.20.57.36
  1219. ⍝.v 1.0 / 00xxx74
  1220. ⍝<y> =¯1: not unique; =0: not found; >0: index of <b> in <a>
  1221. ⍝<a> must contain fields each preceeded by a blank: ' xxx xxx xxxxx xx'
  1222. b←,b
  1223. z←(1-⍴b)↓a
  1224. z←(z=1↑b)/⍳⍴z
  1225. z←(a[z+y←¯1]=' ')/z
  1226. z←(a[z∘.+¯1+⍳⍴b]∧.=b)/z
  1227. →(1<⍴z)/0
  1228. y←' '+.=(1↑z)↑a
  1229.  
  1230. ∇y←first x
  1231. ⍝first occurrence of elements in scalar, vector or matrix <x>
  1232. ⍝.e 1 1 1 0 0 0 = first 6 5⍴'applebettycat '
  1233. ⍝.k searching
  1234. ⍝.t 1992.4.3.17.28.14
  1235. ⍝.v 1.0 / 07apr88
  1236. ⍝.v 1.1 / 03apr92 / improved comments, signalerror used, scalar arg allowed
  1237. →(0 1 2∧.≠⍴⍴x)signalerror '/y/first rank error'
  1238. →(0 1 2=⍴⍴x)/l1,l1,l2
  1239. l1:
  1240. ⍝ for vectors this is the often-used algorithm (x←,x allows scalar case)
  1241. x←,x
  1242. y←(x⍳x)=⍳⍴x
  1243. →0
  1244. l2:
  1245. ⍝ x∧.=⍉x compute comparison matrix
  1246. ⍝ <⍀ turn off all 1's after first 1 in each column.
  1247. ⍝ (first 1 in row i indicates x[i;] is first occurrence).
  1248. ⍝ (all 1's after first 1 indicate second, etc. occurrence).
  1249. ⍝ ∨/ select all rows containing a 1.
  1250. ⍝ y[i]=1 indicates that x[i;] is first occurrence
  1251. y←∨/<⍀x∧.=⍉x
  1252. →0
  1253.  
  1254. ∇y←fisodate t;⎕IO
  1255. ⍝format dates <t> = (mm dd yyyy) as <y> = (yyyy-mm-dd)
  1256. ⍝.e '1992-04-09' = ,fisodate 4 9 1992
  1257. ⍝.k date
  1258. ⍝.t 1992.4.9.9.58.55
  1259. ⍝.v 1.0 / 22sep85
  1260. ⍝.v 2.0 / 09apr92 / added matrix right arg, name change (isodate->fisodate)
  1261. ⍝iso format is yyyy-mm-dd, with leading zeros if necessary
  1262. ⎕IO←1
  1263. ⍝reshape arg <t> to matrix (possibly one-row)
  1264. t←(¯2↑1 1,⍴t)⍴t
  1265. ⍝check months (for one argument check, this is as good as any!)
  1266. →(∼∧/t[;1]∈⍳12)signalerror '/y/fisodate domain error/right arg (month) not in the set ⍳12'
  1267. y←(4 0⍕t[;,3]),'-',(2 0⍕t[;,1]),'-',2 0⍕t[;,2]
  1268. ⍝replace spaces by zeros everywhere in matrix
  1269. y←(⍴y)⍴(' '=y)⊖y,[0.5]'0'
  1270.  
  1271. ∇y←fixuparray data;⎕IO
  1272. ⍝return character matrix representation of array <data>
  1273. ⍝.e (5 2⍴'abcd abcd') = fixuparray 2 2 2⍴'abcd'
  1274. ⍝.k formatting
  1275. ⍝.n rml
  1276. ⍝.t 1992.3.19.3.32.14
  1277. ⍝.v 1.0 / 23may85
  1278. ⍝.v 1.1 / 04apr88 / remove trailing blank row
  1279. ⍝.v 1.2 / 19mar92 / clarify comments and replace <matrix> with statement
  1280. ⎕IO←1
  1281. y←⍕data
  1282. →(0 1 2=⍴⍴y)/l10,l10,end
  1283. ⍝y has rank 3 or greater. append blank row to each plane of y.
  1284. y←y,[¯1+⍴⍴y]' '
  1285. ⍝reshape y to the equivalent matrix (this is the algorithm of <matrix>)
  1286. y←((×/¯1↓⍴y),¯1↑1,⍴y)⍴y
  1287. ⍝drop trailing blank row
  1288. y←¯1 0↓y
  1289. →end
  1290. l10:y←(¯2↑1 1,⍴y)⍴y
  1291. end:
  1292.  
  1293. ∇Y←E fnlist T;⎕IO;I;Name;Text
  1294. ⍝function lister. display functions in list <T> using spacing parameters <E>
  1295. ⍝.k programming-tools
  1296. ⍝.t 1992.4.4.11.50.32
  1297. ⍝.v 2.0 / 20sep85
  1298. ⍝.v 2.1 / 02may88 / spacing between functions in report changed
  1299. ⍝.v 2.2 / 04apr92 / ⎕ output changed to explicit result, left arg added
  1300. ⍝<T> namelist of functions
  1301. ⍝<E> (1) lines between functions, (2)- parameters for <displayfunction>
  1302. ⍝example: '' fnlist 3 ⍝display all functions in workspace using defaults
  1303. ⎕IO←1
  1304. ⍝default E[1]=1; let <displayfunction> compute its own defaults if needed
  1305. E←E,(×/⍴E)↓1
  1306. Y←0 0⍴''
  1307. ⍝ Text is list of <fnlist> subroutines used twice below
  1308. 'fnlist' checksubroutine Text←'displayfunction gradeup on ∆rowmem'
  1309. T←'' ∆box ∆db,' ',T
  1310. →(∼0∈⍴T)/Lnext
  1311. ⍝ get list of ⎕NL 3 and remove all <fnlist> toolbox functions from list
  1312. Text←'' ∆box Text,' fnlist checksubroutine signalerror ∆box ∆db'
  1313. T←⎕NL 3
  1314. T←(∼T ∆rowmem Text)⌿T
  1315. Lnext:
  1316. ⍝ sort function list
  1317. T←T['' gradeup T;]
  1318. ⍝ display all functions in list
  1319. I←0
  1320. L1:
  1321. →((1↑⍴T)<I←I+1)/Lend
  1322. Text←⎕CR Name←∆db T[I;]
  1323. →((3≠⎕NC Name),(0∈⍴Text),1)/L2nf,L2nd,L2f
  1324. L2nf:Text←'... name (',Name,') not a function.'
  1325. →L2end
  1326. L2nd:Text←'... function (',Name,') not displayable (probably locked).'
  1327. →L2end
  1328. L2f:Text←(1↓E)displayfunction Text
  1329. →L2end
  1330. L2end:
  1331. ⍝ append specified number of blank lines after each function listing
  1332. Y←Y on Text on(E[1],0)⍴''
  1333. →L1
  1334. Lend:
  1335. ⍝ remove appended blank lines after last function
  1336. Y←(-E[1],0)↓Y
  1337.  
  1338. ∇y←frame x
  1339. ⍝frame (i.e. surround) an array <x> with a character
  1340. ⍝.k library-utility
  1341. ⍝.t 1992.3.10.20.44.14
  1342. y←'(',x,')'
  1343.  
  1344. ∇t←ftime ts;⎕IO
  1345. ⍝return time of day <ts> (⎕TS format) in format hh:mm:ss (am/pm)
  1346. ⍝.e '06:20:21 am' = ftime 6 20 21
  1347. ⍝.k time
  1348. ⍝.t 1992.4.22.22.14.5
  1349. ⍝.v 1.0 / 31oct83
  1350. ⍝.v 1.1 / 22apr92 / clarified comments
  1351. ⎕IO←1
  1352. ⍝ts[1 2 3] = hh mm ss
  1353. ⍝change ts[1] to t[1 2] where t[1]=0(morning) or 1(afternoon)
  1354. ⍝and t[2]=0 to 11 hours in morning or afternoon.
  1355. t←(2 12⊤ts[1]),ts[2 3]
  1356. ⍝change hour 0 to 12 (12 noon or 12 midnight).
  1357. t[2]←t[2]+12×t[2]=0
  1358. t←1+10,(2,6⍴10)⊤(⍳0)⍴100⊥t
  1359. ⍝format minutes and seconds with zeros before single-digit numbers
  1360. t←'0123456789:'[t[3 4 1 5 6 1 7 8]],' ','ap'[t[2]],'m'
  1361.  
  1362. ∇Y←N funsincat X;⎕IO;g∆sort∆columns;B;Keys;Rc
  1363. ⍝list of functions in <n> belonging to categorys specified in <x>
  1364. ⍝.e 'funsincat' ∧.= ('funsincat' funsincat 'library-utility')[1;]
  1365. ⍝.k library-utility
  1366. ⍝.n rml
  1367. ⍝.t 1992.4.23.0.51.34
  1368. ⍝.v 1.0 / 22may85
  1369. ⍝.v 2.0 / 02may88 / added left argument
  1370. ⍝.v 2.1 / 23apr92 / sort blank first, internal rewrite, enhanced right arg
  1371. ⍝<X> is one wildcard name specification for the category names
  1372. ⍝<N> is namelist of functions
  1373. ⎕IO←1
  1374. 'funsincat' checksubroutine 'gettag gradeup on sort vnames wildcard ∆dtb'
  1375. ⍝empty N defaults to ⎕NL 3 (since ⎕NL 3 and maybe N are large matrices, use ⍎)
  1376. ⍝N all blanks will become empty
  1377. N←'' ∆box ∆db,' ',⍎((0∈⍴N)/'⎕NL 3'),(∼0∈⍴N)/'N'
  1378. Rc←vnames X←∆db,' ',X
  1379. →(1≠⍴Rc)signalerror '/Y/funsincat domain error/right arg contains more than one name specification.'
  1380. →(0∈Rc)signalerror '/Y/funsincat domain error/right arg contains invalid wildcard specification.'
  1381. Y←0 0⍴''
  1382. →(0∈⍴N)/0
  1383. Keys←'k' gettag N
  1384. ⍝B[i]=1 means the .k tag-line for function i is non-blank
  1385. B←' '∨.≠⍉Keys
  1386. →(∼∨/B)/0
  1387. ⍝sort the functions whose .k key belongs to list <X>
  1388. ⍝consider only non-blank keys to avoid unnecessary computation
  1389. ⍝ensure blank comes first in collating sequence when sorting function names
  1390. ⍝all columns will be sorted
  1391. Keys←B⌿Keys
  1392. N←B⌿N
  1393. Y←(' ',⎕AV)sort ∆db(Keys wildcard X)⌿N
  1394.  
  1395. ∇Y←X gettag M;⎕IO;Cr;I;L;Tag
  1396. ⍝get line containing tag X (or line X if numeric) for functions in M
  1397. ⍝.e 'library-utility' = ,'k' gettag 'gettag'
  1398. ⍝.k library-utility
  1399. ⍝.t 1992.3.30.1.12.22
  1400. ⍝.v 1.0 / 28apr88
  1401. ⍝.v 1.1 / 24jul89 / ensure cr has sufficient columns for processing
  1402. ⍝.v 1.2 / 30mar92 / return last occurrence of a tag line (esp for v tags)
  1403. ⎕IO←1
  1404. 'gettag' checksubroutine 'on ∆dtb'
  1405. Y←0 0⍴''
  1406. M←'' ∆box ∆db,' ',M
  1407. ⍝compute actual tag phrase (⍝.k ⍝.n ... ) allow for numeric X
  1408. Tag←'⍝.',(⍕X),' '
  1409. L1:→(0∈⍴M)/End
  1410. Cr←⎕CR M[1;]
  1411. →(∼0∈⍴Cr)/Lok
  1412. ⍝return blank line if function not found or locked
  1413. L←' '
  1414. →L10
  1415. Lok:
  1416. ⍝do special processing for numeric X
  1417. →(0=1↑0⍴X)/Tagn
  1418. ⍝----- search for position of (last occurrence of) Tag line
  1419. ⍝Cr may not have sufficient columns. extend using ↑
  1420. ⍝editor's note: the next line is a good line to inspect using <bal>!
  1421. I←(⌽<\⌽(((1↑⍴Cr),⍴Tag)↑Cr)∧.=Tag)⍳1
  1422. →(1 0=I≤1↑⍴Cr)/L03,L04
  1423. L03:L←4↓Cr[I;]
  1424. →L10
  1425. L04:L←' '
  1426. →L10
  1427. ⍝----- get line X
  1428. Tagn:
  1429. ⍝does canonical form contain line X? (refer to header as line X=0)
  1430. →(1 0=(1↑⍴Cr)≥1+X)/L06,L05
  1431. L05: ⍝this function does not have line X
  1432. L←' '
  1433. →L10
  1434. L06:L←Cr[1+X;]
  1435. →L10
  1436. ⍝----- append tagline L to matrix of tag lines
  1437. L10:
  1438. Y←Y on L
  1439. M←1 0↓M
  1440. →L1
  1441. End:
  1442. Y←∆dtb Y
  1443. ⍝if Y is empty, then extend Y with a column of blanks
  1444. Y←((1↑⍴Y),(1 0=0∈⍴Y)/1,¯1↑⍴Y)↑Y
  1445.  
  1446. ∇Y←getvtag M;⎕IO;Cr;Tag
  1447. ⍝get tag lines identified by .v for function <M>
  1448. ⍝.e 1=1⍴⍴getvtag 'getvtag'
  1449. ⍝.k library-utility
  1450. ⍝.t 1992.4.16.21.57.39
  1451. ⍝.v 1.0 / 16apr92
  1452. ⎕IO←1
  1453. Y←0 0⍴''
  1454. Tag←'⍝.v '
  1455. Cr←⎕CR M
  1456. ⍝return empty if function not found or locked
  1457. →(0∈⍴Cr)/0
  1458. ⍝Cr may not have sufficient columns. extend using ↑
  1459. Y←∆db 0 4↓((((1↑⍴Cr),4)↑Cr)∧.=Tag)⌿Cr
  1460.  
  1461. ∇g←f global m;⎕IO;b;l;w;x
  1462. ⍝global referents in canonical form <m> of function <f>
  1463. ⍝.e '⎕CR'=3⍴'fgl' global ⎕CR 'fgl'
  1464. ⍝.k programming-tools
  1465. ⍝.n roger hui
  1466. ⍝.t 1988.4.30.18.24.1
  1467. ⍝.v 1.0 / jun80
  1468. ⎕IO←1
  1469. g←',',m
  1470. l←g[1;]
  1471. l←(-+/∧\⌽l∈' ')↓l
  1472. x←⌽(¯1+l⍳';')↑l
  1473. l[(⍳⍴f)+(⍴x)-(⍴f)+(' '∈x)×x⍳' ']←' '
  1474. b←≠\g∈''''
  1475. b←b⍱∨\b<g∈'⍝'
  1476. l←l,';⎕;',(,⌽∨\⌽b∧g∈':')/,g
  1477. w←' ⎕abcdefghijklmnopqrstuvwxyz∆ABCDEFGHIJKLMNOPQRSTUVWXYZ⍙0123456789'
  1478. g←l,(1↓⍴g)↓(,b)/,g
  1479. x←g∈1↓w
  1480. g←1↓(x∨1⌽x)/g
  1481. f←(∼b←g∈1↓w)/⍳⍴g
  1482. x←¯1+⌈/f←(f,1+⍴g)-0,f
  1483. g←((⍴f),x)⍴(,f∘.>⍳x)\b/g
  1484. b←⍳1↑⍴g←(g[;1]∈¯10↓w)⌿g
  1485. l40:
  1486. b←b[⍋w⍳g[b;x]]
  1487. →(×x←x-1)⍴l40
  1488. g←g[b;]
  1489. f←l∈1↓w
  1490. g←((b>f+.>1⌽f)∧∨/g≠¯1⊖g)⌿g
  1491. g←(' '∨.≠g)/g
  1492.  
  1493. ∇y←cs gradeup m;⎕IO;c;i
  1494. ⍝gradeup vector for character <m> based on collating sequence <cs>
  1495. ⍝.e 4 3 2 1 = '' gradeup 4 5⍴'dog cat bettyapple'
  1496. ⍝.k sorting
  1497. ⍝.t 1992.4.14.22.2.49
  1498. ⍝.v 1.0 / 15sep85
  1499. ⍝.v 1.1 / 27jul89 / rank error check, minor name changes
  1500. ⍝.v 1.2 / 14apr92 / signalerror used
  1501. ⍝sorts vector or matrix <m> column by column
  1502. ⎕IO←1
  1503. y←⍳0
  1504. →(0∈⍴m)/0
  1505. →(∼(⍴⍴m)∈1 2)signalerror '/y/gradeup rank error/right arg not rank 1 or 2'
  1506. cs←((0=×/⍴cs)/⎕AV),(0≠×/⍴cs)/cs
  1507. ⍝a vector is treated as a one-column matrix
  1508. m←(2↑(⍴m),1 1)⍴m
  1509. ⍝assign columns on which to sort (sort on last column first)
  1510. c←⌽⍳¯1↑⍴m
  1511. ⍝this algorithm sorts the indices, not the complete matrix
  1512. y←⍳1↑⍴m
  1513. i←0
  1514. l10:
  1515. →((1↑⍴c)<i←i+1)/0
  1516. y←y[⍋cs⍳m[y;c[i]]]
  1517. →l10
  1518.  
  1519. ∇y←cs gradeup1 m
  1520. ⍝gradeup vector for character <m> based on collating sequence <cs>
  1521. ⍝.e 4 3 2 1 = '' gradeup1 4 5⍴'dog cat bettyapple'
  1522. ⍝.k sorting
  1523. ⍝.t 1989.7.27.22.47.57
  1524. ⍝encode each row as an integer, then grade up
  1525. 'gradeup1' checksubroutine 'base'
  1526. →(∼(⍴⍴m)∈1 2)/err1
  1527. y←m
  1528. →(0∈⍴m)/0
  1529. ⍝the following line allows for scalar <cs>
  1530. cs←((0∈⍴cs)/⎕AV),(∼0∈⍴cs)/cs
  1531. ⍝treat vector <m> as n×1 matrix
  1532. y←⍋cs base(2↑(⍴m),1 1)⍴m
  1533. →0
  1534. err1:
  1535. ⎕←'gradeup1 rank error'
  1536.  
  1537. ∇gf←codes grafd x;ax;c;n;pds;s;y;⎕IO
  1538. ⍝histogram of data <x> specified by <codes>
  1539. ⍝.e 19 24 = ⍴16 4 grafd 20 22 24 19 15 16 14 30 15 19 26 24
  1540. ⍝.k plotting
  1541. ⍝.n eike kaiser
  1542. ⍝.v 1.0 / 12 may 83
  1543. ⍝codes[1] c = number of cells to be used along y axis
  1544. ⍝codes[2] pds = periods per cycle in data
  1545. ⎕IO←1
  1546. n←1
  1547. c←codes[1]
  1548. pds←codes[2]
  1549. l1:
  1550. y←⌈((⌈/x)-⌊/x)÷c
  1551. →(y>1)/l2
  1552. x←x×10
  1553. n←n×10
  1554. →l1
  1555. l2:
  1556. s←(⌊/x)+(-y)+y×⍳c+1
  1557. gf←⊖((c+1),⍴x)⍴(,s∘.≤x)\'⎕'
  1558. s←s÷n
  1559. s←⊖12 2⍕((⍴s),1)⍴s
  1560. ax←(1↓⍴gf)⍴⌽¯1↓'○',pds⍴'-'
  1561. gf←ax,[1]gf,[1]ax
  1562. s←'∘',[1](((1↑⍴s),-+/∨/[1]s≠' ')↑s),[1]'∘'
  1563. gf←(s,' '),gf,' ',s
  1564.  
  1565. ∇y←n hfd d;⎕IO
  1566. ⍝return hex equivalent of integers <d> to <n> hex positions
  1567. ⍝.e (1 3⍴'011') = 3 hfd 17
  1568. ⍝.k translation
  1569. ⍝.t 1988.4.12.19.49.28
  1570. ⎕IO←0
  1571. →((⍴⍴d)>1)/err1
  1572. d←,d
  1573. y←⍉'0123456789abcdef'[(n⍴16)⊤d]
  1574. →0
  1575. err1:⎕←'hfd rank error'
  1576.  
  1577. ∇y←hist x
  1578. ⍝simple histogram of data vector <x>
  1579. ⍝.e 10 10 = ⍴hist ⍳10
  1580. ⍝.k plotting
  1581. y←'⎕ '[1+(⌽⍳⌈/x)∘.≥x]
  1582.  
  1583. ∇r←jc x
  1584. ⍝justify centre: centre all rows of left-justified character array <x>
  1585. ⍝.e (2 6⍴' ab cd ') = jc 2 6⍴'ab cd '
  1586. ⍝.k formatting
  1587. r←(-⌊0.5×+/∧\' '=⌽x)⌽x
  1588.  
  1589. ∇r←jl x
  1590. ⍝justify left: justify character array <x>
  1591. ⍝.e (2 6⍴'ab cd ') = jl 2 6⍴'ab cd '
  1592. ⍝.k formatting
  1593. r←(+/∧\' '=x)⌽x
  1594.  
  1595. ∇r←jr x
  1596. ⍝justify right: justify character array <x>
  1597. ⍝.e (2 6⍴' ab cd') = jr 2 6⍴'ab cd '
  1598. ⍝.k formatting
  1599. r←(-+/∧\⌽' '=x)⌽x
  1600.  
  1601. ∇z←julian date;c;d;jf;m;s;y
  1602. ⍝compute Julian day number for dates <date> = (mm dd yyyy style)
  1603. ⍝.e 2443281 2447295 = julian 2 3⍴5 17 1977 5 13 1988
  1604. ⍝.k date
  1605. ⍝.t 1992.4.6.2.35.28
  1606. ⍝.v 1.0 / 17may77
  1607. ⍝<date> = n×3 matrix (or n×4 matrix where date[;⎕IO+3] is optional style)
  1608. ⍝ = 3-(or 4) element vector (treated as 1-row matrix)
  1609. date←(¯2↑1,⍴date)⍴date
  1610. m←date[;⎕IO]
  1611. d←date[;1+⎕IO]
  1612. y←date[;2+⎕IO]
  1613. z←100⊥y,[⎕IO]m,[⎕IO-0.5]d
  1614. s←(z>19230114)∨(z>15821025)∧(date,z>17520902)[;3+⎕IO]
  1615. jf←2≥m
  1616. c←(2×∼s)+0.75×s×⌊0.00999999999999999674×y-jf
  1617. z←31+d+(⌊367×jf+(m-2)÷12)-⌈c-⌊365.25×4712+y-jf
  1618.  
  1619. ∇loop x;i;m;n
  1620. ⍝perform computations for each element (or row) of <x>
  1621. ⍝.k programming-tools
  1622. ⍝.t 1992.3.18.11.57.1
  1623. ⍝reshape vector to matrix
  1624. m←(2↑(⍴x),1 1)⍴x
  1625. ⍝if needed, line to reshape character namelist to matrix is below
  1626. ⍝ m←'' ∆box ∆db,' ',x
  1627. n←1↑⍴m
  1628. i←0
  1629. l1:
  1630. →(n<i←i+1)/lend
  1631. ⍝ --- insert computations using m[i;] here
  1632. →l1
  1633. lend:
  1634.  
  1635. ∇y←pw matacross m;cols;mat;rows
  1636. ⍝format matrix <m> in columns across a page of width <pw>
  1637. ⍝.e ' apple betty' = (15 matacross '/' ∆box 'apple/betty/cat/dog')[⎕IO;]
  1638. ⍝.k formatting
  1639. ⍝.t 1989.7.24.22.5.52
  1640. ⍝.v 1.0 / 26jan84
  1641. ⍝.v 2.0 / 05may88 / added left argument
  1642. pw←pw,(×/⍴pw)↓⎕PW
  1643. mat←' ',⍕m
  1644. rows←⌈(1↑⍴mat)÷cols←⌊pw÷¯1↑⍴mat
  1645. y←(rows,colsׯ1↑⍴mat)⍴((rows×cols),¯1↑⍴mat)↑mat
  1646.  
  1647. ∇y←a matdown m;⎕IO;cols;mat;rows;w
  1648. ⍝format matrix <m> in columns down a page according to <a>
  1649. ⍝.e 'apple cat '=12⍴15 2 matdown '/' ∆box 'apple/betty/cat/dog'
  1650. ⍝.k formatting
  1651. ⍝.t 1988.4.24.22.9.20
  1652. ⍝.v 1.2 / 5nov83
  1653. ⍝ a[1]=width of page(:⎕PW), [2]=spaces between columns(:1)
  1654. ⎕IO←1
  1655. ⍝get defaults for a
  1656. a←a,(×/⍴a)↓⎕PW,1
  1657. ⍝compute as though there are a[2] extra spaces on right
  1658. w←+/a
  1659. mat←(⍕m),((1↑⍴m),a[2])⍴' '
  1660. ⍝do 1⌈ to prevent cols=0 if w is specified too small
  1661. rows←⌈(1↑⍴mat)÷cols←1⌈⌊w÷¯1↑⍴mat
  1662. mat←2 1 3⍉(cols,rows,¯1↑⍴mat)⍴((rows×cols),¯1↑⍴mat)↑mat
  1663. mat←((1↑⍴mat),×/1↓⍴mat)⍴mat
  1664. ⍝now drop trailing blank columns on right
  1665. y←(0,-a[2])↓mat
  1666.  
  1667. ∇y←matrix x
  1668. ⍝reshape any array <x> (rank 0 - n) to a matrix
  1669. ⍝.e 6 2 = ⍴matrix 3 2 2 ⍴'a'
  1670. ⍝.k reshape
  1671. ⍝.t 1992.3.18.11.11.30
  1672. ⍝.v 1.0 / 20sep85 / first version
  1673. ⍝.v 1.1 / 18mar92 / simplified computation of first dimension of result
  1674. ⍝compute a=product of all dimensions except last (=1 if x is scalar or vector)
  1675. ⍝compute b=last dimension (=1 if x is scalar)
  1676. ⍝shape of result is (a,b)
  1677. y←((×/¯1↓⍴x),¯1↑1,⍴x)⍴x
  1678.  
  1679. ∇r←mdyoford x;⎕IO;d;day;leap;m;md;month;n;year
  1680. ⍝compute the (mm dd yyyy) format for ordinal dates <x>
  1681. ⍝.e 5 12 1988 = ,mdyoford 88133
  1682. ⍝.k date
  1683. ⍝.t 1988.5.11.23.58.2
  1684. ⍝.v 1.1 / 11may88 / corrected and enhanced version of <jul2ymd>
  1685. ⎕IO←1
  1686. md←0 31 59 90 120 151 181 212 243 273 304 334
  1687. n←⍴x←,x
  1688. d←1000 1000⊤x
  1689. year←1900+d[1;]
  1690. ⍝compute leap year flag for each x[i]
  1691. leap←(0=400|year)∨(0=4|year)∧(0≠100|year)
  1692. ⍝add 1 to months after february if leap year
  1693. m←md[1],md[2],leap∘.+md[2↓⍳12]
  1694. ⍝month of each x[i]
  1695. month←+/(⍉(12,n)⍴d[2;])>m
  1696. ⍝ ----- month day of each element in d[2;]
  1697. ⍝md[month] is number of days in year up to beginning of month <month>.
  1698. ⍝adjust <day> (days in this month) if d[2;] (ordinal date) is in march
  1699. ⍝or greater in a leap year.
  1700. day←d[2;]-md[month]+leap×month≥3
  1701. ⍝return year,month,day as n÷3 matrix
  1702. r←⍉(3,n)⍴month,day,year
  1703.  
  1704. ∇r←moonphase d
  1705. ⍝compute phase of moon <r> for dates <d> = (mm dd yyyy style)
  1706. ⍝.e 1 ∆ moonphase 1989 7 27
  1707. ⍝.k date
  1708. ⍝.t 1992.4.6.1.14.56
  1709. ⍝.v 1.0 / 15apr78
  1710. ⍝<d> is vector (1 date), or matrix of dates (passed to <julian>)
  1711. ⍝<r> 0 is new moon, .5 is full moon, .75 is last quarter, etc.
  1712. 'moonphase' checksubroutine 'julian'
  1713. r←1|÷29.530589999999993÷¯9+julian d
  1714.  
  1715. ∇Nly←Nls nl Nlc;⎕IO
  1716. ⍝namelist of functions or variables <Nlc> within specification <Nls>
  1717. ⍝.e 'nl' ∆rowmem 'm-p' nl 3
  1718. ⍝.k programming-tools
  1719. ⍝.t 1992.3.8.11.18.0
  1720. ⍝.v 1.0 / 27jul89
  1721. ⍝.v 1.1 / 02mar92 / localized ⎕IO, definition of right arg changed
  1722. ⍝.v 1.2 / 06mar92 / replace matdown with matacross for formatting output
  1723. ⍝.v 1.3 / 08mar92 / specify gradeup collating sequence to put blank first
  1724. ⎕IO←1
  1725. 'nl' checksubroutine 'gradeup matacross pick range vnames wildcard'
  1726. →(0∈vnames Nls)signalerror '/Nly/nl domain error/left arg contains invalid name specification.'
  1727. Nly←⎕NL|Nlc
  1728. ⍝sort after picking from objects
  1729. Nly←(Nly pick Nls)⌿Nly
  1730. Nly←∆db Nly[(' ',⎕AV)gradeup Nly;]
  1731. ⍝reformat if at least one of Nlc is negative
  1732. →(∼¯1∈×Nlc)/0
  1733. Nly←'' matacross Nly
  1734.  
  1735. ∇y←a on b;col;⎕IO
  1736. ⍝catenate array <a> to array <b> (maximum rank 2) on first coordinate
  1737. ⍝.e (3 4⍴'aaaabb bb ') = 'aaaa' on 2 2⍴'b'
  1738. ⍝.k catenation
  1739. ⍝.t 1989.7.23.21.59.7
  1740. ⍝note: (0 1⍴''),[1]2 1⍴'a' same as (0 1⍴'') on 2 1⍴'a'
  1741. ⍝note: '',[1]1 0⍴'a' same as '' on 1 0⍴'a'
  1742. ⎕IO←1
  1743. a←(¯2↑1 1,⍴a)⍴a
  1744. b←(¯2↑1 1,⍴b)⍴b
  1745. col←⌈/0 1 0 1/(⍴a),⍴b
  1746. y←(((1↑⍴a),col)↑a),[1]((1↑⍴b),col)↑b
  1747.  
  1748. ∇y←ordofmdy d;⎕IO;day;leap;md;month;year
  1749. ⍝compute the ordinal format for dates <d> = (mm dd yyyy)
  1750. ⍝.e 92061 = ordofmdy 3 1 1992
  1751. ⍝.k date
  1752. ⍝.t 1992.4.14.16.1.27
  1753. ⍝.v 1.0
  1754. ⍝.v 1.1 / 14apr92 / using signalerror, simplified function
  1755. ⍝<d> can be a 3-element vector, or a matrix of dates
  1756. ⍝ordinal date format is (yyddd). e.g. 85036 means 36th day of 1985
  1757. ⎕IO←1
  1758. d←(¯2↑1 1,⍴d)⍴d
  1759. →(3≠¯1↑⍴d)signalerror '/y/ordofmdy length error/last coordinate of right arg not 3'
  1760. ⍝md[i]+1 is first ordinal day of month[i]
  1761. md←0 31 59 90 120 151 181 212 243 273 304 334
  1762. month←d[;1]
  1763. day←d[;2]
  1764. year←d[;3]
  1765. ⍝To compute leap year:
  1766. ⍝ non-century years -- must be evenly divisible by 4
  1767. ⍝ century years -- must be evenly divisible by 400
  1768. ⍝in other words -- every 4 years, except only every 4 century years
  1769. leap←(0=400|year)∨(0=4|year)∧(0≠100|year)
  1770. ⍝add 1 if month[i] is in march or later and year is a leap year
  1771. y←1000⊥(100|year),[0.5]day+md[month]+leap×month≥3
  1772.  
  1773. ∇out x;i;sink
  1774. ⍝put text <x> to output device
  1775. ⍝.k output
  1776. ⍝.t 1992.4.25.21.9.3
  1777. →g∆outf/skip
  1778. g∆outh←g∆outf←1
  1779. outheader
  1780. skip:
  1781. →g∆outh/skip01
  1782. g∆outh←1
  1783. outheader
  1784. skip01:
  1785. x←(¯2↑1 1,⍴x)⍴x
  1786. i←0
  1787. l0:→((1↑⍴x)<i←i+1)/0
  1788. →(g∆outline<g∆outlimit)/ok
  1789. ⍝too many lines. go to new page and print header
  1790. outpage
  1791. g∆outh←1
  1792. outheader
  1793. ok:
  1794. g∆outline←g∆outline+1
  1795. →(g∆outdevice='afptz')/a,f,p,t,z
  1796. a:
  1797. g∆outbuffer←g∆outbuffer on x[i;]
  1798. →l0
  1799. f:
  1800. g∆outbuffer←g∆outbuffer on x[i;]
  1801. →l0
  1802. p:
  1803. ⍝⎕←g∆outpagechar,(132⌊⍴x[i;])↑x[i;]
  1804. g∆outpagechar←' '
  1805. →l0
  1806. t:
  1807. ⎕←⎕PW↑x[i;]
  1808. →l0
  1809. z:
  1810. ∆out x[i;]
  1811. →l0
  1812.  
  1813. ∇outclose;sink
  1814. ⍝close output device
  1815. ⍝.k output
  1816. ⍝.t 1989.7.30.15.44.8
  1817. →(g∆outdevice='afptz')/a,f,p,t,z
  1818. a:
  1819. ⍝pad with blank lines if last page is partially full
  1820. →(g∆outline=0)/a10
  1821. g∆outbuffer←g∆outbuffer,[1]((g∆outlimit-g∆outline),¯1↑⍴g∆outbuffer)⍴' '
  1822. a10:
  1823. ⍝reshape buffer to rank-3 array (each plane is a page)
  1824. g∆outbuffer←(((1↑⍴g∆outbuffer)÷g∆outlimit),g∆outlimit,¯1↑⍴g∆outbuffer)⍴g∆outbuffer
  1825. ⍝define array. important not to choose a name that is shadowed
  1826. ⍎g∆outname,'←g∆outbuffer'
  1827. →lend
  1828. f:
  1829. ⍝define component for text on last page (if any)
  1830. →(g∆outline=0)/lend
  1831. ⍎g∆outname,(⍕g∆outpageno),'←g∆outbuffer'
  1832. →lend
  1833. p:
  1834. ⍝close printer as required (insert code here)
  1835. →lend
  1836. t:
  1837. ⍝print ready text unless last page is empty
  1838. →(g∆outline=0)/lend
  1839. ⍞←g∆outreadytext
  1840. sink←⍞
  1841. →lend
  1842. z:
  1843. ⍝close as already defined for this device
  1844. ∆outreset
  1845. →lend
  1846. lend:
  1847. sink←⎕EX 'g∆outbuffer'
  1848. ⍝if desired ⎕EX various other 'g∆out' variables here
  1849.  
  1850. ∇outheader
  1851. ⍝print header
  1852. ⍝.k output
  1853. ⍎g∆outheader
  1854.  
  1855. ∇header outopen x;parms
  1856. ⍝open output device specified by <x>. use heading function <header>
  1857. ⍝.k output
  1858. ⍝.t 1992.4.25.21.8.51
  1859. ⍝note: if heading feature not used, define <header> as ''
  1860. ⍝<x> has format: device,parameter1,parameter2
  1861. ⍝ the meaning depends on the device
  1862. g∆outheader←header
  1863. parms←',' ∆box x
  1864. g∆outdevice←∆db parms[1;]
  1865. g∆outline←0
  1866. g∆outpageno←1
  1867. g∆outlimit←⌊/⍳0
  1868. g∆outbuffer←0 0⍴''
  1869. →((g∆outdevice='afptz'),1)/a,f,p,t,z,err1
  1870. a: ⍝array. <x>='a',name,limit
  1871. g∆outname←∆db parms[2;]
  1872. g∆outlimit←⍎parms[3;]
  1873. g∆outbuffer←0 0⍴''
  1874. →lend
  1875. f: ⍝file. <x>='f',limit
  1876. g∆outlimit←⍎parms[2;]
  1877. ⍝initialize buffer
  1878. g∆outbuffer←0 0⍴''
  1879. ⍝define base name of matrix used to define components
  1880. g∆outname←'component'
  1881. →lend
  1882. p: ⍝printer (skeleton). <x>='p',limit
  1883. g∆outlimit←⍎parms[2;]
  1884. ⍝page format character. 1=go to top of page before printing text
  1885. g∆outpagechar←'1'
  1886. →lend
  1887. t: ⍝terminal. <x>='t',limit
  1888. g∆outlimit←⍎parms[2;]
  1889. g∆outreadytext←'press <enter> key to continue.'
  1890. →lend
  1891. z: ⍝z-device. <x>='z',limit
  1892. g∆outlimit←⍎parms[2;]
  1893. ∆outset
  1894. →lend
  1895. lend:
  1896. g∆outh←g∆outf←0
  1897. →0
  1898. err1:
  1899. ⎕←'out domain error'
  1900. ⎕←'unknown device code (',g∆outdevice,')'
  1901.  
  1902. ∇outpage;sink
  1903. ⍝advance device to new page
  1904. ⍝.k output
  1905. g∆outh←0
  1906. ⍝no page advance if already at top
  1907. →(g∆outline=0)/0
  1908. →(g∆outdevice='afptz')/a,f,p,t,z
  1909. a:
  1910. ⍝pad buffer with empty lines to end of 'page'
  1911. g∆outbuffer←g∆outbuffer,[1]((g∆outlimit-g∆outline),¯1↑⍴g∆outbuffer)⍴' '
  1912. →lend
  1913. f:
  1914. ⍝define this component (as a variable)
  1915. ⍎g∆outname,(⍕g∆outpageno),'←g∆outbuffer'
  1916. g∆outbuffer←0 0⍴''
  1917. →lend
  1918. p:
  1919. ⍝in ibm environment simply reset page format character
  1920. g∆outpagechar←'1'
  1921. →lend
  1922. t:
  1923. ⍞←g∆outreadytext
  1924. sink←⍞
  1925. →lend
  1926. z:
  1927. ∆outpage
  1928. →lend
  1929. lend:
  1930. g∆outline←0
  1931. ⍝advance page counter to 'this page'
  1932. g∆outpageno←g∆outpageno+1
  1933.  
  1934. ∇z←m patterng c;⎕IO
  1935. ⍝random rearrangement of text <c> based on <m>
  1936. ⍝.e 4 9 = ⍴ 2 3 2 3 patterng ' sun ⋆ moon '
  1937. ⍝.k graphics
  1938. ⍝.n roger frey
  1939. ⍝.t 1989.7.27.23.42.49
  1940. ⍝.v 1.0 / aug68
  1941. ⎕IO←1
  1942. z←((2↑m)×2↓m)⍴2 4 1 3⍉((m[3 4],⍴c)⍴c)[;;?m[1 2]⍴⍴c]
  1943.  
  1944. ∇y←payday d
  1945. ⍝<y> is the closest Friday on or before dates <d> = (mm dd yyyy)
  1946. ⍝.e 7 21 1989 = ,payday 7 27 1989
  1947. ⍝.k date
  1948. ⍝.t 1992.4.9.17.27.59
  1949. ⍝.v 1.0 / 15apr78
  1950. ⍝.v 1.1 / 09apr92 / left arg extended to matrix; use <days> not <julian>
  1951. ⍝<d> can be vector (1 date), or matrix of dates, in format (mm dd yyyy)
  1952. 'payday' checksubroutine 'days cdays'
  1953. ⍝for each date compute day counts starting from <d> and going back a week
  1954. y←(days d)∘.-¯1+⍳7
  1955. ⍝pick out the day count for friday (day 5) in each row and convert to dates
  1956. y←cdays(,5=7|y)/,y
  1957.  
  1958. ∇y←m pick v;⎕IO;b;i;mv;r;tc;tf;token
  1959. ⍝select (pick) rows from character <m> using name specification <v>
  1960. ⍝.e 1 1 0 0 1 = ('/' ∆box 'apple/betty/cat/dog/zebra') pick 'a-b z⋆'
  1961. ⍝.k searching
  1962. ⍝.n rml
  1963. ⍝.t 1988.5.12.21.11.46
  1964. ⍝.v 1.8 / 23jan84
  1965. ⍝.v 2.0 / 26nov85
  1966. ⍝.v 2.1 / 06may88 (rewritten, use enhanced name specifications)
  1967. ⍝.v 2.2 / 23apr92 / using signalerror
  1968. ⍝<m> character matrix of names
  1969. ⍝<v> character vector containing name specifications
  1970. ⎕IO←1
  1971. 'pick' checksubroutine 'vnames wildcard range'
  1972. →(∼(⍴⍴v)∈0 1)signalerror '/y/pick rank error/right arg not rank 0 or 1'
  1973. ⍝mv is needed in one of the early error messages
  1974. mv←'' ∆box v←∆db v
  1975. →(2≠⍴⍴m)signalerror '/y/pick rank error/left arg not rank 2'
  1976. y←(1↑⍴m)⍴0
  1977. →((0∈⍴m),0∈⍴v)/0
  1978. ⍝compute class of each name specification in <mv>
  1979. tc←vnames v
  1980. →(0∈tc)signalerror '/y/pick domain error/right arg has invalid items (',(∆db,' ',(tc=0)⌿mv),')'
  1981. ⍝translate a token class into its positive equivalent
  1982. r←(1 12 21 121 212 2 13 31 131 3,tc)[(41 412 421 4121 4212 42 413 431 4131 43,tc)⍳tc]
  1983. ⍝for each token in <mv> remove trailing blanks, compute tilde
  1984. ⍝flag, remove tilde, get corresponding compression vector.
  1985. i←0
  1986. l20:→((1↑⍴mv)<i←i+1)/0
  1987. tf←'∼'=1↑token←∆db mv[i;]
  1988. token←tf↓token
  1989. →(r[i]=1 12 21 121 212 2 13 31 131 3)/(6⍴l30a),(4⍴l30b)
  1990. l30a:b←m wildcard token
  1991. →l30
  1992. l30b:b←m range token
  1993. →l30
  1994. l30:
  1995. ⍝treat <b> differently depending on <tf> (tilde flag)
  1996. →(1 0=tf)/l50a,l50b
  1997. ⍝tilde specification. turn off a subset of the items already picked.
  1998. ⍝but if first one, start with universe.
  1999. l50a:y←(y∨i=1)×∼b
  2000. →l20
  2001. ⍝no tilde. add to subset of items already picked.
  2002. l50b:y←y∨b
  2003. →l20
  2004.  
  2005. ∇y←v pickn n;⎕IO;b;i;mv;r;t;x
  2006. ⍝pick ('select') numbers from <n> using positive integer specification <v>
  2007. ⍝.e 1 1 1 1 0 0 0 0 1 1 = '1-4 9-' pickn ⍳10
  2008. ⍝.k searching
  2009. ⍝.t 1992.4.25.17.18.49
  2010. ⍝.v 1.0 / 23nov83 / uses vfpi
  2011. ⍝.v 1.1 / 13nov85 / uses vpis
  2012. ⍝.v 1.2 / 25apr92 / uses signalerror
  2013. ⍝<n> is vector of numbers
  2014. ⍝<v> is positive integer specification as defined by <vpis>
  2015. ⍝<y> is compression vector for <n>
  2016. ⎕IO←1
  2017. 'pickn' checksubroutine 'vpis'
  2018. →(∼(⍴⍴n)∈0 1)signalerror '/y/pickn rank error/right arg not rank 0 or 1'
  2019. n←,n
  2020. mv←'' ∆box v←∆db,' ',v
  2021. y←(⍴n)⍴0
  2022. →((0∈⍴n),0∈⍴v)/0
  2023. ⍝find token class <r> of each specification
  2024. r←vpis v
  2025. t←∆db,' ',(∼r[;1])⌿mv
  2026. →(0∈r[;1])signalerror '/y/pickn domain error/left arg contains invalid items (',t,')'
  2027. ⍝for each token, get the compression vector
  2028. i←0
  2029. l20:
  2030. →((⍴r)<i←i+1)/0
  2031. →(r[i;2]=1 12 21 2 121)/exact,prefix,suffix,all,range
  2032. exact: ⍝number
  2033. b←n=⍎mv[i;]
  2034. →endloop
  2035. prefix: ⍝n-
  2036. b←n≥⍎(mv[i;]≠'-')/mv[i;]
  2037. →endloop
  2038. suffix: ⍝-n
  2039. b←n≤⍎(mv[i;]≠'-')/mv[i;]
  2040. →endloop
  2041. all: ⍝ - all the matrix
  2042. b←(⍴n)⍴1
  2043. →endloop
  2044. range: ⍝n-m
  2045. x←⍎b\(b←mv[i;]≠'-')/mv[i;]
  2046. b←(x[1]≤n)∧n≤x[2]
  2047. →endloop
  2048. endloop:
  2049. y←y∨b
  2050. →l20
  2051.  
  2052. ∇z←a pnrot n;i;j
  2053. ⍝permutation vector <a> for partitioned <n>-rotate on partitions <a>
  2054. ⍝.e 2 1 5 3 4 8 9 6 7 ∧.= 1 0 1 0 0 1 0 0 0 pnrot 1 ¯1 2
  2055. ⍝.k uncategorized
  2056. ⍝.t 1988.4.13.1.38.6
  2057. ⍝returns the permutation vector to perform a partitioned <n>-rotate
  2058. ⍝on a vector whose partitions are designated by <a>
  2059. ⍝<n> must satisfy (⍴,n)∈1,+/a and will be scalar-extended if necessary
  2060. i←(1⌽a)/⍳⍴a
  2061. j←+\a
  2062. i←i-¯1↓0,i
  2063. z←⍋j+(i|n)[j]≥+\1-a\¯1↓0,i
  2064.  
  2065. ∇print text
  2066. ⍝example print cover function to print <text> on printer
  2067. ⍝.k output
  2068. '' outopen 'z,34'
  2069. out text
  2070. outclose
  2071.  
  2072. ∇y←prompt msg
  2073. ⍝simple prompt with <msg> and request input on same line
  2074. ⍝.k input
  2075. ⍞←msg,' '
  2076. y←,⍞
  2077. y←(¯1+(y≠' ')⍳1)↓y
  2078.  
  2079. ∇Y←Text puttag Fns;⎕IO;Alpha;Code;Fn;I;J;Line;Mat;T
  2080. ⍝put tag line <text> on functions <fns>
  2081. ⍝.k library-utility
  2082. ⍝.t 1989.7.24.18.17.10
  2083. ⍝.v 1.2 / 31oct83
  2084. ⍝<text> has the form: c xxxxx where c is a tag character
  2085. ⎕IO←1
  2086. Y←⍳0
  2087. ⍎(2≠⍴⍴Fns)/'Fns←'' '' ∆box ∆db Fns'
  2088. ⍝remove leading '.' if necessary
  2089. Text←(∼∧\Text='.')/Text
  2090. Code←1↑Text
  2091. ⍝ensure for new tag line that space follows code
  2092. Line←'⍝.',(2↑Code),2↓Text
  2093. J←0
  2094. L10:→((J←J+1)>1↑⍴Fns)/End
  2095. Mat←⎕CR Fn←Fns[J;]
  2096. ⍝----- make sure Mat has at least two lines with first line comment
  2097. →((0 1=1↑⍴Mat)/L15,L20),L0
  2098. ⍝no line. cannot get cr.
  2099. L15:⎕←'puttag error. cannot get canonical matrix for ',Fn
  2100. →Blend
  2101. L20: ⍝one line. add a line for first line comment
  2102. Mat←Mat,[1](¯1↑⍴Mat)↑'⍝'
  2103. →L2
  2104. L0: ⍝this Mat has at least two lines. check for first line comment
  2105. →('⍝'=Mat[2;1])/L2
  2106. ⍝add line for first line comment
  2107. Mat←Mat[1;],[1]((¯1↑⍴Mat)↑'⍝'),[1]1 0↓Mat
  2108. L2: ⍝now Mat has at least 2 lines with first line comment
  2109. ⍝skip next part if Text is empty
  2110. →(0=⍴Text)/L3
  2111. ⍝----- put in new tag line
  2112. ⍝pad mat with trailing blanks (if necessary) to accommodate Line
  2113. Mat←((1↑⍴Mat),((¯1↑⍴Mat)⌈⍴Line))↑Mat
  2114. ⍝now search for tag line
  2115. I←(Mat[;⍳4]∧.='⍝.',2↑Code)/⍳1↑⍴Mat
  2116. →(0=⍴I)/L1
  2117. ⍝found it. so replace (first occurrence of) it.
  2118. Mat[1↑I;]←(¯1↑⍴Mat)↑Line
  2119. →L3
  2120. L1: ⍝did not find it. so insert new Line after line 1
  2121. Mat←Mat[⍳2;],[1]((¯1↑⍴Mat)↑Line),[1]2 0↓Mat
  2122. L3:
  2123. ⍝----- now reorder lines with ⍝.x<blank> (where x is alphabetic)
  2124. I←(Mat[;1 2 4]∧.='⍝. ')/⍳1↑⍴Mat
  2125. Alpha←'abcdefghijklmnopqrstuvwxyz∆ABCDEFGHIJKLMNOPQRSTUVWXYZ⍙'
  2126. I←(Mat[I;3]∈Alpha)/I
  2127. Mat[I;]←Mat[I[⍋Alpha⍳Mat[I;3]];]
  2128. →(0≠1↑0⍴T←⎕FX Mat)/Lend
  2129. ⎕←'puttag error'
  2130. ⎕←'error when fixing function = ',Fn,' line = ',(⍕T),' ',Mat[T;]
  2131. →Blend
  2132. Lend:
  2133. Y←Y,1
  2134. →L10
  2135. Blend:
  2136. Y←Y,0
  2137. →L10
  2138. End:
  2139.  
  2140. ∇Y←L qstop N
  2141. ⍝set stop vector for functions <N> on lines <L>, but not comments
  2142. ⍝.k programming-tools
  2143. ⍝.t 1988.4.8.3.47.42
  2144. ⍝example: (⍳10) qstop 'func' ⍝stop function 'func' at lines 1 tthrough 10
  2145. 'qstop' checksubroutine 'stoptrace'
  2146. →((∼0∈⍴L)∧0≠1↑0⍴L)/Err1
  2147. Y←L stoptrace 's',,' ',⍕N
  2148. →0
  2149. Err1:⎕←'stop domain error'
  2150.  
  2151. ∇Y←L qtrace N
  2152. ⍝set trace for functions <N> on lines <L>, optionally avoid comments
  2153. ⍝.k programming-tools
  2154. ⍝.t 1988.4.8.3.47.42
  2155. ⍝example: (⍳10) qtrace 'func' ⍝trace function 'func' at lines 1 tthrough 10
  2156. 'qtrace' checksubroutine 'stoptrace'
  2157. →((∼0∈⍴L)∧0≠1↑0⍴L)/Err1
  2158. Y←L stoptrace 't',,' ',⍕N
  2159. →0
  2160. Err1:⎕←'trace domain error'
  2161.  
  2162. ∇y←m range s;⎕CT;⎕IO;cs;lh;n;nn;x
  2163. ⍝select names in matrix <m> using 'range' search specification <s>
  2164. ⍝.e 1 1 1 0 0 = (5 5⍴'appleanniebettycat dog ') pick 'a-b'
  2165. ⍝.k searching
  2166. ⍝.t 1989.7.27.22.20.17
  2167. ⍝.v 1.0 / 06may88
  2168. ⍝assume <s> belongs to set of valid specifications (a-z, a-, -z, -)
  2169. ⍝<s> can contain ? search character
  2170. ⎕IO←1
  2171. ⎕CT←0
  2172. ⍝assume collating sequence <cs> includes all characters in nn and m.
  2173. ⍝blank will also appear as a pad character and we set it so it
  2174. ⍝is first in collating sequence.
  2175. cs←' abcdefghijklmnopqrstuvwxyz∆ABCDEFGHIJKLMNOPQRSTUVWXYZ⍙0123456789⎕'
  2176. ⍝the lowest and highest characters in collating sequence
  2177. lh←cs[1,⍴cs]
  2178. ⍝<nn[1;]> = first part of range specification, <nn[2;]> = second part
  2179. ⍝e.g. if <s> is 'ax-d', nn[1;]='ax' and nn[2;]='d '
  2180. ⍝<s,'-'> ensures that nn has 2 rows if <s>='a-'
  2181. nn←'-' ∆box s,'-'
  2182. ⍝ensure that m has as many columns as nn
  2183. m←((1↑⍴m),(¯1↑⍴nn)⌈¯1↑⍴m)↑m
  2184. ⍝replace blank in low limit with lh[1].
  2185. ⍝replace blank in high limit with lh[2].
  2186. ⍝this also assigns defaults to empty limits.
  2187. ⍝'?' in range specification (e.g. a?-b, ?-, etc.) is allowed but
  2188. ⍝essentially irrelevant. it is replaced by low or high character in
  2189. ⍝collating sequence, depending on if it appears in the first or second
  2190. ⍝part of the range specification, respectively.
  2191. nn[1;]←(lh[1 1],nn[1;])[(' ?',nn[1;])⍳nn[1;]]
  2192. nn[2;]←(lh[2 2],nn[2;])[(' ?',nn[2;])⍳nn[2;]]
  2193. ⍝compute numeric values up to precision of specified phrases
  2194. x←(⍴cs)⊥⍉cs⍳nn
  2195. n←(⍴cs)⊥⍉cs⍳m[;⍳¯1↑⍴nn]
  2196. y←(x[1]≤n)∧n≤x[2]
  2197.  
  2198. ∇y←a reformat m;⎕IO;i;v
  2199. ⍝reformat <m> to matrix a[1] characters wide, including a[2] initial blanks
  2200. ⍝.e 2 35 = ⍴35 4 reformat 'the quick brown fox jumped over the lazy red hen'
  2201. ⍝.k formatting
  2202. ⍝.t 1988.4.27.22.14.51
  2203. ⎕IO←1
  2204. 'reformat' checksubroutine 'jl ss expandaf split'
  2205. ⍝<a[2]> defaults to 0
  2206. a←2↑a
  2207. ⍝delete redundant blanks after appending blank for words ending on last column
  2208. v←∆db,m,' '
  2209. ⍝<ss> find occurrences in <v> of period or ? followed by blank
  2210. ⍝<expandaf> put extra blank in <v> after these occurrences
  2211. ⍝<split> split text into several lines within specified text width
  2212. ⍝<jl> move any leading blanks in each row to end of row
  2213. y←jl(a[1]-a[2])split(expandaf(⍳⍴v)∈(v ss '. '),v ss '? ')\v
  2214. ⍝preceed text by a[2] blank columns
  2215. y←(((1↑⍴y),a[2])⍴' '),y
  2216.  
  2217. ∇y←a reparray m;⎕IO;c;n;shape;x
  2218. ⍝replicate array <m>. replicate <a[1]> times along coordinate <a[2]>
  2219. ⍝.e ((3 2 2⍴'abcd'),[1] 3 2 2⍴'1234') = 3 1 reparray 2 2 2⍴'abcd1234'
  2220. ⍝.k reshape
  2221. ⍝.n rml
  2222. ⍝.t 1992.4.25.17.1.8
  2223. ⍝.v 1.0 / 10feb84
  2224. ⍝.v 1.1 / 25apr92 / using signalerror
  2225. ⍝note: each 'slice' of the array along the specified coordinate
  2226. ⍝is replicated <a[1]> times.
  2227. ⎕IO←1
  2228. ⍝default to last coordinate
  2229. a←2↑a,⍴⍴m
  2230. →(∼(1≤a[2])∧a[2]≤⍴⍴m)signalerror '/y/reparray domain error/coordinate specification (',(⍕a[2]),') outside range (1,',(⍕⍴⍴m),')'
  2231. n←a[1]
  2232. c←a[2]
  2233. x←(c+1),((c+1)≠⍳1+⍴⍴m)/⍳1+⍴⍴m
  2234. shape←(⍴m)×(c≠⍳⍴⍴m)+(c=⍳⍴⍴m)×n
  2235. y←shape⍴x⍉(n,⍴m)⍴m
  2236.  
  2237. ∇y←a reparray1 m;c;n;⎕IO
  2238. ⍝replicate matrix <m>. replicate <a[1]> times along coordinate <a[2]>
  2239. ⍝.e ((3 2⍴'ab'),[1] 3 2⍴'cd') = 3 1 reparray1 2 2⍴'abcd'
  2240. ⍝.k reshape
  2241. ⍝.n rml
  2242. ⍝.t 1989.7.27.22.10.15
  2243. ⍝.v 1.0 / 10feb84
  2244. ⍝simplified version of reparray restricted to rank 2 arrays
  2245. ⎕IO←1
  2246. ⍝default to last coordinate
  2247. a←2↑a,2
  2248. n←a[1]
  2249. c←a[2]
  2250. ⍝replicate coordinate 1 (rows) or coordinate 2 (columns)
  2251. →(c=1 2)/l1,l2
  2252. l1:
  2253. y←((n×(⍴m)[1]),(⍴m)[2])⍴2 1 3⍉(n,⍴m)⍴m
  2254. →0
  2255. l2:
  2256. y←((⍴m)[1],n×(⍴m)[2])⍴3 1 2⍉(n,⍴m)⍴m
  2257.  
  2258. ∇report parms;n
  2259. ⍝example of using the output functions
  2260. ⍝.k output
  2261. ⍝.t 1992.4.25.20.38.47
  2262. 'reportheader' outopen parms
  2263. out 'first line of sample report - using the output functions'
  2264. ⍝here's one way to make two blank lines
  2265. out 'two blank lines follow ...'
  2266. out 2 1⍴' '
  2267. out 'it is ok to output a matrix'
  2268. out 6 6⍴'matrix'
  2269. ⍝numerics must be in character form
  2270. out 'to output numeric data, put in character form first ...'
  2271. out⍕⍳3
  2272. outpage
  2273. out 'first line of next page'
  2274. out 'the quick brown fox jumped over the lazy black hen'
  2275. out 'now two successive calls to outpage (advances one page only)'
  2276. ⍝two calls to outpage (advances one page only)
  2277. outpage
  2278. outpage
  2279. out 'this should be top of next page (after quick brown fox)'
  2280. out 'print ',(⍕n←16),' lines ...'
  2281. out((n,5)⍴'line '),⍕(n,1)⍴⍳n
  2282. outclose
  2283.  
  2284. ∇reportheader
  2285. ⍝example of report header function (used in <report>)
  2286. ⍝.k output
  2287. ⍝.t 1992.4.25.20.39.35
  2288. out jc 78↑'sample report page ',⍕g∆outpageno
  2289. out 78⍴'-'
  2290.  
  2291. ∇r←x riota y;⎕IO
  2292. ⍝in matrix <x> where is each row of matrix <y>?
  2293. ⍝.e 2=('/' ∆box 'apple/betty/cat') riota 'betty'
  2294. ⍝.k searching
  2295. ⍝.n dave macklin
  2296. ⍝.t 1992.4.16.22.20.19
  2297. ⍝.v 1.0 / 00apr78
  2298. ⎕IO←1
  2299. y←(¯2↑1 1,⍴y)⍴y
  2300. x←(¯2↑1 1,⍴x)⍴x
  2301. r←1++/∼∨\(((0 1×⍴x)⌈⍴y)↑y)∧.=⍉((0 1×⍴y)⌈⍴x)↑x
  2302.  
  2303. ∇r←n rnd x
  2304. ⍝round numbers <x> to <n> decimal places
  2305. ⍝.e 45.35 10.13 2.14 = 2 rnd 45.345 10.134 2.136
  2306. ⍝.k computation
  2307. ⍝.t 1989.7.23.22.16.56
  2308. r←(10⋆-n)×⌊0.5+x×10⋆n
  2309.  
  2310. ∇r←rnde x;t
  2311. ⍝round <x> to nearest integer (.5 case goes to nearest even integer)
  2312. ⍝.e 12 12 14 14 = rnde 11.5 12.5 13.5 14.5
  2313. ⍝.k computation
  2314. ⍝.t 1989.7.23.22.18.18
  2315. t←¯1⋆⌈2|x
  2316. r←t×⌊0.5+x×t
  2317.  
  2318. ∇y←roman x;a;⎕IO
  2319. ⍝character roman numeral equivalent of arabic (base 10) number <x>
  2320. ⍝.e 'xiv' = roman 14
  2321. ⍝.k translation
  2322. ⍝.t 1988.4.13.1.6.8
  2323. ⎕IO←1
  2324. x←,x
  2325. a←,(10 4⍴3 3 3 3 1 3 3 3 1 1 3 3 1 1 1 3 1 0 3 3 0 3 3 3 0 1 3 3 0 1 1 3 0 1 1 1 1 ¯1 3 3)[1+(4⍴10)⊤x;]
  2326. y←'mdclxvi'[(a≠3)/a+2×⌊0.25ׯ1+⍳16]
  2327.  
  2328. ∇mat←y scatter x;pos;shape;⎕IO
  2329. ⍝simple scatter plot of vectors <y> (y-axis) against <x> (x-axis)
  2330. ⍝.e 11 21 = ⍴((⍳10),⌽⍳10) scatter(⍳20)
  2331. ⍝.k plotting
  2332. ⎕IO←1
  2333. mat←,(shape←(⌈/y),⌈/x)⍴' '
  2334. pos←1+shape⊥¯1+y,[0.5]x
  2335. mat[pos]←'⋆'
  2336. mat←⊖'+','+',[1]shape⍴mat
  2337.  
  2338. ∇Y←script Text;⎕IO;BB;C;Codes;I;J;KK;L;Scriptbuffer;Sink;Tokens;X
  2339. ⍝compute document <Y> using script in character matrix <Text>
  2340. ⍝.e (¯9↑'⎕←x') = 9⍴script '/' ∆box '.t ⎕←x←2 2⍴⍳4/abcdefg/.r 3 3⍴⍳4/.x x'
  2341. ⍝.k library-utility
  2342. ⍝.n rml
  2343. ⍝.t 1992.4.25.18.28.6
  2344. ⍝.v 1.0 / 15oct83
  2345. ⍝.v 1.1 / 15may85 / various modifications
  2346. ⍝.v 1.2 / 04apr88 / added and improved definitions of codes
  2347. ⍝.v 1.3 / 15jul89 / ∆rowmem used, .b added
  2348. ⍝.v 1.4 / 25apr92 / comments and algorithms improved, .p added, .s removed
  2349. ⍝local variables start with underscore to avoid shadowed values. do not
  2350. ⍝use these names in executable expressions in <text>.
  2351. ⍝if <script> suspends ...
  2352. ⍝ - to display the row index of the bad line in the script, display I
  2353. ⍝ - to display the text of the bad line, display Text[I;]
  2354. ⍝ - to display the result so far, display Y
  2355. ⎕IO←1
  2356. 'script' checksubroutine 'fixuparray on ∆dlb ∆dtb ∆if ∆rowmem'
  2357. →(∼(⍴⍴Text)∈0 1 2)signalerror '/Y/script rank error/right arg has rank > 2'
  2358. →L02 ∆if 2=⍴⍴Text
  2359. ⍝vector. assume delimited by 'return' characters and reshape to matrix
  2360. Text←g∆cr ∆box Text
  2361. L02: ⍝argument <Text> is now a matrix
  2362. Y←Scriptbuffer←0 0⍴''
  2363. ⍝each code is in a 3-character format <.x > (period, code, blank)
  2364. Codes←'drpenctxb'
  2365. Tokens←'.',Codes,[1.5]' '
  2366. J←3
  2367. I←0
  2368. ⍝find indices of all lines starting with codes
  2369. BB←(((1↑⍴Text),J)↑Text)∆rowmem Tokens
  2370. L10:
  2371. →Lend ∆if(1↑⍴Text)<I←I+1
  2372. →(L15f,L15nf)∆if BB[I]
  2373. L15f: ⍝found code on this line
  2374. C←Text[I;2]
  2375. ⍝use everything after code for expression
  2376. L←J↓Text[I;]
  2377. →L15
  2378. L15nf: ⍝did not find code on this line. use entire line for result.
  2379. ⍝KK is used to improve performance. Find the next run of no-code lines and
  2380. ⍝append to result in one operation. Avoids looping over many lines.
  2381. KK←¯1+(I↓BB)⍳1
  2382. Y←Y on Text[I,I+⍳KK;]
  2383. I←I+KK
  2384. →L10
  2385. L15:
  2386. ⍝comment code .c is ignored (go to L10)
  2387. →(Ld,Lr,Lp,Le,Ln,L10,Lt,Lx,Lb)∆if C=Codes
  2388. Ld: ⍝display text
  2389. Y←Y on L
  2390. →L10
  2391. Lr: ⍝display computed result
  2392. Y←Y on fixuparray⍎L
  2393. →L10
  2394. Lp: ⍝capture statements and results
  2395. ⍝display all statements (including comments) as on terminal
  2396. ⍝capture and show output of all statements, including assignments
  2397. ⍝treat like .t except show output of assignment statements
  2398. ⍝note: there will be double output for ⎕ statements
  2399. →Lt
  2400. Le: ⍝execute
  2401. Sink←⍎L
  2402. →L10
  2403. Ln: ⍝niladic execute
  2404. ⍎L
  2405. →L10
  2406. Lt: ⍝terminal
  2407. ⍝remove leading blanks before further processing
  2408. L←∆dlb L
  2409. ⍝adjust 6 spaces for typical APL terminal display
  2410. Y←Y on(6⍴' '),L
  2411. ⍝exit now if L is an APL comment statement
  2412. →L10 ∆if '⍝'=1↑L
  2413. ⍝do not special-case assignment if processing a .p code
  2414. →Lt01 ∆if C='p'
  2415. ⍝test if assignment symbol in line
  2416. →Lt01 ∆if∼'←'∈L
  2417. ⍝there is assignment symbol. get text (quad or name) preceeding symbol.
  2418. X←(¯1+L⍳'←')↑L
  2419. ⍝test if text before assignment is a quad
  2420. →Lt03 ∆if∧/X∈'⎕'
  2421. ⍝test if text is valid name (assignment statement, no terminal output)
  2422. →(Lt02,Lt01)∆if∧/X∈'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890∆⍙'
  2423. Lt01:
  2424. ⍝L does not need special treatment. execute and capture result for display.
  2425. Y←Y on fixuparray⍎L
  2426. →L10
  2427. Lt02:
  2428. ⍝L has form: name←expression
  2429. ⍝execute but do not show result in document,
  2430. ⍎L
  2431. →L10
  2432. Lt03:
  2433. ⍝assume L has form: ⎕←expression or ⎕←name←expression
  2434. ⍝execute script recursively using .r code with the text without the ⎕
  2435. ⍝result of ⎕←expression will be embedded in document.
  2436. Y←Y on script '.r ',(L⍳'←')↓L
  2437. →L10
  2438. Lx: ⍝expunge
  2439. Sink←⎕EX '' ∆box ∆db L
  2440. →L10
  2441. Lb: ⍝build
  2442. ⍝fix scriptbuffer if L = '∇'
  2443. →(Lbf,Lba)∆if 1=+/'∇'=∆db L
  2444. Lbf:
  2445. Sink←⎕FX Scriptbuffer
  2446. →(' '≠1↑0⍴Sink)signalerror '/Y/script error/(⎕FX Scriptbuffer)=',(⍕Sink),' on line ',⍕I
  2447. Scriptbuffer←0 0⍴''
  2448. →L10
  2449. Lba:
  2450. Scriptbuffer←Scriptbuffer on L
  2451. →L10
  2452. Lend:
  2453. Y←∆dtb Y
  2454.  
  2455. ∇y←m search s;⎕IO;c;i;x
  2456. ⍝y[i]=1 if row <m[i;]> contains the search sequence <s>
  2457. ⍝.e 0 1 0 = (3 5⍴'appleanniecat ') search 'nn'
  2458. ⍝.k searching
  2459. ⍝.t 1989.7.27.22.22.10
  2460. ⍝.v 1.0 / 06may88
  2461. ⎕IO←1
  2462. s←,s
  2463. c←(¯1↑⍴m)⌈⍴s
  2464. x←((1↑⍴m),c)↑m
  2465. i←(⍳1+(⍴x)[2]-⍴s)∘.+¯1+⍳⍴s
  2466. ⍝pick rows that contain <s>
  2467. y←∨/x[;i]∧.=s
  2468.  
  2469. ∇y←shares
  2470. ⍝return names of shared variables
  2471. ⍝.e 1 ∆ shares
  2472. ⍝.k programming-tools
  2473. y←(2=⎕SVO ⎕NL 2)/[1]⎕NL 2
  2474.  
  2475. ∇Y←C signalerror T;M;Sink
  2476. ⍝display message <T> if condition <C> is true
  2477. ⍝.e 0=1 signalerror '/y'
  2478. ⍝.k programming
  2479. ⍝.t 1992.4.27.13.54.40
  2480. ⍝.v 1.0 / 27apr92
  2481. Y←⍳0
  2482. ⍝c=0: quit now (error did not occur)
  2483. →(∼C)/0
  2484. ⍝c=1: display message, erase variable specified in first row, return vector 0
  2485. Y←,0
  2486. M←(1↑T)∆box 1↓T
  2487. Sink←⎕EX M[⎕IO;]
  2488. M←1 0↓M
  2489. ⍝quit if no message, otherwise display non-empty message on quad device
  2490. →(0∈⍴M)/0
  2491. ⎕←(((1↑⍴M),3)⍴'.'),' ',M
  2492.  
  2493. ∇plt←sixline v;a;b;ma;mi;nc;x;xd;yd;⎕IO
  2494. ⍝return sixline plot given x and y data in <v> = n×2 matrix
  2495. ⍝.e 6 33 = ⍴sixline (⍳11),[1.5] (.5ׯ5+⍳10),0
  2496. ⍝.k plotting
  2497. ⍝.n rml
  2498. ⍝.t 1989.7.27.20.0.48
  2499. ⍝.v 1.0 / jun75
  2500. ⍝<v[;1]> is x-coordinate, <v[;2]> is y-coordinate
  2501. ⎕IO←1
  2502. →(2≠⍴⍴v)/err1
  2503. →(0∈⍴v)/err2
  2504. →(2≠¯1↑⍴v)/err3
  2505. nc←30⌈(1↑⍴v)⌊60
  2506. x←v[;1]
  2507. v←v[;2]
  2508. mi←⌊/x
  2509. ma←⌈/x
  2510. xd←⌈1+(x-mi)×(nc-1)÷ma-mi
  2511. yd←1⌈37⌊19+(×v)×⌊1+4×|v
  2512. a←((10⍴6),(4⍴5),(4⍴4),(5⍴3),(4⍴2),(10⍴1))[yd]
  2513. b←'x98765432143214321012341234123456789x'[yd]
  2514. plt←(6×nc)⍴' '
  2515. plt[nc⊥(a-1),[0.5]xd]←b
  2516. plt←(6 3⍴'+2|+1|+0|-0|-1|-2|'),(6,nc)⍴plt
  2517. →0
  2518. err1:
  2519. ⎕←'sixline rank error'
  2520. ⎕←'right argument does not have rank 2'
  2521. →0
  2522. err2:
  2523. ⎕←'sixline domain error'
  2524. ⎕←'right argument is empty'
  2525. →0
  2526. err3:
  2527. ⎕←'sixline length error'
  2528. ⎕←'right argument does not have 2 columns.'
  2529. →0
  2530.  
  2531. ∇y←cs sort m;⎕IO;c;shape
  2532. ⍝sort character vector or matrix <m> using collating sequence <cs>
  2533. ⍝.e 'dee' = ('' sort 3 3⍴'eggdogeat')[;1] ∆ g∆sort∆columns←1
  2534. ⍝.k sorting
  2535. ⍝.n rml
  2536. ⍝.t 1992.4.23.0.12.46
  2537. ⍝.v 1.3 / 22may85
  2538. ⍝.v 1.4 / 19jun86 / fixed bug in computing <c>
  2539. ⍝.v 1.5 / 04may88 / minor corrections, use gradeup
  2540. ⍝.v 2.0 / 22apr92 / better comments and arg checking, global arg now columns
  2541. ⎕IO←1
  2542. 'sort' checksubroutine 'gradeup'
  2543. →(∼(⍴⍴m)∈1 2)signalerror '/y/sort rank error/right arg not rank 1 or 2'
  2544. y←m
  2545. →(0∈⍴y)/0
  2546. ⍝ --- right argument
  2547. ⍝vector <m> is treated as a one-column matrix
  2548. shape←⍴m
  2549. m←(2↑(⍴m),1 1)⍴m
  2550. ⍝ --- global argument
  2551. ⍝define columns from global parameter (default is all columns)
  2552. ⍎(0=⎕NC 'g∆sort∆columns')/'g∆sort∆columns←⍳0'
  2553. c←g∆sort∆columns
  2554. c←((0∈⍴c)/⍳¯1↑⍴m),(∼0∈⍴c)/c
  2555. →(∨/(c<1),c>¯1↑⍴m)signalerror '/y/sort index error/column numbers not in domain (1,',(⍕¯1↑⍴m),')'
  2556. ⍝ --- left argument
  2557. ⍝defaults to implementation atomic vector
  2558. cs←((0∈⍴cs)/⎕AV),(∼0∈⍴cs)/cs
  2559. ⍝get specified columns of data, then sort and reshape to original shape
  2560. y←shape⍴m[cs gradeup m[;c];]
  2561.  
  2562. ∇Z←sortl X;G
  2563. ⍝sort local names in header of function <X> and fix result
  2564. ⍝.k programming-tools
  2565. ⍝.t 1992.4.3.13.25.24
  2566. ⍝.v 1.0 / 05may88
  2567. ⍝.v 1.1 / 03apr92 / signalerror used
  2568. →(3≠⎕NC X)signalerror '/Z/sortl domain error/(',X,') not a function.'
  2569. G←⎕CR X
  2570. →(0∈⍴G)signalerror '/Z/sortl domain error/function (',X,') locked.'
  2571. Z←⎕FX sortlocal G
  2572.  
  2573. ∇y←sortlocal x;⎕IO;c;header;i;t
  2574. ⍝sort local variables in first line of <x> = canonical matrix
  2575. ⍝.e 'y←sortlocal x;⎕IO;c;header;i;t' = ∆db (sortlocal ⎕CR 'sortlocal')[1;]
  2576. ⍝.k formatting
  2577. ⍝.t 1992.3.3.20.50.4
  2578. ⍝.v 1.0 / 12jun85 / first version
  2579. ⍝.v 1.1 / 03mar92 / ensure that special characters sort before letters
  2580. ⎕IO←1
  2581. 'sortlocal' checksubroutine 'gradeup'
  2582. →(2≠⍴⍴x)signalerror '/y/sortlocal rank error/left arg not rank 2'
  2583. ⍝do nothing if empty argument
  2584. →(0∈⍴y←x)/0
  2585. c←¯1↑⍴y
  2586. header←y[1;]
  2587. ⍝do nothing if no locals (no semicolon)
  2588. →(c<i←header⍳';')/0
  2589. ⍝sort locals and reconstruct list of local names
  2590. t←';' ∆box i↓header
  2591. ⍝ensure that special characters and blank sort before letters and numbers
  2592. t←t[(' ⎕∆⍙',⎕AV)gradeup t;]
  2593. t←1↓,';',t
  2594. ⍝assign new line 1 (header)
  2595. y[1;]←c↑(i↑header),(t≠' ')/t
  2596.  
  2597. ∇y←w split line;⎕IO;g;p;t
  2598. ⍝split text vector <line> into <w>-size pieces
  2599. ⍝.e 'please read the cat '=(20 split 'please read the cat in the hat')[1;]
  2600. ⍝.k formatting
  2601. ⍝.t 1992.4.25.16.55.44
  2602. ⍝.v 1.0 / 30oct81
  2603. ⍝.v 1.1 / 25apr92 / using signalerror
  2604. ⎕IO←1
  2605. →(w<1)signalerror '/y/split domain error/left arg (',(⍕w),') should be greater than 0'
  2606. line←,line
  2607. y←(0,w)⍴''
  2608. g←⍴line
  2609. →(g=0)/0
  2610. l2:
  2611. →((g=0),g≤w)/0,l4
  2612. ⍝find last blank in line. if no blanks, take whole piece
  2613. t←(w+1)-(' '=⌽w↑line)⍳1
  2614. p←(0 1=×t)/w,t
  2615. ⍝t=0 if there were no blanks
  2616. →(t=0)/l3
  2617. ⍝all blank or partially blank. if all blank, take whole piece
  2618. t←(p+1)-(' '≠⌽p↑line)⍳1
  2619. p←(0 1=×t)/w,t
  2620. l3:y←y,[1]w↑p↑line
  2621. g←⍴line←p↓line
  2622. →l2
  2623. l4:y←y,[1]w↑line
  2624. →0
  2625.  
  2626. ∇l←v sr s;⎕IO;i;n;o;r;rl;rn;ro;rr;w
  2627. ⍝search for 'old' sequence and replace by 'new' in <v>. <s>=/old/new
  2628. ⍝.e 'annie had a little lamb' = 'mary had a little lamb' sr '/mary/annie'
  2629. ⍝.k substitution
  2630. ⍝.t 1992.3.27.20.7.30
  2631. ⍝.v 1.0 / 15mar83
  2632. ⍝.v 2.0 / 02may88 / order of arguments reversed to conform to <ss>
  2633. ⍝.v 2.1 / 27mar92 / better error messages, signalerror used, renamed variables
  2634. ⍝the first element in <s> is the delimiter.
  2635. ⎕IO←1
  2636. 'sr' checksubroutine 'ss'
  2637. ⍝left argument
  2638. →(∼0 1∨.=⍴⍴v)signalerror '/l/sr rank error/left arg not rank 0 or 1.'
  2639. l←,v
  2640. ⍝right argument
  2641. →(1≠⍴⍴s)signalerror '/l/sr rank error/right arg not rank 1.'
  2642. →(2≠+/s=1↑s)signalerror '/l/sr domain error/delimiter in right arg must occur exactly twice.'
  2643. ⍝get old and new sequences
  2644. i←(s[1]=s)/⍳⍴s
  2645. o←1↓(¯1+i[2])↑s
  2646. n←i[2]↓s
  2647. ⍝determine number and locations of 'old' string
  2648. rr←⍴r←v ss o
  2649. →(0=rr)/0
  2650. ro←⍴o
  2651. ⍝check for overlapping occurrences of 'old'
  2652. →(∨/ro>¯1↓(1⌽r)-r)signalerror '/l/sr domain error/overlapping search sequence = ',⍕o
  2653. ⍝replace 'old' by 'new'
  2654. rl←⍴l
  2655. rn←⍴n
  2656. r←r-1
  2657. w←,(r+(rn-ro)ׯ1+⍳rr)∘.+⍳rn
  2658. l←(∼(⍳rl+rr×rn-ro)∈w)\(∼(⍳rl)∈r∘.+⍳ro)/l
  2659. l[w]←(rr×rn)⍴n
  2660.  
  2661. ∇l←text srn s;⎕IO;i;n;o;r;rl;rn;ro;rr;w
  2662. ⍝search and replace name by 'new' sequence in <text>. <s>=/name/new
  2663. ⍝.e 'factor←a3×vara÷factor×2' = 'a←a3×vara÷a×2' srn '/a/factor'
  2664. ⍝.k substitution
  2665. ⍝.t 1992.4.3.14.30.8
  2666. ⍝.v 1.0 / 05apr84
  2667. ⍝.v 1.1 / 23oct85 / corrections made to v1.0
  2668. ⍝.v 1.2 / 02may88 / ⎕IO added to header, ⎕-names added, ssn used
  2669. ⍝.v 1.3 / 03apr92 / arg checking enhanced, signalerror used
  2670. ⎕IO←1
  2671. 'srn' checksubroutine 'ss ssn'
  2672. ⍝left argument
  2673. →(∼0 1∨.=⍴⍴text)signalerror '/l/srn rank error/left arg not rank 0 or 1.'
  2674. l←,text
  2675. ⍝right argument
  2676. →(1≠⍴⍴s)signalerror '/l/srn rank error/right arg not rank 1.'
  2677. →(2≠+/s=1↑s)signalerror '/l/srn domain error/delimiter in right arg must occur exactly twice.'
  2678. ⍝ --- get old and new sequences
  2679. i←(s[1]=s)/⍳⍴s
  2680. o←1↓(i[2]-1)↑s
  2681. n←i[2]↓s
  2682. →(0∈⍴o)/0
  2683. ⍝ --- find positions of old sequence (name)
  2684. r←l ssn o
  2685. →(0∈⍴r)/0
  2686. ⍝note: no need to check <r> for overlapping occurences of <o>
  2687. ⍝ for further details see <ssn>.
  2688. ⍝ --- replace name with new sequence
  2689. ro←⍴o
  2690. rl←⍴l
  2691. rn←⍴n
  2692. rr←⍴r
  2693. r←r-1
  2694. ⍝<w> is indices of all occurrences of new sequence in new line
  2695. w←,(r+(rn-ro)ׯ1+⍳rr)∘.+⍳rn
  2696. ⍝remove occurrences of old sequence, and expand to allow new sequence
  2697. l←(∼(⍳rl+rr×rn-ro)∈w)\(∼(⍳rl)∈r∘.+⍳ro)/l
  2698. ⍝insert new sequence
  2699. l[w]←(rr×rn)⍴n
  2700.  
  2701. ∇y←v ss s;⎕IO;a;f;r
  2702. ⍝return all locations of sequence <s> in vector <v>
  2703. ⍝.e 1 12 ='the cat in the hat' ss 'the'
  2704. ⍝.k searching
  2705. ⍝.t 1992.3.28.1.36.58
  2706. ⍝.v 1.0 / 21feb83
  2707. ⍝.v 1.1 / 21apr88 / ⎕IO added to header, rank check added
  2708. ⍝.v 1.2 / 28mar92 / signalerror used
  2709. ⎕IO←1
  2710. ⍝left argument
  2711. →(1≠⍴⍴v)signalerror '/y/ss rank error'
  2712. s←,s
  2713. f←⍴s
  2714. a←⍴v
  2715. y←⍳0
  2716. →(f>a)/0
  2717. →(f=0)/0
  2718. →(1 0=f=1)/l1,l2
  2719. l1:
  2720. y←(s=v)/⍳a
  2721. →0
  2722. l2:
  2723. r←s∧.=(0,1-f)↓(¯1+⍳f)⌽(f,a)⍴v
  2724. y←r/⍳⍴r
  2725. →0
  2726.  
  2727. ∇y←text ssn s;⎕IO;b;vc
  2728. ⍝return locations of occurrences of the name <s> in vector <text>
  2729. ⍝.e 1 11 = 'a←a3×vara÷a×2' ssn 'a'
  2730. ⍝.k searching
  2731. ⍝.n rml
  2732. ⍝.t 1992.3.28.1.39.29
  2733. ⍝.v 1.2 / 02may88 / change name to ssn; use subroutine <ss>
  2734. ⍝.v 1.3 / 28mar92 / clarify comments, sequence <s> checked, signalerror used
  2735. ⎕IO←1
  2736. 'ssn' checksubroutine 'ss'
  2737. ⍝special check for invalid character=blank. (difficult error to notice)
  2738. →(' '∈s)signalerror '/y/ssn domain error/blanks in name specified in right arg.'
  2739. ⍝check for invalid characters. <vc> is valid characters allowed in a name
  2740. vc←'⎕abcdefghijklmnopqrstuvwxyz∆ABCDEFGHIJKLMNOPQRSTUVWXYZ⍙0123456789'
  2741. →(∼∧/s∈vc)signalerror '/y/ssn domain error/invalid characters in name specified in right arg.'
  2742. y←⍳0
  2743. →(0∈⍴s)/0
  2744. b←text∈vc
  2745. ⍝ note on overlapping occurrences when using <ss>:
  2746. ⍝ <ss> returns locations of overlapping occurrences. a name by
  2747. ⍝ definition will not overlap itself.
  2748. ⍝ ' ',s,' ' may overlap itself (e.g. <s>='x' with ' x x ' in text)
  2749. ⍝ but s will not because s does not contain blanks.
  2750. y←(' ',(b\b/text),' ')ss ' ',s,' '
  2751.  
  2752. ∇sl←stemleaf z;i;leaf;leafn;maxl;n;nleaf;stem;stemn;zn;zp;⎕IO
  2753. ⍝stem and leaf plot of data <z>
  2754. ⍝.e 12 17 = ⍴stemleaf ¯2 ¯23 23 34, (⍳10), (4×⍳10), 45 86 44
  2755. ⍝.k plotting
  2756. ⍝.t 1989.7.27.20.8.29
  2757. ⎕IO←1
  2758. z←,z
  2759. z←z[⍋z]
  2760. n←⍴z
  2761. zp←⌊(0≤z)/z
  2762. zn←⌊-(0>z)/z
  2763. stemn←⌊(zn,zp)÷10
  2764. leafn←⌊(zn,zp)-10×stemn
  2765. stemn←(⌊-(zn+1)÷10),⌊zp÷10
  2766. stem←stemn[1]+¯1+⍳1+stemn[n]-stemn[1]
  2767. nleaf←+/stem∘.=stemn
  2768. maxl←⌈/nleaf
  2769. leaf←((⍴stem),maxl)⍴' '
  2770. i←⍴stem
  2771. l:leaf[i;⍳nleaf[i]]←'0123456789'[1+(-nleaf[i])↑leafn]
  2772. leafn←(-nleaf[i])↓leafn
  2773. →(0≠i←i-1)/l
  2774. stem←(stem<0)+stem
  2775. sl←(5 0⍕((⍴stem),1)⍴stem),(((⍴stem),1)⍴'|'),leaf
  2776. →(0=⍴zn)/0
  2777. n←stem⍳¯1
  2778. →(n<⍴stem)/l1
  2779. →(n=⍴stem)/0
  2780. →(0=stem[i])/l2
  2781. →0
  2782. l1:sl[n+1;sl[n;]⍳'¯']←'¯'
  2783. →0
  2784. l2:sl[1;¯1+sl[1;]⍳'0']←'¯'
  2785.  
  2786. ∇Y←L stoptrace Names;Code;Fname;I;Ll;Mat;N;⎕IO
  2787. ⍝subroutine for qstop and qtrace
  2788. ⍝.k programming-tools
  2789. ⍝.n rml
  2790. ⍝.t 1988.4.23.14.36.24
  2791. ⍝.v 1.2 / 28dec83
  2792. ⍝.v 2.0 / 08apr88 / left arg changed: negative means no comment trace
  2793. ⍝ L[I] positive means to trace line L[I]
  2794. ⍝ L[I] negative means to trace if line L[I] is not a comment
  2795. ⍝ L 0 means to remove trace
  2796. ⍝ L empty defaults to negative numbers for all lines
  2797. ⍝ 1↑Names is Code -- 't' or 's', for trace or stop
  2798. ⍝ 1↓Names is namelist of functions
  2799. ⎕IO←1
  2800. ⍝function is trace or stop?
  2801. Code←1↑Names
  2802. Fname←(((Code='t')/'trace'),(Code='s')/'stop')
  2803. ⍝right argument
  2804. Names←'' ∆box ∆db 1↓Names
  2805. →(0∈⍴Names)/0
  2806. →(∼3∧.=⎕NC Names)/Err1
  2807. ⍝left argument
  2808. L←,L
  2809. I←0
  2810. L10:→((1↑⍴Names)<I←I+1)/0
  2811. Mat←⎕CR Names[I;]
  2812. N←1↑⍴Mat
  2813. ⍝L is empty? default to all negative lines
  2814. Ll←((0=⍴L)/-⍳N-1),(0≠⍴L)/L
  2815. ⍝if Ll[I] is negative and |Ll[I] is comment line, don't trace it. i.e. remove from list
  2816. ⍝note that line 0 (header) never is a comment line
  2817. Ll←(∼(¯1=×Ll)∧(|Ll)∈('⍝'=Mat[;1])/¯1+⍳N)/Ll
  2818. ⍝any other negative numbers are non-comment lines, so trace anyway
  2819. Y←Ll←|Ll
  2820. ⍝duplicate line numbers don't matter.
  2821. ⍝next line becomes something like: t∆xxxx←1 2 3
  2822. ⍎Code,'∆',Names[I;],'←',⍕Ll
  2823. →L10
  2824. Err1:
  2825. ⎕←Fname,' domain error'
  2826. ⎕←'cannot find function(s) = ',∆db,' ',(3≠⎕NC Names)⌿Names
  2827.  
  2828. ∇r←p subtotal m;⎕IO
  2829. ⍝compute and merge subtotals of <m> determined by positions <p>
  2830. ⍝.e (7 2⍴1 2 1 2 2 4 10 20 10 20 20 40 22 44) = (3 2⍴1 2 3 4 1 4) subtotal 4 2⍴1 2 1 2 10 20 10 20
  2831. ⍝.k computation
  2832. ⍝.t 1989.7.23.23.49.42
  2833. ⍝.v 1.0 jan82
  2834. ⍝<p> is n×2 matrix
  2835. ⍝ n is number of subtotal rows
  2836. ⍝ p[;1] is subtotal row start positions, p[;2] is end positions
  2837. ⎕IO←1
  2838. r←(m,[1]-/[2](+\[1]0,[1]m)[⌽p+(⍴p)⍴0 1;])[⍋(⍳1↑⍴m),p[;2];]
  2839.  
  2840. ∇p←d suppress v;b;level;mask;shape;x;⎕IO
  2841. ⍝suppress characters in matrix <v> delimited by delimiters <d>
  2842. ⍝.e 'abc def' = '()' suppress 'abc(xxx)def'
  2843. ⍝.k delete-elements
  2844. ⍝.t 1988.4.18.20.55.29
  2845. ⍝ d[1] = d[2] no nesting of delimiters is allowed
  2846. ⍝ d[1] ≠ d[2] nesting level is arbitrarily set to 1
  2847. ⎕IO←1
  2848. shape←⍴v
  2849. v←(¯2↑1 1,⍴v)⍴v
  2850. ⍝ensure that <d> has exactly 2 elements
  2851. d←2⍴d
  2852. →(0 1==/d)/different,same
  2853. different:
  2854. ⍝set level of nesting arbitrarily for this part
  2855. level←1
  2856. x←+\(v=d[1])-0 ¯1↓0,v=d[2]
  2857. mask←level≤x
  2858. →l10
  2859. same:
  2860. b←d[1]=v
  2861. mask←b≥0 1↓≠\1,b
  2862. →l10
  2863. l10:
  2864. p←mask⌽[1]v,[0.5]' '
  2865. p←shape⍴p[1;;]
  2866.  
  2867. ∇r←f thru tb;⎕IO;b
  2868. ⍝generate equal-interval vector from <f> to <1↑tb>, increment=¯1↑tb
  2869. ⍝.e 1 1.5 2 2.5 3 3.5 4 4.5 5 = 1 thru 5 .5
  2870. ⍝.k computation
  2871. ⍝.n dave macklin
  2872. ⍝.t 1992.4.22.22.28.22
  2873. ⍝.v 1.0 / 06may88
  2874. ⍝the interval is <1↓tb>
  2875. ⎕IO←0
  2876. b←|tb[1]
  2877. r←(tb[0]-f)÷b
  2878. r←f+(×r)×b×⍳1+⌊|r
  2879.  
  2880. ∇y←time
  2881. ⍝return current time of day in format hh:mm:ss (am/pm)
  2882. ⍝.e 1 ∆ time
  2883. ⍝.k time
  2884. ⍝.t 1992.4.22.22.13.52
  2885. ⍝.v 1.0 / 00oct80
  2886. ⍝.v 1.1 / 00apr88
  2887. ⍝.v 1.2 / 22apr92 / replaced all code with call to <ftime>
  2888. 'time' checksubroutine 'ftime'
  2889. y←ftime ⎕TS[4 5 6]
  2890.  
  2891. ∇y←timer n;tt
  2892. ⍝time <n> executions of an expression for cpu and connect time
  2893. ⍝.k timing
  2894. ⍝.t 1992.3.28.15.34.56
  2895. ⍝.v 1.0 / 12apl82
  2896. ⍝.v 1.1 / 28mar92 / clarified comments
  2897. ⍝this function uses ⎕AI
  2898. ⍝when using <timer> compute overhead first and ignore first timing test.
  2899. ⍝ tt starts with current accumulated cpu and connect time
  2900. tt←2↑1↓⎕AI
  2901. l1:→(0>n←n-1)/l2
  2902. ⍝put code here
  2903. →l1
  2904. l2:
  2905. ⍝ result y is elapsed cpu and connect time
  2906. y←(2↑1↓⎕AI)-tt
  2907.  
  2908. ∇interval timetrace msg;cp;now
  2909. ⍝print <msg> after <interval> milliseconds of cpu time
  2910. ⍝.k timing
  2911. ⍝example: 2000 timetrace 'another 2 seconds has elapsed'
  2912. now←1↑2↓⎕AI
  2913. ⍝check for checkpoint time (cp)
  2914. ⍎(0=⎕NC 'g∆timetrace∆cp')/'g∆timetrace∆cp←',⍕now
  2915. cp←g∆timetrace∆cp
  2916. →(interval>now-cp)/0
  2917. ⎕←msg
  2918. g∆timetrace∆cp←now
  2919.  
  2920. ∇y←timing
  2921. ⍝cover function to call and format elapsed cpu and connect time
  2922. ⍝.e 1 ∆ timing
  2923. ⍝.k timing
  2924. ⍝.t 1992.3.28.13.51.56
  2925. ⍝.v 1.0 / 25may88
  2926. y←fcpucon cpucon
  2927.  
  2928. ∇z←tower x;i;j;m;n;xx;y;z1;z2;z3;⎕IO
  2929. ⍝tower chart (skyscraper diagram) for contingency table <x>
  2930. ⍝.e 29 72 = ⍴tower 3 3⍴29 16 5 26 12 20 28 30 17
  2931. ⍝.k plotting
  2932. ⍝.n carina heiselbetz
  2933. ⍝.t 1989.7.27.20.10.30
  2934. ⎕IO←1
  2935. 'tower' checksubroutine 'field'
  2936. z←(n←¯1↓⍴x)field m←1↓⍴x
  2937. xx←100×x÷⌈/,x
  2938. z1←¯4+⌈0.0999999999999999778×⌈/,xx
  2939. z1←0⌈z1
  2940. z←((z1,1↓⍴z)⍴' '),[1]z
  2941. j←i←1
  2942. loop:
  2943. →(xx[i;j]<0)/l1
  2944. z2←z1+¯1+7×i
  2945. z3←(7×n-i+1)+17×j
  2946. →(xx[i;j]<5)/l2
  2947. y←1+⌊0.0999999999999999778ׯ5+xx[i;j]
  2948. z[z2-y;z3+¯1+⍳4]←1 4⍴'/¯¯/'
  2949. z[z2;z3+3]←'/'
  2950. z[z2-⍳y;z3+4]←'|'
  2951. z[z2-⍳y-1;z3+3]←' '
  2952. z[z2+1-⍳y;z3+¯2+⍳4]←(y,4)⍴'|⋆⋆|'
  2953. l1:
  2954. →(m≥j←j+1)/loop
  2955. →(n≥i←i+j←1)/loop
  2956. →end
  2957. l2:
  2958. z[z2;z3+¯1+⍳5]←'/___/'
  2959. z[z2-1;z3+⍳5]←'/¯¯¯/'
  2960. →l1
  2961. end:
  2962. z←z,[1]' '
  2963. z[¯1↓⍴z;9+⍳17×m]←(17×m)↑,(⍉1 6⍴'abcdef'),6 16⍴' '
  2964. i←1
  2965. l5:
  2966. z[z1+5+7×i-1;1+7×n-i]←⍕i
  2967. →(n≥i←i+1)/l5
  2968.  
  2969. ∇y←triangle n;i;z
  2970. ⍝print a pretty triangle using ≠\ where <n> is a power of 2
  2971. ⍝.e 16 16 = ⍴triangle 16
  2972. ⍝.k graphics
  2973. ⍝.n larry smith
  2974. ⍝note: if n is not a power of 2, the triangle is not pretty
  2975. i←0
  2976. y←''
  2977. z←n⍴1
  2978. l1:→(n<i←i+1)/end
  2979. y←y,z\'⋆'
  2980. z←≠\z
  2981. →l1
  2982. end:y←(n,n)⍴y
  2983.  
  2984. ∇r←c unbox x;b;chars;fill;sep;⎕IO
  2985. ⍝unbox matrix <x>. remove trailing <c[2]>, delimit vector <x> by <c[1]>
  2986. ⍝.e 'apple/betty/cat/' = '/' unbox 3 5⍴'applebettycat '
  2987. ⍝.k reshape
  2988. ⍝.t 1988.4.6.1.25.34
  2989. ⍝.v 1.0 / jul83
  2990. ⍝c[1]=separator character (default is blank/zero)
  2991. ⍝c[2]=fill character (default is blank/zero)
  2992. ⍝remove trailing character c[2] from the end of each line of matrix
  2993. ⍝then delimit end of each line with c[1] and return a vector
  2994. ⎕IO←1
  2995. r←0⍴x
  2996. →(0=⍴,x)/0
  2997. ⍝assign defaults to special characters
  2998. chars←c,(⍴,c)↓2↑0⍴x
  2999. ⍝get separator (to be put at end of each row)
  3000. sep←(⍳0)⍴1↑chars
  3001. ⍝get fill character (to be removed from end of each row)
  3002. fill←1↑1↓chars
  3003. r←x
  3004. ⍝compute 0 for trailing fill in each row and append 1 for sep
  3005. b←(⌽∨\⌽r≠fill),1
  3006. ⍝append line separator to end of each row
  3007. r←r,sep
  3008. ⍝remove trailing fill (but not separator)
  3009. r←(,b)/,r
  3010.  
  3011. ∇y←a union b;c
  3012. ⍝set union <a> and <b> leaving order of result as in <a>
  3013. ⍝.e (4 5⍴'applebettycat peach') = (3 5⍴'applebettycat ') union 3 5⍴'cat bettypeach'
  3014. ⍝.k uncategorized
  3015. ⍝.t 1988.4.6.1.28.16
  3016. c←⌈/0 1 0 1/(⍴a),⍴b
  3017. a←((1↑⍴a),c)↑a
  3018. b←((1↑⍴b),c)↑b
  3019. ⍝get elements of b but not in a and put them after a
  3020. y←a,[1](∼b ∆rowmem a)⌿b
  3021.  
  3022. ∇line←ved text;a
  3023. ⍝vector edit. edit vector <text> in a simple fashion
  3024. ⍝.k text-editing
  3025. ⍝.n jarry apsit
  3026. ⍝.t 1992.4.16.22.37.59
  3027. ⍝.v 1.0 / 23mar83
  3028. line←⍞,0⍴⍞←('/'≠text)/a\(a←'\'≠text←(⍴text)↑⍞)/⍞←text←,text
  3029.  
  3030. ∇N vedit Name;Prompt;T;Text;Y
  3031. ⍝vector edit. screen edit variable <name> from <n[1]> to <n[2]>
  3032. ⍝.k text-editing
  3033. ⍝.n rml
  3034. ⍝.t 1985.8.8.11.21.40
  3035. ⍝.v 1.1 / 8aug85
  3036. ⍝this function can be used on a terminal with screen editing features
  3037. Text←Y←⍎Name
  3038. ⍝assign defaults (1,end of text) to N
  3039. N←2↑N,(×/⍴N)↓1,×/⍴Text
  3040. ⍝ensure N is between 1 and ⍴Text
  3041. N←1⌈(⍴Text)⌊N
  3042. ⍞←Prompt←(¯1+N[1])↓N[2]↑Text
  3043. T←,⍞
  3044. →(0≠⍴T)/L2
  3045. →End,0⍴⎕←'empty result. no change'
  3046. ⍝if first part of T is all blank, do not →L1
  3047. L2:→(∼∧/' '=(1+N[2]-N[1])↑T)/L1
  3048. ⍝all blank. assume prompt text was unchanged and must be kept
  3049. ⍝reinsert Prompt into returned Text <T>
  3050. T←Prompt,(⍴Prompt)↓T
  3051. L1:Y←((N[1]-1)↑Text),T,N[2]↓Text
  3052. End:⍎Name,'←Y'
  3053.  
  3054. ∇r←x veq y;c
  3055. ⍝r←1 if vectors <x> and <y> are equal. trailing blanks ignored
  3056. ⍝.e 1 = 'apple' veq 'apple '
  3057. ⍝.k programming
  3058. ⍝scalar <x> or <y> treated as 1-element vector
  3059. c←(⍴,x)⌈⍴,y
  3060. r←(c↑x)∧.=c↑y
  3061.  
  3062. ∇r←vi a;t
  3063. ⍝validate numeric input <a>
  3064. ⍝.e 1 1 0 0 1 = vi '1 2 1a 3.3.3 123.35'
  3065. ⍝.k validation
  3066. ⍝.n gerald bamberger, apl quote-quad, mar 80
  3067. ⍝.t 1989.7.27.23.11.44
  3068. ⍝.v 1.0 / mar 80
  3069. t←' 11111111112345'[' 0123456789.¯e'⍳'0 ',a]
  3070. r←1↓⍎((t∈'234')∨t≠' ',¯1↓t)/t
  3071. r←r∈(8 3⍴0 41 431)+1 12 121 21 31 312 3121 321∘.×1 100 1000
  3072.  
  3073. ∇y←vnames v;an;r;t;⎕IO
  3074. ⍝validate name specifications in <v>
  3075. ⍝.e 1 12 131 412 4131 0 = vnames 'a d?⋆ a-d ∼∆⋆ ∼d-e ⋆a⋆a'
  3076. ⍝.k validation
  3077. ⍝.n rml
  3078. ⍝.t 1988.4.24.21.39.7
  3079. ⍝.v 1.2 23jan84
  3080. ⍝.v 2.0 26nov85 / add ? facility and remove escape chars
  3081. ⍝.v 2.1 22apr88 / add valid specifications, allow general ?, add ∼
  3082. ⍝valid name specifications:
  3083. ⍝ x x⋆ ⋆x x⋆y ⋆x⋆ ⋆ x-y x- -x -
  3084. ⍝ 1 12 21 121 212 2 131 13 31 3
  3085. ⍝also any of above prefaced by <∼>
  3086. ⍝<an> contains characters allowed to form x and y
  3087. ⎕IO←1
  3088. an←'?⎕abcdefghijklmnopqrstuvwxyz∆ABCDEFGHIJKLMNOPQRSTUVWXYZ⍙0123456789'
  3089. v←∆db v
  3090. →(0∈⍴y←v)/0
  3091. ⍝compute class of specifications in v
  3092. t←(' ',((⍴an)⍴'1'),'2345')[(' ',an,'⋆-∼')⍳v]
  3093. r←,⍎((t∈'234')∨t≠' ',¯1↓t)/t
  3094. ⍝return invalid codes as 0
  3095. y←r×r∈1 12 21 121 212 2 13 31 131 3 41 412 421 4121 4212 42 413 431 4131 43
  3096.  
  3097. ∇y←vpis v;a;cs;r;t
  3098. ⍝validate positive integer specification <v>
  3099. ⍝.e (2 2⍴1 12 1 121) = vpis '5- 1-10'
  3100. ⍝.k validation
  3101. ⍝.n rml
  3102. ⍝.t 1992.4.25.22.43.44
  3103. ⍝.v 1.0 / 23nov83
  3104. ⍝.v 1.1 / 13nov85
  3105. ⍝positive integer specification: sequence of integers and ranges
  3106. ⍝integer n to n n to end start to n all
  3107. ⍝ n n-n n- -n -
  3108. ⍝ 1 121 12 21 2
  3109. y←⍳0
  3110. a←∆db v
  3111. →(0∈⍴a)/0
  3112. ⍝character set for valid positive integer
  3113. cs←'0123456789'
  3114. t←(' ',((⍴cs)⍴'1'),'23')[(' ',cs,'-')⍳a]
  3115. r←,⍎((t∈'2')∨t≠' ',¯1↓t)/t
  3116. y←(r∈1 121 12 21 2),[1.5]r
  3117.  
  3118. ∇e←v vrepl a;i;j;l;m;v1;⎕IO
  3119. ⍝replace in <v> single-character abbreviations defined in <a>
  3120. ⍝.e 'dear bob how are you?' = '⎕ ○ how are ∆?' vrepl(3 5 ⍴'⎕dear○bob ∆you ')
  3121. ⍝.k substitution
  3122. ⍝.n k.h. glatting and g. osterburg
  3123. ⍝.t 1989.7.27.22.54.26
  3124. ⍝.v 1.0 / dec80
  3125. ⎕IO←1
  3126. v1←v∈a[;⎕IO]
  3127. i←v1/⍳⍴v
  3128. j←a[;⎕IO]⍳v[i]
  3129. ⍝determine the length of the string to replace each code
  3130. l←∼⌽∧\(1↑0⍴v)=⌽0 1↓a
  3131. l←l[j;]
  3132. m←0 1↓×\(i+0.5),l
  3133. v1←(∼v1)/⍳⍴v
  3134. e←(v[v1],(,l)/,0 1↓a[j;])[⍋v1,(,l)/,m]
  3135.  
  3136. ∇r←vtype x
  3137. ⍝return <r> = 'type' of variable <x> (logical,character,integer,real)
  3138. ⍝.e 4=vtype 10.456
  3139. ⍝.k programming-tools
  3140. ⍝.t 1983.10.31.17.40.29
  3141. ⍝.v 1.0 / 12feb82
  3142. ⍝warning: this is an implementation-dependent function
  3143. ⍝ <r> -- 1=logical,2=char,3=integer,4=real
  3144. x←64↑0⍴x
  3145. r←70000
  3146. r←⎕WA+70000
  3147. x←128↑x
  3148. r←0.125×r-⎕WA+70000
  3149. r←(1 2 3 4 4)[1 8 32 64⍳r]
  3150.  
  3151. ∇b←m wildcard s;⎕IO;c;i;j;name;wp;x
  3152. ⍝select names in matrix <m> using 'wildcard' search specification <s>
  3153. ⍝.e 0 0 1 1 0 = (5 5⍴'appleanniebettybattydog ') pick '⋆tt⋆'
  3154. ⍝.k searching
  3155. ⍝.t 1988.5.7.19.23.17
  3156. ⍝.v 1.0 / 06may88
  3157. ⍝<s> can contain ? search character
  3158. ⎕IO←1
  3159. s←,s
  3160. ⍝assume <s> is one of the following --- ⋆ ⋆a⋆ ⋆a a⋆ a⋆a a
  3161. →(('⋆'∧.=s),(2=+/'⋆'=s),('⋆'=1↑s),('⋆'=¯1↑s),('⋆'∈s),1)/all,mid,suff,pref,lr,exact
  3162. all: ⍝everything phrase: s=⋆
  3163. b←(1↑⍴m)⍴1
  3164. →0
  3165. mid: ⍝somewhere in between phrase: s=⋆name⋆
  3166. name←1↓¯1↓s
  3167. x←((1↑⍴m),(¯1↑⍴m)⌈⍴name)↑m
  3168. i←(⍳1+(⍴x)[2]-⍴name)∘.+¯1+⍳⍴name
  3169. →l50
  3170. suff: ⍝suffix phrase: s=⋆name
  3171. name←1↓s
  3172. ⍝right justify, then take last (⍴name) columns
  3173. x←((1↑⍴m),-⍴name)↑(-+/∧\⌽' '=m)⌽m
  3174. i←(1,⍴name)⍴⍳⍴name
  3175. →l50
  3176. pref: ⍝prefix phrase: s=name⋆
  3177. name←¯1↓s
  3178. x←((1↑⍴m),⍴name)↑m
  3179. i←(1,⍴name)⍴⍳⍴name
  3180. →l50
  3181. exact: ⍝exact phrase: s=name
  3182. c←(¯1↑⍴m)⌈⍴s
  3183. name←c↑s
  3184. x←((1↑⍴m),c)↑m
  3185. i←(1,c)⍴⍳c
  3186. →l50
  3187. l50:
  3188. ⍝if question mark in <name>, replace all non-blanks in corresponding
  3189. ⍝columns with '?'. algorithm works fine even if no '?' present. note
  3190. ⍝that <name> and <x> are conformable in length at this point. x is
  3191. ⍝always a rank-4 array after the next line.
  3192. x←x[;i],[0.5]'?'
  3193. wp←'?'=name
  3194. j←wp/⍳⍴wp
  3195. x[;;;j]←(x[1;;;j]≠' ')⌽[1]x[;;;j]
  3196. ⍝find rows that contain search string in specified columns
  3197. b←∨/x[1;;;]∧.=name
  3198. →0
  3199. lr: ⍝left - right phrase: s=name⋆name
  3200. b←(m wildcard(s⍳'⋆')↑s)∧m wildcard(¯1+s⍳'⋆')↓s
  3201.  
  3202. ∇r←s xfade c;c1;c2;⎕IO
  3203. ⍝transform text in <c> using a 'fading' algorithm controlled by <s>
  3204. ⍝.e 16 64 = ⍴16 64 xfade '/apple betty /is a dessert '
  3205. ⍝.k graphics
  3206. ⍝.n phil last
  3207. ⍝.t 1989.7.27.23.42.49
  3208. ⍝s[1] number of rows in result; s[2] number of columns
  3209. ⍝<c> is /first text/second text
  3210. ⍝.v 1.0 / 23jul82
  3211. ⎕IO←1
  3212. c2←,s⍴(1↓s←2⍴,s)⍴c2←(1⌈⍴c2)↑c2←1↓(2=c1←+\c∈1↑c)/c←(1⌈⍴c)↑c←,c
  3213. c1←,s⍴(1↓s)⍴c1←(1⌈⍴c1)↑c1←1↓(1=c1)/c
  3214. c2←,⊖s⍴c\(c,0⍴c[??⍳⍴c←,(×/s)⍴0]←1)/c2
  3215. c2[c/⍳⍴c]←(c,0⍴c[??⍳⍴c,⍴c[]←0]←1)/c1
  3216. r←s⍴c2
  3217.  
  3218. ∇y←l ∆ r
  3219. ⍝glue function. return left argument <l>
  3220. ⍝.e 101 = 101 ∆ 1+1 ∆ 2+2
  3221. ⍝.k programming
  3222. y←l
  3223.  
  3224. ∇y←chars ∆box x;fill;len;m;of;pos;s;sep;⎕IO
  3225. ⍝'box' vector <x> using separator and fill character <chars>
  3226. ⍝.e (3 5⍴'applebettycat ') = '/' ∆box 'apple/betty/cat'
  3227. ⍝.k reshape
  3228. ⍝.t 1988.4.28.1.20.21
  3229. ⍝.v 2.0 / 8jul83
  3230. ⍝chars[1]=separator; chars[2]=fill; defaults are blank/zero
  3231. ⍝<y> matrix corresponding to a vector delimited into logical fields
  3232. ⎕IO←1
  3233. y←0 0⍴x
  3234. →(0∈⍴x)/0
  3235. chars←chars,(×/⍴chars)↓2↑0⍴x
  3236. ⍝separator
  3237. sep←chars[1]
  3238. ⍝filler
  3239. fill←chars[2]
  3240. ⍝add sep to end if necessary
  3241. x←x,(sep≠¯1↑x)/sep
  3242. ⍝lengths
  3243. pos←(x=sep)/⍳⍴x
  3244. m←⌈/len←¯1+pos-0,¯1↓pos
  3245. ⍝offsets
  3246. of←(len+1)∘.⌊⍳m
  3247. ⍝starting indices
  3248. s←⍉(m,⍴len)⍴0,¯1↓pos
  3249. ⍝replace separator with fill character
  3250. x[(x=sep)/⍳⍴x]←fill
  3251. ⍝return matrix
  3252. y←x[s+of]
  3253.  
  3254. ∇y←fld ∆centh label;⎕IO;c;i;m;n
  3255. ⍝centre column headings <label> within fields specified by <fld>
  3256. ⍝.e ' a bb cc d' = 4 ¯1 2 ∆centh '/a/bb/cc/d'
  3257. ⍝.k formatting
  3258. ⍝.n rml
  3259. ⍝.t 1988.5.3.0.38.19
  3260. ⍝.v 1.0 / nov83
  3261. ⍝<fld> vector of triplets
  3262. ⍝[1] width; [2] 1=lj, 0=centre, ¯1=rj; [3] inter-column spacing
  3263. ⎕IO←1
  3264. y←''
  3265. ⍝box labels and left justify
  3266. m←(1↑label)∆box 1↓label
  3267. m←(+/∧\' '=m)⌽m
  3268. →(0=n←1↑⍴m)/0
  3269. fld←,fld
  3270. →((⍴fld)=1 3,3×n)/l1,l2,l2
  3271. →1 signalerror '/y/∆centh length error/left arg must have 1, 3, or 3×n elements.'
  3272. l1: ⍝1 number. extend to all fields, centred(0), 1 space
  3273. fld←⍉(3,n)⍴(n⍴fld),(n⍴0),n↑(n-1)⍴1
  3274. →l4
  3275. l2: ⍝3 or 3n numbers. extend width, positioning, spacing to all fields
  3276. fld←(n,3)⍴((¯1+3×n)⍴fld),0
  3277. →l4
  3278. l4:
  3279. ⍝arguments have now been defined and shaped
  3280. i←0
  3281. l05:→((1↑⍴fld)<i←i+1)/0
  3282. ⍝take as many columns as specified by fld[i]
  3283. c←fld[i;1]↑m[i;]
  3284. →(¯1 0 1=×fld[i;2])/l10,l20,l30
  3285. l10: ⍝right justify (¯1⌽x)
  3286. c←(-+/∧\' '=⌽c)⌽c
  3287. →l40
  3288. l20: ⍝centre
  3289. c←(-⌊0.5×+/∧\' '=⌽c)⌽c
  3290. →l40
  3291. l30: ⍝it is already left-justified
  3292. →l40
  3293. l40: ⍝catenate to full header
  3294. y←y,c,fld[i;3]⍴' '
  3295. →l05
  3296.  
  3297. ∇y←w ∆centt text;d;f;l;mid;p;v;⎕IO
  3298. ⍝centre <text> with left, middle, and right phrases in <w> spaces
  3299. ⍝.e 'date title page 1' = 25 ∆centt '/date/title/page 1'
  3300. ⍝.k formatting
  3301. ⍝.n rml
  3302. ⍝.t 1989.7.23.23.55.10
  3303. ⍝.v 1.0 / 2nov83
  3304. ⍝.v 2.0 / 23apr88 / remove 'feature' that specially handled one phrase
  3305. ⍝<text> has the form /left/middle/right
  3306. ⎕IO←1
  3307. d←1↑text
  3308. ⍝ensure 3 ending delimiters so there are three fields (phrases)
  3309. v←text,3⍴d
  3310. ⍝find positions p
  3311. p←(v=d)/⍳⍴v
  3312. ⍝lengths l
  3313. l←¯1+1↓p-¯1⌽p
  3314. ⍝we only want the first, second, and third phrases
  3315. ⍝get second phrase and centre within w spaces
  3316. mid←¯1↓p[2]↓p[3]↑v
  3317. mid←w↑((⌈0.5×w-⍴mid)⍴' '),mid
  3318. ⍝put them all together. w↑ ensures exactly w spaces
  3319. y←w↑(¯1↓1↓p[2]↑v),(l[1]↓(-l[3])↓mid),¯1↓p[3]↓p[4]↑v
  3320.  
  3321. ∇y←∆db v;b
  3322. ⍝delete blanks (leading, trailing and multiple) from v (rank 0 - 2)
  3323. ⍝.e 'apple betty cat' = ∆db ' apple betty cat '
  3324. ⍝.k delete-characters
  3325. ⍝.v 1.1
  3326. →((0 1 2=⍴⍴v),1)/l1,l1,l2,err1
  3327. l1:
  3328. b←' '≠v←' ',v
  3329. y←1↓(b∨1⌽b)/v
  3330. →0
  3331. l2:
  3332. b←∨⌿' '≠v←' ',v
  3333. y←0 1↓(b∨1⌽b)/v
  3334. →0
  3335. err1:⎕←'∆db rank error'
  3336.  
  3337. ∇y←c ∆dc v;b
  3338. ⍝delete characters (leading, trailing and multiple) from v (rank 0 - 2)
  3339. ⍝.e 'apple.betty.cat' = '.' ∆dc '...apple...betty...cat...'
  3340. ⍝.k delete-characters
  3341. ⍝.v 1.1
  3342. ⍝note: same algortihm as ∆db (delete blanks)
  3343. c←(⍳0)⍴1↑c
  3344. →((0 1 2=⍴⍴v),1)/l1,l1,l2,err1
  3345. l1:
  3346. b←c≠v←c,v
  3347. y←1↓(b∨1⌽b)/v
  3348. →0
  3349. l2:
  3350. b←∨⌿c≠v←c,v
  3351. y←0 1↓(b∨1⌽b)/v
  3352. →0
  3353. err1:⎕←'∆dc rank error'
  3354.  
  3355. ∇y←∆dlb v
  3356. ⍝delete leading blanks from v (rank 0 - 2)
  3357. ⍝.e 'apple betty cat' = ∆dlb ' apple betty cat'
  3358. ⍝.k delete-characters
  3359. ⍝.v 1.1
  3360. →((0 1 2=⍴⍴v),1)/l1,l1,l2,err1
  3361. l1:y←(¯1+(v≠' ')⍳1)↓v
  3362. →0
  3363. l2:y←(∨\∨⌿v≠' ')/v
  3364. →0
  3365. err1:⎕←'∆dlb rank error'
  3366.  
  3367. ∇y←c ∆dlc v
  3368. ⍝delete leading character c from v (rank 0 - 2)
  3369. ⍝.e 'apple betty cat' = '.' ∆dlc '.....apple betty cat'
  3370. ⍝.k delete-characters
  3371. ⍝.v 1.1
  3372. ⍝note: same code as ∆dlb (delete leading blanks)
  3373. c←1↑c
  3374. →((0 1 2=⍴⍴v),1)/l1,l1,l2,err1
  3375. l1:y←(¯1+(v≠c)⍳1)↓v
  3376. →0
  3377. l2:y←(∨\∨⌿v≠c)/v
  3378. →0
  3379. err1:⎕←'∆dlc rank error'
  3380.  
  3381. ∇y←∆dtb v
  3382. ⍝delete trailing blanks from <v> (rank 0 - 2)
  3383. ⍝.e 'a b c' = ∆dtb 'a b c '
  3384. ⍝.k delete-characters
  3385. ⍝.v 1.1
  3386. →((0 1 2=⍴⍴v),1)/l1,l1,l2,err1
  3387. l1:y←(1-(⌽v≠' ')⍳1)↓v
  3388. →0
  3389. l2:y←(∨⌿⌽∨\⌽v≠' ')/v
  3390. →0
  3391. err1:⎕←'∆dtb rank error'
  3392.  
  3393. ∇y←c ∆dtc v
  3394. ⍝delete trailing character c from v (rank 0 - 2)
  3395. ⍝.e 'a b c' = '.' ∆dtc 'a b c.....'
  3396. ⍝.k delete-characters
  3397. ⍝.v 1.1
  3398. ⍝note: same code as dtb (delete trailing blanks)
  3399. c←1↑c
  3400. →((0 1 2=⍴⍴v),1)/l1,l1,l2,err1
  3401. l1:y←(1-(⌽v≠c)⍳1)↓v
  3402. →0
  3403. l2:y←(∨⌿⌽∨\⌽v≠c)/v
  3404. →0
  3405. err1:⎕←'∆dtc rank error'
  3406.  
  3407. ∇y←label ∆if condition
  3408. ⍝if statement. return <label[i]> if <condition[i]> = 1
  3409. ⍝.e 20 = 10 20 ∆if 3 4 = 2+2
  3410. ⍝.k programming
  3411. ⍝.t 1992.4.27.14.39.33
  3412. ⍝.v 1.0 / 00sep85
  3413. ⍝.v 1.1 / 27apr92 / clarified comments, empty result if empty right arg
  3414. y←⍳0
  3415. ⍝if <condition> is empty, return ⍳o
  3416. →(0∈⍴condition)/0
  3417. ⍝if condition is boolean, return corresponding label vector or ⍳o
  3418. ⍝note: if <label> is one element longer than <condition>, the last label
  3419. ⍝ may be considered the label of an 'else' statement.
  3420. y←((⍴,label)⍴condition,1)/label
  3421.  
  3422. ∇r←x ∆rowmem y;c
  3423. ⍝r[i]=1 if <x[i;]> is a row in <y> (trailing blanks ignored)
  3424. ⍝.e 1 0 = (2 5⍴'applezebra') ∆rowmem 4 5⍴'applebettycat dog '
  3425. ⍝.k searching
  3426. ⍝.t 1992.4.22.23.42.16
  3427. ⍝.v 1.0 / 22sep85
  3428. ⍝.v 1.1 / 13mar88 / revised error messages
  3429. ⍝.v 1.2 / 22apr92 / using signalerror
  3430. →(2<⍴⍴x)signalerror '/r/∆rowmem rank error/left arg has rank greater than 2'
  3431. →(2<⍴⍴y)signalerror '/r/∆rowmem rank error/right arg has rank greater than 2'
  3432. ⍝make x and y matrices
  3433. x←(¯2↑1 1,⍴x)⍴x
  3434. y←(¯2↑1 1,⍴y)⍴y
  3435. ⍝c is maximum number of columns
  3436. c←(¯1↑⍴x)⌈¯1↑⍴y
  3437. ⍝pad with blank columns on right to make columns conformable
  3438. r←∨/(((1↑⍴x),c)↑x)∧.=⍉((1↑⍴y),c)↑y
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement