Download | ||

The MACFNS1.W3 workspace is delivered "for trial only": you are not allowed to include these Assembler functions in sofwtare you distribute or sell! | ||

The free MACFNS1.W3 workspace includes a few sample Assembler functions extracted from the *MACfns* v4.0 product.

The functions are the following:

∆AVFREQ | Frequency of all characters: +/⎕AV∘.≡,R |

∆DATEUNP | Unpack scalars as YYYY MM DD dates |

∆INDS | Indices of nonzeros in vector (bitvec R/⍳⍴R): (~R∊0)/⍳⍴,R |

∆MATNV | Character matrix to nested vector |

∆ROWFIND | Flag rows of character L containing vector R: ∨/R⍷1/L |

You should test these functions with various arguments of different sizes, notably with very large arguments
and see how fast these functions are. All **257 Assembler functions** in the *MACfns* package have the same
quality and speed!

**Important Note:** the ∆INITMAC function must be run in a workspace before using any MACfns function

Here are the **documentation** and **examples** showing use of the above Assembler functions (you can use the top right toolbar Print button in this page to print this as documentation for your trials):

## ∆AVFREQ: Frequency of all characters

### Documentation

Z←∆AVFREQ R is equivalent to +/⎕AV∘.≡,R, returning a 256-element nonnegative integer vector reporting the number of occurrences in R of each character of ⎕AV. R may be any array. Only simple character scalars are counted, so if R is heterogeneous or nested, (+/∆AVFREQ R)≡+/,(⎕TYPE R)∊' '. If R is simple, ∆AVFREQ is equivalent to +/⎕AV∘.=,R. If R is character, (+/∆AVFREQ R)≡×/⍴R. If R is numeric or empty, (∆AVFREQ R)≡256⍴0. For simple R, ∆AVFREQ differs from +/⎕AV∘.=,R in APL+Win version 3.6.02 in the following respects: 1. ∆AVFREQ needs space only for its 1,048-byte result; APL needs an additional 32 (if R is homogeneous) or 2,556 (if R is heterogeneous) bytes per item of R. APL returns a Boolean result if 1≥⍴,R; ∆AVFREQ always returns an integer result. 2. ∆AVFREQ R is faster than +/⎕AV∘.=,R for any nonempty array; it can exceed 1,000 times for character and 10,000 times for heterogeneous, but is arbitrarily faster for numeric. 3. +/⎕AV∘.=,R can process up to 838,860 homogeneous or 835,586 heterogeneous items. ∆AVFREQ can process up to 2,147,483,647 items. More sophisticated APL code can substantially improve upon the performance of +/⎕AV∘.=,R (which is usually much faster than +/⎕AV∘.≡,R) in all three aspects listed above, but is still typically 25-100 times slower than ∆AVFREQ. Errors: (none) Related functions: ∆AVEPS (⎕AV∊R), ∆AVNUB (⎕AV~⎕AV~R), ∆AF (atomic function).

### Examples

(256⍴0)≡∆AVFREQ ⍬ ⍝ identity 1 (256⍴1)≡∆AVFREQ ⎕AV ⍝ identity 1 8 32⍴∆AVFREQ R←'THE FIVE BOXING WIZARDS JUMP QUICKLY' 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 2 1 1 1 4 1 1 1 1 1 1 1 1 1 1 1 2 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ⍝ much faster than R[⎕AV⍋R] to sort 25≤⍴chrvec in ⎕AV order: (∆AVFREQ R)/⎕AV ABCDEEFGHIIIIJKLMNOPQRSTUUVWXYZ ⍝ nonsimple heterogeneous: H←'A' 1 'V' 8 'B' 2 'C' 'O' 2 'H' 2 'O' 'C' 3 'PO' (⍳3) (∆AVFREQ H)/⎕AV ABCCHOOV

## ∆DATEUNP: Unpack scalars as dates

### Documentation

Z←{L} ∆DATEUNP R unpacks integers in R to YYYY MM DD dates (3↑⎕TS-form datestamps) given they are in the human-readable format specified by packing format L[1] (default 0): ↑L Format of Right Argument APL equivalent 0 YYYYMMDD (default) ⍉ 0 100 100⊤⍉⌊.5+R 1 MMDDYYYY (U.S.) ⍉2⊖0 100 10000⊤⍉⌊.5+R 2 DDMMYYYY (E.U.) ⍉ ⊖0 100 10000⊤⍉⌊.5+R 3 YYMMDD (two-digit years) Adjusted ⍉ 0 100 100⊤⍉⌊.5+R 4 MMDDYY Adjusted ⍉2⊖0 100 100⊤⍉⌊.5+R 5 DDMMYY Adjusted ⍉ ⊖0 100 100⊤⍉⌊.5+R See below for the adjustments made to two-digit years. The right argument is an integer array of dates packed in one of the six formats shown above; it may also be floating point values, which are rounded like ∆IRND (⌊.5+R), Boolean, or empty character. If ↑L is 0-2, R must be 0-99999999 (1E8-1); if ↑L is is 3-5, R must be 0-999999 (1E6-1). The result is a three-column integer array of shape (⍴R),3 (i.e., a trailing three axis is introduced); if R is a scalar, Z is a three-element vector. The dates in the result are not validated so ∆DATEUNP can be used for other purposes, but the first column (nominally years) will be 0-9999 and the second and third columns (nominally months and days) will be 0-99. The optional left argument is an integer scalar or vector having 0-2 items. The first item L[1] (default 0) specifies the format of the numbers in the right argument; it must be 0-5 and is same as the packing format used by ∆DATEPACK, the inverse of ∆DATEUNP. The second item L[2] (default 2060) is the cusp year (CCYY) for changing two-digit to four-digit years; it is used only when the first item is 3-5, and must be 99-9999. If a two-digit year in R is less than or equal to 100∣CCYY, (60 using the default cusp year of 2060) then CCYY-100∣CCYY (CC00 or 2000 using the default) will be added to the year; if greater than 100∣CCYY, then CCYY-100+100∣CCYY (CC00-100 or 1900 using the default) will be added. Thus, the first column of the result will be from CC00-99 to CCYY (default 1961 to 2060), and will never be greater than the cusp year in L[2]. If YR is the two-digit years from R (YR←⌊R÷10000 if L[1]=3 or YR←100∣R if L[1]≥4), then the year in the first column of Z is computed by YY←100∣CCYY←L[2] ⋄ (CCYY-YY)+YR-100×YR>YY For example, L[2] Interpretation Rules 99 no adjustment Years 00-99 remain 0-99. 2000 20th century Year 00 becomes 2000; years 01-99 become 1901-1999. (default) 2060 1961-2060 Years 00-60 become 2000-2060; years 61-99 become 1961-1999. 2079 1980-2079 Years 00-79 become 2000-2079; (DOS dates) years 80-99 become 1980-1999. 2099 all 2000's Years 00-99 become 2000-2099. 2100 21st century Year 00 becomes 2100; years 01-99 become 2001-2099. ∆DATEUNP is useful for unpacking dates from external processes for use by ∆DATEBASE or, in conjunction with ∆DATEPACK, changing the format of packed dates. ∆DATEUNP is up to 5-8 times faster than the fastest APL code (which is not that given above) in APL+Win version 3.6.02 for 8-15 integer dates, depending on the left argument (the ratios are greater if L[1]≥3), the datatype of the right argument (the ratios are greater if R is floating point, yet greater if R is Boolean), the rank and shape of the right argument (the ratios increase as these increase), and the APL comparison code. APL can process up to 71,582,784 dates; ∆DATEUNP can process up to 89,333,375. Errors: DOMAIN ERROR The first item of the left argument is not an integer 0-5, or the second item is not an integer 99-9999. The right argument is character and not empty. LENGTH ERROR The left argument is a vector of length exceeding two. LIMIT ERROR The right argument is of rank 127. The result size would exceed 1,072,000,528 bytes. An item of the right argument is not 0-99999999 when L[1]≤2, or not 0-999999 when L[1]≥3. NONCE ERROR The right argument is nested or heterogeneous. RANK ERROR The left argument is not a scalar or vector. Customization: The fourth and sixth items of ⍙DATEUNP are defaults. The default packing format (PF) (when L is not supplied or is empty) is 0, specifying YYYYMMDD dates in R, but it can be changed by ⍙DATEUNP[⎕IO+3]←PF. The default cusp year (CCYY) (when L is not supplied or is not a two-item vector) is 2060, but it too can be changed by ⍙DATEUNP[⎕IO+5]←CCYY. DOMAIN ERROR will be signaled if ⍙DATEUNP[⎕IO+3] is not 0-5 or ⍙DATEUNP[⎕IO+5] is not 99-9999. The third item of the left argument of ⎕CALL (normally ⎕STPTR'L') may be elided (using ⍙rz in place of ⍙rzl) or 0, and the left argument eliminated, for solely monadic usage: ∇ Z←∆DATEUNP R [1] →⍙rz ⎕CALL ⍙DATEUNP⍝∇Unpack scalars as YYYY MM DD dates. ... Related functions: ∆DATEPACK (pack dates as scalars), ∆DOS2D (unpack two DOS dates).

### Examples

∆DATEUNP 20080517 ⍝ default format YYYYMMDD 2008 5 17 1 ∆DATEUNP 5172008 ⍝ United States format MMDDYYYY 2008 5 17 2 ∆DATEUNP 17052008 ⍝ European format DDMMYYYY 2008 5 17 L←¯1+⍳6 ⍝ Illustrate all six packing formats: R←3/12345678 123456 ⍝ need not be valid dates F←2/6 4⍴'YYMDMDYYDMYY YMD MDY DM' L,R,F,L ∆DATEUNP¨R 0 12345678 YYYYMMDD 1234 56 78 1 12345678 MMDDYYYY 5678 12 34 2 12345678 DDMMYYYY 5678 34 12 3 123456 YYMMDD 2012 34 56 4 123456 MMDDYY 2056 12 34 5 123456 DDMMYY 2056 34 12 D←12900 40801 71445 103160 110761 122599 ⍝ MMDDYY dates D,4 ∆DATEUNP D ⍝ default cusp year 2060 (same as 4 2060 ...) 12900 2000 1 29 40801 2001 4 8 71445 2045 7 14 103160 2060 10 31 110761 1961 11 7 122599 1999 12 25 D,4 2100 ∆DATEUNP D ⍝ all 21st century years 12900 2100 1 29 40801 2001 4 8 71445 2045 7 14 103160 2060 10 31 110761 2061 11 7 122599 2099 12 25 D,4 2099 ∆DATEUNP D ⍝ all 2000's 12900 2000 1 29 40801 2001 4 8 71445 2045 7 14 103160 2060 10 31 110761 2061 11 7 122599 2099 12 25 D,4 99 ∆DATEUNP D ⍝ no adjustment to years 12900 0 1 29 40801 1 4 8 71445 45 7 14 103160 60 10 31 110761 61 11 7 122599 99 12 25

## ∆INDS: Indices of nonzeros in vector

### Documentation

Z←∆INDS R is equivalent to (~R∊0)/⍳⍴,R, returning the ⎕IO-dependent indices of the nonzeros in a vector. The result is always an integer vector, even if empty. Scalars are accepted as one-item vectors, but arrays of higher rank are rejected with a RANK ERROR. For simple vectors, ∆INDS is equivalent to (0≠R)/⍳⍴R. For Boolean vectors, ∆INDS is equivalent to R/⍳⍴R. Indices of all but simple scalar 0's are returned for nested and heterogeneous vectors. The result is ⍳⍴R for character vectors (all items are nonzero). ∆INDS is equivalent to WHERE from the 'ASMFNS' workspace supplied by APL2000 with APL+Win version 3.6.02. However, ∆INDS can process character, heterogeneous, and nested vectors, whereas WHERE rejects them with a DOMAIN ERROR. WHERE uses APL for part (0≠R) of its processing of integer and floating point vectors, but ∆INDS handles these natively. ∆INDS R is also equivalent to ∆INDS ∆ZNE R (the ∆ZNE being superfluous) or ∆ZNDS ∆ZEQ R. APL and WHERE can return up to 214,748,352 indices; ∆INDS can return up to 268,000,001 indices. At minimum, APL needs more than double the space of the result (sometimes arbitrarily more) to hold both the Boolean left and integer right arguments of the compression. ∆INDS and WHERE need space only for their result and (only when the argument is not Boolean) a Boolean vector of the length of the argument (but sometimes less for ∆INDS). ∆INDS is faster than APL for simple homogeneous vectors of length 100 or more (length 2,000 if all-0 Boolean), up to 4-50 times for Boolean, and 4-15 times for integer and floating point. It is up to 10-50 times faster than APL for simple heterogeneous vectors of length seven or more, but can exceed 100 times faster for nested vectors. ∆INDS is always faster than WHERE, up to 1.3-8 times. Errors: LIMIT ERROR The argument has more than 268,000,001 nonzeros. The length of the argument plus the customized origin (see point 2. below) exceeds 2*31. RANK ERROR The argument is not a scalar or vector. WS FULL The size of the result (24+4×+/~R∊0) would exceed the workspace available. When the argument is not Boolean, there is not enough ⎕WA to hold both R∊0 and ⍳+/~R∊0. Customization: The index origin ⎕IO is an implicit argument of ∆INDS; it is passed to the machine code as the fourth item of the left argument of ⎕CALL: ∇ Z←∆INDS R;L [1] →(⍙rzl,⎕IO)⎕CALL ⍙INDS⍝∇Indices of nonzeros ... Three modifications are useful: 0. If the result is always desired in origin 0, irrespective of ⎕IO, then ⎕IO may be elided by changing line [1] to [1] →⍙rzl ⎕CALL ⍙INDS⍝∇Origin-0 indices of nonzeros ... (Unsupplied values default to 0 in ⎕CALL.) 1. If the result is always desired in origin 1, irrespective of ⎕IO, then line [1] may be changed to [1] →(⍙rzl,1)⎕CALL ⍙INDS⍝∇Origin-1 indices of nonzeros ... Alternatively, for a minor speedup (25% in small cases), create a new global ⎕STPTR variable during workspace initialization forMACfns, here ⍙rzl1, ⍙r←↑⍙rz←2⍴⍙rzl1←(⍙rzl←3⍴⍙rzla←⎕STPTR'R Z L A'),1 then use it to avoid repeated catenations: [1] →⍙rzl1 ⎕CALL ⍙INDS⍝∇Origin-1 indices of nonzeros ... 2. If an origin other than 0 or 1 is desired, the fourth item may be set to any integer (⎕DR type 323), which can be a constant (as in case 1. above), a global, or, most cleanly and conveniently, as the left argument (renaming the function is appropriate in this case): ∇ Z←L ∆OINDS R [1] →(⍙rzl,L)⎕CALL ⍙INDS⍝∇Origin-L indices of nonzeros ... The left argument may not be preserved (local L is used for temporary storage). RANK or LENGTH ERROR will be engendered (by ⎕CALL) if L is not a vector or scalar with 0-4 items (all but the first being ignored); DOMAIN ERROR will be engendered (by ⎕CALL) if L is not numeric and exactly [demotable to] an integer in the range ¯2147483648-2147483647. LIMIT ERROR will be signaled (by ∆INDS) if (2*31)<↑L+⍴R. Related functions: ∆ZNDS ((R∊0)/⍳⍴R), ∆INDEX_ ((⊂R)⌷[⎕IO]L), ∆ZNE (~R∊0), ∆SUMZNE (+/,~R∊0).

### Examples

∆INDS 0 1 1 0 1 0 0 1 0 0 2 3 5 8 ∆INDS 'ZERO' (,0) 0 '0' ⍝ only the third item is scalar 0 1 2 4 (⍳256)≡∆INDS ⎕AV ⍝ all characters are nonzero 1 V←¯5+?12⍴9 ⊃(⍳⍴V) V ⍝ show indices with vector 1 2 3 4 5 6 7 8 9 10 11 12 ¯3 2 0 0 ¯3 ¯4 2 2 4 ¯1 0 3 ∆INDS V ⍝ indices of nonzeros 1 2 5 6 7 8 9 10 12 ⎕IO←0 ⍝ switch to origin 0 ∆INDS V ⍝ new indices of nonzeros 0 1 4 5 6 7 8 9 11 S←⊂[1]1-?9 99⍴3 ⍝ 9-item vector of 99 random signs N←(S≠0)⎕REPL¨⍳¨⍴¨S ⍝ clumsy nested-array pepper code N≡∆INDS¨S ⍝ easier and faster 1

## ∆MATNV: Character matrix to nested vector

### Documentation

Z←{L} ∆MATNV R creates a nested vector of character vectors from character matrix R after deleting trailing blanks, or the fill character L, from each row. The right argument must be a character or empty matrix. If provided, the optional left argument must be a single character or ¯1. The result is a nested vector of depth two and shape ↑⍴R in which each item of Z is a row of R after deleting trailing blanks (or L if given). The items are character even if an item of R is empty and not character. L may also be the distinguished value ¯1 to delete no trailing characters from each row, in which case the result is the same as ⎕SPLIT R or ⊂[⎕IO+1]R. ∆MATNV is equivalent to (+/∨\L≠⌽R)⍴¨⊂[⎕IO+1]R (which simplifies to ⊂[2]R if ⎕IO=1 and L=¯1 and R has one or more rows). ∆MATNV is also equivalent to (∆DTBLENS R)⍴¨⎕SPLIT R when L is a blank or not given. ∆MATNV differs from APL+Win version 3.6.02 in the following respects: 1. Unless L=¯1, the result of ∆MATNV is smaller than that of APL if two or more rows of R are all blank, approaching 1/7 the size if all rows are blank. If no rows are blank, the size of the result of ∆MATNV is usually 4-12 bytes smaller than that of APL. 2. ∆MATNV uses no more than four bytes of intermediate storage per item of the result, and often less. APL needs at least 42 bytes per item, and usually more. 3. Monadic ∆MATNV, or when the left argument is a character, is up to 10-50 times faster than APL for all nonempty matrices. When the left argument is ¯1, it is faster than ⎕SPLIT R or ⊂[2]R alone when R has 25-800 or more elements (ranging from 25×1 to 16×16 to 1×800 matrices), up to 5-25 times, and for empty matrices having more than 800 rows or 200 columns, up to 3-20 times. 4. The size of the result of ∆MATNV is limited to 1,072,000,528 bytes. APL imposes no specific overall limit. APL can handle matrices having up to 214,748,352 rows or columns. ∆MATNV can accommodate up to 268,000,120 rows or (after deleting trailing blanks) 1,072,000,476 columns. Errors: DOMAIN ERROR The right argument is a matrix, but neither character nor empty. The left argument is neither character nor ¯1. LIMIT ERROR The result size would exceed 1,072,000,528 bytes. RANK ERROR The right argument is not a matrix. The left argument is not a singleton. WS FULL There is not enough ⎕WA to hold both the temporary local variable L and the result. The size of L (which overwrites the left argument) varies, but is no more than 24+4×↑⍴R. Customization: The sixth item of ⍙MATNV is the default trailing fill character (FC). Normally the default (when L is not supplied) is blank=∆AF 32, but it can be changed by ⍙MATNV[⎕IO+5]←∆AF FC. ⍙MATNV[⎕IO+5] may also be ¯1 for no trailing fill. DOMAIN ERROR will be signaled if ⍙MATNV[⎕IO+5] is not ¯1-255. Related functions: ∆NVMAT (nested vector to character matrix), ∆MATDS (matrix to delimited string), ∆MATSS (matrix to segmented string), ∆DTBLENS (+/∨\' '≠⌽R).

### Examples

⎕←M←3 9⍴'Ethel Arnold Mackenzie' Ethel Arnold Mackenzie ⍴¨⎕←∆MATNV M Ethel Arnold Mackenzie 5 6 9 ⍴¨⎕←¯1 ∆MATNV M ⍝ delete no trailing blanks Ethel Arnold Mackenzie 9 9 9 ⍝ this documentation as a matrix: ⍴R←∆DSMAT 4 1⊃'←' GetMACfns'dMATNV' 96 66 ⍴A←(+/∨\' '≠⌽R)⍴¨⊂[2]R 96 A≡B←∆MATNV R 1 R≡⊃B 1 ⎕SIZE'R A B' 6364 6488 6148

## ∆ROWFIND: Flag string in rows

### Documentation

Z←L ∆ROWFIND R flags rows of character array L which contain string R. L must be a character or empty array of any rank; R must be a vector or scalar, nominally character. The result is a Boolean array of shape ¯1↓⍴L. If R is empty and L has one or more columns, the result is all 1's. If both have zero columns, or R is wider than L, or R is neither character nor empty, the result is all 0's. L ∆ROWFIND R is equivalent to ∨/R⍷1/L for character L, except that if R is empty and L is not empty and their types differ, ∆ROWFIND returns all 1's, but APL [erroneously] returns all 0's. For example, if L←2 1⍴'A', then 1 1≡L ∆ROWFIND'' and 1 1≡L ∆ROWFIND ⍬ and 1 1≡∨/''⍷L but [erroneously] 0 0≡∨/⍬⍷L. (The 1/ in ∨/R⍷1/L is solely for when L is a scalar and R is a one-item vector.) If L is a character vector and R is character, then ∆ROWFIND is equivalent to 1∊L ⎕SS R (R∊L if R is a scalar). If R is a singleton, then ∆ROWFIND is equivalent to ∨/L=R. If L and R have the same nonzero width ((0∊⍴R)<(↑⌽⍴1/L)∊⍴,R), then ∆ROWFIND is equivalent to L^.=R. ∆ROWFIND can be arbitrarily faster than ∨/R⍷1/L because it stops when it finds a match in each row rather than processing the entire row. Typically, however, ∆ROWFIND is up to 15-45 times faster than the general expression, 4-7 times faster than ∨/L=R, and 1.1-5 times faster than L^.=R. CAUTION: ∆ROWFIND performs a distinctly different operation than ROWFIND from the 'ASMFNS' workspace supplied by APL2000 with APL+Win version 3.6.02; use MACfns' ∆ROWIOTA in place of ROWFIND. Errors: DOMAIN ERROR The left argument is neither character nor empty. LIMIT ERROR The last axis of the left argument is 0, but the product of the leading axes (×/¯1↓⍴L) exceeds 2,147,483,647. RANK ERROR The right argument is not a scalar or vector. VALENCE ERROR No left argument is supplied. Related functions: ∆ROWIOTA (table lookup), ∆STS (L ⎕SS R).

### Examples

⎕←M←3 9⍴'Ethel Arnold Mackenzie' Ethel Arnold Mackenzie M ∆ROWFIND'old' 0 1 0 M ∆ROWFIND'e' ⍝ ∨/M='e' 1 0 1 M ∆ROWFIND ⍬ 1 1 1 ↑⎕REPL[1]/⌽∆ROWFIND\('∆'⎕NL 3)'ROW' ⍝ ∆fns containing 'ROW' ∆ONEROW ∆ROWFIND ∆ROWIOTA ∆ROWMAT