From 558ce948ddee5fe233c985780cfdd5294901c41e Mon Sep 17 00:00:00 2001 From: Bart Jablonski Date: Sat, 11 Nov 2023 17:30:53 +0100 Subject: [PATCH] DFA package [ver. 0.5.7] DFA package [ver. 0.5.7] - Package regenerated with the latest version of SPF --- README.md | 2 +- dfa.md | 6 +- dfa.zip | Bin 48503 -> 48636 bytes hist/0.5.7/dfa.md | 1597 ++++++++++++++++++++++++++++++++++++++++++++ hist/0.5.7/dfa.zip | Bin 0 -> 48636 bytes 5 files changed, 1601 insertions(+), 4 deletions(-) create mode 100644 hist/0.5.7/dfa.md create mode 100644 hist/0.5.7/dfa.zip diff --git a/README.md b/README.md index 253133f..961a16a 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ a dynamically allocated array, a stack, a fifo queue, an ordered stack, and a pr Run `%helpPackage(DFA,createDFArray)` to find examples. -SHA256 digest for the latest version of `DFA`: F*09EA5201360922A91A9EEE72F4567792E9CFDFB591BA33419E2BF2B31D9B7C62 +SHA256 digest for the latest version of `DFA`: F*012375D87F66EB3A7BF5DDD0CC5AEE28851733EE33CC63231DF9045BEB958168 [**Documentation for DFA**](./dfa.md "Documentation for DFA") diff --git a/dfa.md b/dfa.md index 0ab0381..8a7d4f6 100644 --- a/dfa.md +++ b/dfa.md @@ -18,7 +18,7 @@ --- -# The DFA package [ver. 0.5.6] ############################################### +# The DFA package [ver. 0.5.7] ############################################### The **DFA** (a.k.a. *Dynamic Function Array*) package implements: - dynamic numeric and character arrays, @@ -52,10 +52,10 @@ Package contains: 12. exec generatearrays 13. clean generatearrays -*SAS package generated by generatePackage, version 20230905* +*SAS package generated by generatePackage, version 20231111* The SHA256 hash digest for package DFA: -`F*09EA5201360922A91A9EEE72F4567792E9CFDFB591BA33419E2BF2B31D9B7C62` +`F*012375D87F66EB3A7BF5DDD0CC5AEE28851733EE33CC63231DF9045BEB958168` --- # Content description ############################################################################################ diff --git a/dfa.zip b/dfa.zip index c189a62bfead338dde1676f6ceb42e13e7f086bf..657adca1e50615eead9b1a063f73fdc1ba6b7c20 100644 GIT binary patch delta 9629 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 delta 9468 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 USNWfATmyKxlLbDo`5%J+2iz>IasU7T diff --git a/hist/0.5.7/dfa.md b/hist/0.5.7/dfa.md new file mode 100644 index 0000000..8a7d4f6 --- /dev/null +++ b/hist/0.5.7/dfa.md @@ -0,0 +1,1597 @@ +- [The DFA package](#dfa-package) +- [Content description](#content-description) + * [`%createDFArray()` macro](#createdfarray-macro) + * [`%createDHArray()` macro](#createdharray-macro) + * [`%createDHFifo()` macro](#createdhfifo-macro) + * [`%createDHOrdStack()` macro](#createdhordstack-macro) + * [`%createDHPrtQueue()` macro](#createdhprtqueue-macro) + * [`%createDHStack()` macro](#createdhstack-macro) + * [`bit64orPROTOdfa()` proto function](#bit64orprotodfa-proto-function) + * [`bit64andPROTOdfa()` proto function](#bit64andprotodfa-proto-function) + * [`bit64orDFA()` subroutine](#bit64ordfa-function) + * [`bit64andDFA()` subroutine](#bit64anddfa-function) + * [`%createDFBitmap()` macro](#createdfbitmap-macro) + * [`generateArrays` exec](#createdhprtqueue-exec) + * [`generateArrays` clean](#createdhprtqueue-clean) + + * [License](#license) + +--- + +# The DFA package [ver. 0.5.7] ############################################### + +The **DFA** (a.k.a. *Dynamic Function Array*) package implements: + - dynamic numeric and character arrays, + - dynamic stacks (filo), + - dynamic queues (fifo), + - dynamic ordered stacks, + - priority queues, + - bitmap. + +The package provides a set of *macros*, +which allows to *generate* `call routines` +simulating data structures mentioned above. + +Few exemplary functions are also generated. +See particular macro help for further details. + +--- + +Package contains: +1. macro createdfarray +2. macro createdharray +3. macro createdhfifo +4. macro createdhordstack +5. macro createdhprtqueue +6. macro createdhstack +7. proto bit64andprotodfa +8. proto bit64orprotodfa +9. functions bit64anddfa +10. functions bit64ordfa +11. macro createdfbitmap +12. exec generatearrays +13. clean generatearrays + +*SAS package generated by generatePackage, version 20231111* + +The SHA256 hash digest for package DFA: +`F*012375D87F66EB3A7BF5DDD0CC5AEE28851733EE33CC63231DF9045BEB958168` + +--- +# Content description ############################################################################################ + +## >>> `%createDFArray()` macro: <<< ####################### + +The `%createDFArray()` macro allows to generate +a `dynamic function array` which is a FCMP based +approach to create *dynamically* allocated **numeric** +array with possible values searching and `WHICHN()` +function emulation. + +*Note:* Arrays provided by the macro are *one dimensional* arrays. + +### SYNTAX: ################################################################### + +The basic syntax is the following, the `<...>` means optional parameters: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%createDFArray( + arrayName + <,debug=0> + <,simple=0> + <,resizeFactor=0> + <,outlib=work.DFAfcmp.package> + <,hashexp=13> + <,header=1> +) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**Arguments description**: + +1. `arrayName` - *Required*, creates a FCMP call subroutine which is also + an array name. In the data step it is used in form of + a call subroutine, e.g. `call arrayName("Allocate", -3, 3)`. + Has to satisfy FCMP function naming requirements, but with + maximum of 24 characters. + +* `debug=` - *Optional*, the default value is `0`. + If set to `1` then it turns on a debugging mode. + +* `simple=` - *Optional*, the default value is `0`. A *simple* dynamic + function array is one which is not searchable and does not + allows to use `which()` functionality. + If set to `1` then it disables `SEARCH` and `WHICH` functionality. + See examples below for details. + +* `resizeFactor=` - *Optional*, the default value is `0`. If set to `0` then + the dynamic array size is not changeable(mutable) after initial + size allocation. + If set not to `0` then arrays dimensions are mutable after allocation, + i.e. even if an array is allocated for ten elements (like `A[1:10]`) + you can do `A[17] = 42` and it will resize itself dynamically. + *Hint!* Set to, e.g. 4999, for faster allocation process. + See examples below for details. + +* `outlib=` - *Optional*, the default value is `work.DFAfcmp.package`. + It points the default location for new generated dynamic + function arrays compiled by FCMP. + *Hint!* Keep it as it is. + +* `hashexp=` - *Optional*, the default value is `13`. It is the default `hashexp=` + value for internal hash table used by the function. + +* `header=` - *Optional*, the default value is `1`. Indicates if + the `proc fcmp outlib = &outlib.;` header is added to + the executed code. If not 1 then no header is added. + +**Created function arguments description**: + +A function generated by the macro is: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +call &arrayName.(IO, position, value) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +and accepts the following list of arguments and values: + +1. `IO` - is a *character* steering argument, possible + values and behaviour they call are the following: + - `O`, `Output`, `R`, `Return` - to get the data from an array, + - `I`, `Input` - to insert the data into an array, + - `+`, `Add` - to increment given position by a value, + - `C`, `Clear` - to reduce an array to a single empty cell, + - `A`, `Allocate` - to reserve space for array width and set starting values, + - `D`, `Dimension` - to return minimal and maximal index of an array, + - `F`, `Find`, `Exist` - to find out if a given value exist in an array, + - `W`, `Which` - to search the first position of data in array, `WHICHN()` function emulator, + - `Sum` - to return the sum of non-missing elements of an array, + - `Nonmiss` - to return the number of non-missing elements of an array, + - `Avg`, `Mean`, `Average` - to return the average of non-missing elements of an array, + - `Min`, `Minimum` - to return the minimum of non-missing elements of an array, + - `Max`, `Maximum` - to return the maximum of non-missing elements of an array. + +2. `position` - is a *numeric* argument and depends on the `IO` value. + Behaves in the following way: + - for `O`, `Output`, `R`, `Return`/ `I`, `Input`/ `+`, `Add` it takes + an arrays index from (into) which data is get (put), + - for `C`, `Clear` is ignored, + - for `A`, `Allocate` sets the value of the minposition, i.e. the minimal position of the array index, + - for `D`, `Dimension` it returns value of the minposition, + - for `Sum`, `Nonmiss`, `Avg`, `Mean`, `Average`, `Min`, `Minimum`, `Max`, and `Maximum` is ignored, + - for `F`, `Find`, `Exist` it returns number of occurrences of a given value in an array, + - for `W`, `Which` it returns position the first occurrence of a given value in an array. + +.3 `value` - is a *numeric* argument and depends on the `IO` value. + Behaves in the following way: + - for `O`, `Output`, `R`, `Return` it holds value retrieved from an array on a given position, + - for `I`, `Input` it holds the value inserted into an array on a given position, + - for `+`, `Add` it holds the value that is used to increment an array value at a given position, + - for `C`, `Clear` is ignored, + - for `A`, `Allocate` it sets the value of the maxposition, i.e. maximal position of the array index, + - for `D`, `Dimension` it returns value of the maxposition + - for `Sum`, `Nonmiss`, `Avg`, `Mean`, `Average`, `Min`, `Minimum`, `Max`, and `Maximum` it returns + the calculated summary value, + - for `F`, `Find`, `Exist`, `W`, `Which` is the value to be searched in an array. + +The `position` and the `value` arguments are **outargs**, i.e. can be changed by the function. + +### EXAMPLES AND USECASES: #################################################### + +**EXAMPLE 1.** Dynamic, Searchable, and Immutable array: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %createDFArray(ArrDSI); + options APPEND=(cmplib = WORK.DFAfcmp) ; + + data Example1; + call ArrDSI("Allocate", 1, 10); + L = 0; H = 0; + call ArrDSI("Dim", L, H); + put L= H=; + + * populate array with data ; + do i = L to H; + call ArrDSI("Input", i, i**2); + end; + + * searchability allows to find number of occurrences of value in the array ; + F = .; + call ArrDSI("Find", F, 16); + put "Value 16 occurs " F "times"; + call ArrDSI("Find", F, 17); + put "Value 17 occurs " F "times"; + + * increase value of cell 4 by 1, and verify at WHICH position is 17 (by searchability); + call ArrDSI("+", 4, 1); + call ArrDSI("Which", F, 17); + put "Value 17 occurred for the first time at position " F; + + * get values from the array ; + Value = .; + do i = L to H; + call ArrDSI("Output", i, Value); + put i= Value=; + end; + + * some basic statistics ; + call ArrDSI("Sum", ., STAT); put "sum = " STAT; + call ArrDSI("Avg", ., STAT); put "avg = " STAT; + call ArrDSI("Min", ., STAT); put "min = " STAT; + call ArrDSI("Max", ., STAT); put "max = " STAT; + call ArrDSI("Cnt", ., STAT); put "cnt = " STAT; + + * immutability does _not_ allow to increase dimensions automatically; + * this line returns an error ; + call ArrDSI("Input", 42, -1); + run; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 2.** Dynamic, Searchable, and Mutable array: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %createDFArray(ArrDSM, resizefactor=17); + options APPEND=(cmplib = WORK.DFAfcmp) ; + + data Example2; + call ArrDSM("Allocate", -2, 2); + + do i = -2 to 2; + call ArrDSM("Input", i, 2**i); + end; + + L = .; H = .; + call ArrDSM("Dim", L, H); + put L= H=; + + * mutability allows to increase dimensions automatically + * create index 3 and -3; + call ArrDSM("+", 3, 8); + call ArrDSM("+",-3, 0.125); + call ArrDSM("Dim", L, H); + put L= H=; + + Value = .; + do i = L to H; + call ArrDSM("O", i, Value); + put i= Value=; + end; + + run; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 3.** Dynamic, non-searchable (a.k.a. SiMPle), and Immutable array: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %createDFArray(ArrDSMPLI, simple=1); + options APPEND=(cmplib = WORK.DFAfcmp) ; + + data Example3; + call ArrDSMPLI("Allocate", -2, 2); + + do i = -2 to 2; + call ArrDSMPLI("Input", i, 2**i); + end; + + * non-searchable array (a.k.a. simple) does not allow ; + * to find number of occurrences of value in the array ; + * and verify what is the first position of a value ; + * this lines return a warning ; + call ArrDSMPLI("Exist", i, 1); + call ArrDSMPLI("Which", i, 1); + run; + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 4.** Dynamic, non-searchable (a.k.a. SiMPle), and Mutable array: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %createDFArray(ArrDSMPLM, simple=1, resizefactor=42); + options APPEND=(cmplib = WORK.DFAfcmp) ; + + data Example4; + call ArrDSMPLM("Allocate", 1, 1); + + * mutability allows to increase dimensions automatically ; + do i = -12 to 12; + call ArrDSMPLM("Input", i, i*2); + end; + + * non-searchable array (a.k.a. simple) does not allow ; + * to find number of occurrences of value in the array ; + * and verify what is the first position of a value ; + * this lines return a warning ; + i = .; + call ArrDSMPLM("Exist", i, -24); + put "Exist " i=; + call ArrDSMPLM("Which", i, 24); + put "Which " i=; + run; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +--- +## >>> `%createDHArray()` macro: <<< ####################### + +The `%createDHArray()` macro allows to generate +a `dynamic hash array` which is a FCMP based approach +to create *dynamically* allocated **numeric** +or **character** array + +*Note:* Arrays provided by the macro are *one dimensional* arrays. + +### SYNTAX: ################################################################### + +The basic syntax is the following, the `<...>` means optional parameters: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%createDHArray( + arrayName + <,debug=0> + <,type=8> + <,outlib=work.DFAfcmp.package> + <,hashexp=13> + <,header=1> +) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**Arguments description**: + +1. `arrayName` - *Required*, creates a FCMP call subroutine which is also + an array name. In the data step it is used in form of + a call subroutine, e.g. `call arrayName("Allocate", -3, 3)`. + Has to satisfy FCMP function naming requirements, but with + maximum of 24 characters. + +* `debug=` - *Optional*, the default value is `0`. + If set to `1` then it turns on a debugging mode. + +* `type=` - *Optional*, the default value is `8`. + Indicates what *type* (numeric/character) and *length* + are data portion of generated array. Should be in line + with the LENGTH statement, e.g. `8`, `$ 30`, etc. + Determines if the `value` argument is numeric or character. + +* `outlib=` - *Optional*, the default value is `work.DFAfcmp.package`. + It points the default location for new generated dynamic + function arrays compiled by FCMP. + *Hint!* Keep it as it is. + +* `hashexp=` - *Optional*, the default value is `13`. It is the default `hashexp=` + value for internal hash table used by the function. + +* `header=` - *Optional*, the default value is `1`. Indicates if + the `proc fcmp outlib = &outlib.;` header is added to + the executed code. If not 1 then no header is added. + +**Created function arguments description**: + +A function generated by the macro is: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +call &arrayName.(IO, position, value) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +and accepts the following list of arguments and values: + +1. `IO` - is a *character* steering argument, possible + values and behaviour they call are the following: + - `O`, `Output`, `R`, `Return` - to get the data from an array, + - `I`, `Input` - to insert the data into an array, + - `C`, `Clear` - to reduce an array to a single empty cell, + - `L`, `Low`, `Lower`, `Lbound` - to return minimal position of index, + - `H`, `High`, `Higher`, `Hbound` - to return maximal position of index. + +2. `position` - is a *numeric* argument and depends on the `IO` value. + Behaves in the following way: + - for `O`, `Output`, `R`, `Return`/ `I`, and `Input` it is an array + index from (into) which data is get (put), + - for `C` it is ignored, + - for `L`, `Low`, `Lower`, and `Lbound` it returns the first position of an index, + - for `H`, `High`, `Higher`, and `Hbound` it returns the last position of an index, + - otherwise is not modified. + +3. `value` - is a *numeric* or *character* argument (determined by the `type=`) + and depends on the `IO` value. Behaves in the following way: + - for `O`, `Output`, `R`, and `Return` it holds value retrieved from an array from a given position, + - for `I`, `Input` it holds the value inserted into an array into a given position, + - for `C` is ignored, + - for `L`, `Low`, `Lower`, and `Lbound` returns first value of index, + - for `H`, `High`, `Higher`, and `Hbound` returns last value of index, + - otherwise is not modified. + +The `position` and the `value` arguments are **outargs**, i.e. can be changed by the function. + +### EXAMPLES AND USECASES: #################################################### + +**EXAMPLE 1.** Dynamic, Hash-based, and Character array: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %createDHArray(ArrDHC, type = $ 12); + options APPEND=(cmplib = WORK.DFAfcmp) ; + + %let zeros = 6; *[to test bigger sizes]; + data Example1; + + t = time(); + do _I_ = -1e&zeros. to 1e&zeros.; + _X_ = put(_I_*10, z12.); + call ArrDHC("Input", _I_, _X_); + end; + t = time() - t; + put t= / _X_= /; + + * get the size info ; + LB = 0; HB = 0; + drop LB HB; + call ArrDHC('Lbound', LB, _X_); + call ArrDHC('Hbound', HB, _X_); + put LB= HB= /; + + t = time(); + do _I_ = HB + 1 to LB - 1 by -1; + call ArrDHC('Output', _I_, _X_); + output; + end; + t = time() - t; + put t= / _X_= /; + + * clear for further reuse ; + call ArrDHC('C', ., ''); + + run; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 2.** Dynamic, Hash-based, and Numeric array: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %createDHArray(ArrDHN); + options APPEND=(cmplib = WORK.DFAfcmp) ; + + data Example2; + + do i = -2 to 2; + call ArrDHN("Input", i, 2**i); + end; + + do i = -2 to 2; + call ArrDHN("+", i, -10); + end; + + v = .; + do i = -2 to 2; + call ArrDHN("Output", i, v); + put i= v=; + end; + + run; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +--- +## >>> `%createDHFifo()` macro: <<< ####################### + +The `%createDHFifo()` macro allows to generate +a `dynamic hash fifo` which is a FCMP based approach +to create dynamically allocated numeric or character +"first in first out" [queue](https://en.wikipedia.org/wiki/FIFO_(computing_and_electronics)) + +Interesting reading about implementing a fifo via hash table +can be found in *chapter 10.4* of the: +*"Data Management Solutions Using SAS Hash Table Operations: + A Business Intelligence Case Study"* book +by Paul Dorfman and Don Henderson. + +### SYNTAX: ################################################################### + +The basic syntax is the following, the `<...>` means optional parameters: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%createDHFifo( + fifoName + <,debug=0> + <,type=8> + <,outlib=work.DFAfcmp.package> + <,hashexp=13> + <,header=1> +) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**Arguments description**: + +1. `fifoName` - *Required*, creates a FCMP call subroutine which is also + a fifo name. In the data step it is used in form of + a call subroutine, e.g. `call fifoName("Enqueue", 3)`. + Has to satisfy FCMP function naming requirements, but with + maximum of 24 characters. + +* `debug=` - *Optional*, the default value is `0`. + If set to `1` then it turns on a debugging mode. + +* `type=` - *Optional*, the default value is `8`. + Indicates what *type* (numeric/character) and *length* + are data portion of generated array. Should be in line + with the LENGTH statement, e.g. `8`, `$ 30`, etc. + Determines if the `value` argument is numeric or character. + +* `outlib=` - *Optional*, the default value is `work.DFAfcmp.package`. + It points the default location for new generated dynamic + function arrays compiled by FCMP. + *Hint!* Keep it as it is. + +* `hashexp=` - *Optional*, the default value is `13`. It is the default `hashexp=` + value for internal hash table used by the function. + +* `header=` - *Optional*, the default value is `1`. Indicates if + the `proc fcmp outlib = &outlib.;` header is added to + the executed code. If not 1 then no header is added. + +**Created function arguments description**: + +A function generated by the macro is: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +call &fifoName.(IO, value) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +and accepts the following list of arguments and values: + +1. `IO` - is a *character* steering argument, possible + values and behaviour they call are the following: + - `O`, `Output`, `D`, `Dequeue`, `R`, `Return` - to get the data from a fifo (and remove it from the fifo) + - `I`, `Input`, `E`, `Enqueue`, and `Insert` - to insert the data into a fifo + - `C`, `Clear` - to reduce a fifo to an empty one + - `P`, `Peek`, `T`, and `Tail` - to peek the data from a fifo (and NOT remove it from the fifo) + - `H`, `Head` - to peek the data from a fifo head (and NOT remove it from the fifo) + - `Sum` - returns sum of nonmissing numeric elements of a stack + - `Avg`, `Mean`, `Average` - returns average of nonmissing numeric elements of a stack + - `Nonmiss`, `Cnt` - returns number of nonmissing elements of a stack + - `Height` - returns height a stack + +2. `value` - is a *numeric* or *character* argument (determined by the `type=`) + and depends on the `IO` value. Behaves in the following way: + - for `O`, `Output`, `D`, `Dequeue`, `R`, `Return` it holds the value popped from the fifo, + - for `I`, `Input`, `E`, `Enqueue`, `Insert` it holds the value to be pushed into the fifo, + - for `C`, `Clear` it is ignored, + - for `P`, `Peek` holds the value peeked from the fifo, + - for `Sum`, `Nonmiss`, `Cnt`, `Avg`, `Mean`, `Average`, and `Height` it returns calculated summary value. + +The `value` argument is **outarg**, i.e. can be changed by the function. + + +### EXAMPLES AND USECASES: #################################################### + +**EXAMPLE 1.** Dynamic, Hash-based, and Character fifo: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %createDHFifo(FifoDHC, type = $ 12); + options APPEND=(cmplib = WORK.DFAfcmp) ; + + + %let zeros = 6; *[to test bigger sizes]; + data Example1; + + t = time(); drop t; + do _I_ = 1 to 1e&zeros.; + _X_ = put(_I_*10, z12.); + call FifoDHC("Enqueue", _X_); + end; + t = time() - t; + + call FifoDHC("Height", _X_); + put t= / _X_=; + + t = time(); + do _I_ = 1 to 1e&zeros. + 3; + call FifoDHC('Dequeue', _X_); + output; + end; + t = time() - t; + + call FifoDHC("Height", _X_); + put t= / _X_=; + + %* clear for further reuse *; + call FifoDHC('Clear', ''); + + run; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 2.** Dynamic, Hash-based, and Numeric fifo: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %createDHFifo(FifoDHN); + options APPEND=(cmplib = WORK.DFAfcmp) ; + + data Example2; + + do _I_ = 1,.,2,.,3,.,4,.,5,.,6; + call FifoDHN("E", _I_); + end; + + call FifoDHN("Sum", _I_); + put "Sum " _I_=; + + call FifoDHN("Avg", _I_); + put "Avg " _I_=; + + call FifoDHN("Cnt", _I_); + put "Cnt " _I_=; + + call FifoDHN("Height", _I_); + put "Height " _I_=; + + call FifoDHN("Tail", _I_); + put "Tail of fifo is " _I_=; + + call FifoDHN("Height", _I_); + put "Height after Tail " _I_=; + + call FifoDHN("Head", _I_); + put "Head of fifo is " _I_=; + + call FifoDHN("Height", _I_); + put "Height after Head" _I_=; + + _X_ = 0; + do _I_ = 1 to _I_; + call FifoDHN('D', _X_); + output; + end; + + call FifoDHN("Height", _I_); + put "Height " _I_=; + + run; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +--- +## >>> `%createDHOrdStack()` macro: <<< ####################### + +The `%createDHOrdStack()` macro allows to generate +a `dynamic ORDERED hash stack` which is a FCMP based approach +to create dynamically allocated numeric or character +*ordered* [stack](https://en.wikipedia.org/wiki/Stack_(abstract_data_type)) + +Interesting reading about implementing a stack via hash table +can be found in *chapter 10.4* of the: +*"Data Management Solutions Using SAS Hash Table Operations: + A Business Intelligence Case Study"* book +by Paul Dorfman and Don Henderson. + +### SYNTAX: ################################################################### + +The basic syntax is the following, the `<...>` means optional parameters: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%createDHOrdStack( + fifoName + <,debug=0> + <,type=8> + <,order=A> + <,outlib=work.DFAfcmp.package> + <,hashexp=13> + <,header=1> +) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**Arguments description**: + +1. `stackName` - *Required*, creates a FCMP call subroutine which is also + a stack name. In the data step it is used in form of + a call subroutine, e.g. `call stackName("Push", 3)`. + Has to satisfy FCMP function naming requirements, but with + maximum of 24 characters. + +* `debug=` - *Optional*, the default value is `0`. + If set to `1` then it turns on a debugging mode. + +* `type=` - *Optional*, the default value is `8`. + Indicates what *type* (numeric/character) and *length* + are data portion of generated array. Should be in line + with the LENGTH statement, e.g. `8`, `$ 30`, etc. + Determines if the `value` argument is numeric or character. + +* `order=` - *Optional*, the default value is `A`. + Indicates a method of ordering of the stack, + allowed values are: `A` for ascending and `D` for descending. + +* `outlib=` - *Optional*, the default value is `work.DFAfcmp.package`. + It points the default location for new generated dynamic + function arrays compiled by FCMP. + *Hint!* Keep it as it is. + +* `hashexp=` - *Optional*, the default value is `13`. It is the default `hashexp=` + value for internal hash table used by the function. + +* `header=` - *Optional*, the default value is `1`. Indicates if + the `proc fcmp outlib = &outlib.;` header is added to + the executed code. If not 1 then no header is added. + +**Created function arguments description**: + +A function generated by the macro is: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +call &stackName.(IO, value) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +and accepts the following list of arguments and values: + +1. `IO` - is a *character* steering argument, possible + values and behaviour they call are the following: + - `O`, `Output`, `Pop`, `G`, `Get`, `R`, `Return` - to get the data from a stack (and remove it from the top), + - `I`, `Input`, `Push`, `Put`, `Insert` - to insert the data into a stack, + - `C`, `Clear` - to reduce a stack to an empty one, + - `P`, `Peek` - to peek the data from a stack (and NOT remove it from the top), + - `Sum` - returns sum of non-missing numeric elements of a stack, + - `Avg`, `Mean`, `Average` - returns average of non-missing numeric elements of a stack, + - `Nonmiss`, `Cnt`, `Nnm` - returns number of non-missing elements of a stack, + - `Height` - returns height a stack, + - `Min`, `Minimum` - returns minimum of non-missing elements of a stack, + - `Max`, `Maximum` - returns maximum of non-missing elements of a stack. + +2. `value` - is a *numeric* or *character* argument (determined by the `type=`) + and depends on the `IO` value. Behaves in the following way: + - for `O`, `Output`, `Pop`, `G`, `Get`, `R`, `Return` it holds a value popped from a stack, + - for `I`, `Input`, `Push`, `Put`, `Insert` it holds a value to be pushed into a stack, + - for `C`, `Clear` it is ignored, + - for `P`, `Peek` it holds a value peeked from a stack, + - for `Sum`, `Nonmiss`, `Cnt`, `Avg`, `Mean`, `Average`, `Height`, `Min`, `Minimum`, `Max`, and `Maximum` + it returns calculated summary value, + +The `value` argument is **outarg**, i.e. can be changed by the function. + + +### EXAMPLES AND USECASES: #################################################### + +**EXAMPLE 1.** Dynamic, Hash-based, and Character Descending Ordered stack: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %createDHOrdStack(DescStackC, type = $ 12, order=D); + options APPEND=(cmplib = WORK.DFAfcmp) ; + + data Example1; + + do _X_ = "A","B"," ","C","A"," ","B","C"; + call DescStackC("Push", _X_); + end; + + length S $ 12; + call DescStackC('Height', S); + put 'Height ' S; + + do until(strip(S) = "0"); + call DescStackC('Get', _X_); + call DescStackC('Height', S); + put S= _X_=; + output; + end; + + %* clear for further reuse *; + call DescStackC('Clear',''); + + run; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 2.** Dynamic, Hash-based, and Numeric Ascending Ordered stack: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %createDHOrdStack(DescStackN, order=A); + options APPEND=(cmplib = WORK.DFAfcmp) ; + + data Example2; + + call missing(Sum, Avg, Min, Max, Cnt, Hgt, Peek); + do _X_ = 1,6,2,.,5,3,4; + call DescStackN("Put", _X_); + call DescStackN('Sum', Sum); + call DescStackN('Avg', Avg); + call DescStackN('Min', Min); + call DescStackN('Max', Max); + call DescStackN('Cnt', Cnt); + call DescStackN('Height', Hgt); + put (_ALL_) (=); + end; + + call DescStackN('Peek', Peek); + put Peek=; + + do _I_ = 1 to Hgt; + call DescStackN('Output', _X_); + keep _X_; + if _X_ > .z then output; + end; + + call DescStackN('Peek', Peek); + put Peek=; + + %* clear for further reuse *; + call DescStackN('Clear',.); + + run; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +--- +## >>> `%createDHPrtQueue()` macro: <<< ####################### + + +The `%createDHPrtQueue()` macro allows to generate +a `dynamic PRIORITY hash queue` which is a FCMP based approach +to create dynamically allocated numeric or character +[priority queue](https://en.wikipedia.org/wiki/Priority_queue) + +### SYNTAX: ################################################################### + +The basic syntax is the following, the `<...>` means optional parameters: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%createDHPrtQueue( + fifoName + <,debug=0> + <,type=8> + <,newOnTop=+> + <,outlib=work.DFAfcmp.package> + <,hashexp=13> + <,header=1> +) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**Arguments description**: + +1. `queueName` - *Required*, creates a FCMP call subroutine which is also + a queue name. In the data step it is used in form of + a call subroutine, e.g. `call queueName("Bottom", 1, 3)`. + Has to satisfy FCMP function naming requirements, but with + maximum of 24 characters. + +* `debug=` - *Optional*, the default value is `0`. + If set to `1` then it turns on a debugging mode. + +* `type=` - *Optional*, the default value is `8`. + Indicates what *type* (numeric/character) and *length* + are data portion of generated array. Should be in line + with the LENGTH statement, e.g. `8`, `$ 30`, etc. + Determines if the `value` argument is numeric or character. + +* `newOnTop=` - *Optional*, the default value is `+`. + Indicates how to keep order in the same priority group, + allowed values are `+` or `-`. Plus(`+`) sets new elements + at the top of the group, minus(`-`) at the bottom. + +* `outlib=` - *Optional*, the default value is `work.DFAfcmp.package`. + It points the default location for new generated dynamic + function arrays compiled by FCMP. + *Hint!* Keep it as it is. + +* `hashexp=` - *Optional*, the default value is `13`. It is the default `hashexp=` + value for internal hash table used by the function. + +* `header=` - *Optional*, the default value is `1`. Indicates if + the `proc fcmp outlib = &outlib.;` header is added to + the executed code. If not 1 then no header is added. + +**Created function arguments description**: + +A function generated by the macro is: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +call &queueName.(IO, position, value) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +and accepts the following list of arguments and values: + +1. `IO` - is a *character* steering argument, possible + values and behaviour they call are the following: + - `O`, `Output`, `D`, `Dequeue`, `R`, `Return` - it pops/gets/outputs the data from the queue head (high priority), + - `B`, `Bottom` - it pops/gets/outputs the data from the queue tail (low priority), + - `I`, `Input`, `E`, `Enqueue`, `Insert` - it push/puts/inserts the data into the queue, + - `C`, `Clear` - it reduces a queue to an empty one, + - `H`, `Head` - it peeks the data from the queue head and NOT removes it, + - `T`, `Tail` - it peeks the data from the queue tail and NOT removes it, + - `Sum` - it returns sum of non-missing *numeric* elements of the queue, + - `Avg`, `Mean`, `Average` - it returns average of non-missing *numeric* elements of the queue, + - `Nonmiss`, `Cnt` - it returns number of non-missing elements of the queue, + - `Height` - it returns height of the queue. + +2. `position` - is a *numeric* argument and depends on the `IO` value. + Behaves in the following way: + - for `O`, `Output`, `D`, `Dequeue`, `R`, `Return` and `B`, `Bottom`, or `H`, `Head`, `T`, `Tail` + it holds a priority level of value popped from the queue, + - for `I`, `Input`, `E`, `Enqueue`, `Insert` it holds a priority level of value to be pushed into the queue, + - for `C` ignored, + - for *numeric* queue and `Sum`, `Nonmiss`, `Cnt`, `Avg`, `Mean`, `Average`, `Height` returns calculated summary value. + +3. `value` - is a *numeric* or *character* argument (determined by the `type=`) + and depends on the `IO` value. Behaves in the following way: + - for `O`, `Output`, `D`, `Dequeue`, `R`, `Return` and `B`, `Bottom` or `H`, `Head`, `T`, `Tail` + it holds a value popped from the queue, + - for `I`, `Input`, `E`, `Enqueue`, `Insert` it holds a value to be pushed into the queue, + - for `C` ignored, + - for *numeric* queue and `Sum`, `Nonmiss`, `Cnt`, `Avg`, `Mean`, `Average`, `Height` returns calculated summary value, + - otherwise does not modify value. + +The `position` and the `value` arguments are **outargs**, i.e. can be changed by the function. + + +### EXAMPLES AND USECASES: #################################################### + +**EXAMPLE 1.** Dynamic, Hash-based, and Character Priority queue: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %createDHPrtQueue(PriorityQueuePC, type = $ 12, newOnTop=+); + %createDHPrtQueue(PriorityQueueNC, type = $ 12, newOnTop=-); + options APPEND=(cmplib = WORK.DFAfcmp) ; + + data Example1; + + _I_ = .; + length _X_ _Y_ $ 3; + do _X_ = "AAA","BBB","CCC","AA","BB","CC","A","B","C"; + _I_ + 1; + call PriorityQueuePC("I", mod(_I_, 3), _X_); + call PriorityQueueNC("I", mod(_I_, 3), _X_); + end; + + Height = .; + call PriorityQueuePC('Height', Height, ''); + put Height=; + + do until(Height = 0); + call PriorityQueuePC('Dequeue', _I_, _X_); + call PriorityQueueNC("Dequeue", _I_, _Y_); + call PriorityQueueNC('Height', Height, ''); + put (_ALL_) (=); + output; + end; + + run; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 2.** Dynamic, Hash-based, and Numeric Priority queue: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %createDHPrtQueue(PriorityQueueN); + options APPEND=(cmplib = WORK.DFAfcmp) ; + + data Example2; + + do _X_ = -5 to 5; + call PriorityQueueN("Enqueue", abs(_X_), _X_); + end; + + call missing(Sum, Avg, Cnt, Hgt); + call PriorityQueueN('Sum', ., Sum); + call PriorityQueueN('Avg', ., Avg); + call PriorityQueueN('Cnt', ., Cnt); + call PriorityQueueN('Height', ., Hgt); + put (_ALL_) (=); + + do _N_ = 1 to Hgt; + call PriorityQueueN("Dequeue", _X_, _Y_); + put _X_= _Y_=; + end; + + run; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +--- +## >>> `%createDHStack()` macro: <<< ####################### + +The `%createDHStack()` macro allows to generate +a `dynamic hash stack` which is a FCMP based approach +to create dynamically allocated numeric or character +[stack](https://en.wikipedia.org/wiki/Stack_(abstract_data_type)) + +Interesting reading about implementing a stack via hash table +can be found in *chapter 10.4* of the: +*"Data Management Solutions Using SAS Hash Table Operations: + A Business Intelligence Case Study"* book +by Paul Dorfman and Don Henderson. + +### SYNTAX: ################################################################### + +The basic syntax is the following, the `<...>` means optional parameters: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%createDHStack( + fifoName + <,debug=0> + <,type=8> + <,outlib=work.DFAfcmp.package> + <,hashexp=13> + <,header=1> +) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**Arguments description**: + +1. `stackName` - *Required*, creates a FCMP call subroutine which is also + a stack name. In the data step it is used in form of + a call subroutine, e.g. `call stackName("Push", 3)`. + Has to satisfy FCMP function naming requirements, but with + maximum of 24 characters. + +* `debug=` - *Optional*, the default value is `0`. + If set to `1` then it turns on a debugging mode. + +* `type=` - *Optional*, the default value is `8`. + Indicates what *type* (numeric/character) and *length* + are data portion of generated array. Should be in line + with the LENGTH statement, e.g. `8`, `$ 30`, etc. + Determines if the `value` argument is numeric or character. + +* `outlib=` - *Optional*, the default value is `work.DFAfcmp.package`. + It points the default location for new generated dynamic + function arrays compiled by FCMP. + *Hint!* Keep it as it is. + +* `hashexp=` - *Optional*, the default value is `13`. It is the default `hashexp=` + value for internal hash table used by the function. + +* `header=` - *Optional*, the default value is `1`. Indicates if + the `proc fcmp outlib = &outlib.;` header is added to + the executed code. If not 1 then no header is added. + +**Created function arguments description**: + +A function generated by the macro is: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +call &stackName.(IO, value) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +and accepts the following list of arguments and values: + +1. `IO` - is a *character* steering argument, possible + values and behaviour they call are the following: + - `O`, `Output`, `Pop`, `G`, `Get`, `R`, `Return` - to get the data from a stack (and remove it from the top), + - `I`, `Input`, `Push`, `Put`, `Insert` - to insert the data into a stack, + - `C`, `Clear` - to reduce a stack to an empty one, + - `P`, `Peek` - to peek the data from a stack (and NOT remove it from the top), + - `Sum` - returns sum of non-missing numeric elements of a stack, + - `Avg`, `Mean`, `Average` - returns average of non-missing numeric elements of a stack, + - `Nonmiss`, `Cnt`, `Nnm` - returns number of non-missing elements of a stack, + - `Height` - returns height a stack, + +2. `value` - is a *numeric* or *character* argument (determined by the `type=`) + and depends on the `IO` value. Behaves in the following way: + - for `O`, `Output`, `Pop`, `G`, `Get`, `R`, `Return` it holds a value popped from a stack, + - for `I`, `Input`, `Push`, `Put`, `Insert` it holds a value to be pushed into a stack, + - for `C`, `Clear` it is ignored, + - for `P`, `Peek` it holds a value peeked from a stack, + - for `Sum`, `Nonmiss`, `Cnt`, `Avg`, `Mean`, `Average`, `Height` it returns calculated summary value, + +The `value` argument is **outarg**, i.e. can be changed by the function. + + +### EXAMPLES AND USECASES: #################################################### + +**EXAMPLE 1.** Dynamic, Hash-based, and Character stack: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %createDHStack(StackDHC, type = $ 12); + options APPEND=(cmplib = WORK.DFAfcmp) ; + + + %let zeros = 6; *[to test bigger sizes]; + data Example1; + + t = time(); drop t; + do _I_ = 1 to 1e&zeros.; + _X_ = put(_I_*10, z12.); + call StackDHC("Put", _X_); + end; + t = time() - t; + + call StackDHC("Height", _X_); + put t= / _X_=; + + t = time(); + do _I_ = 1 to 1e&zeros. + 3; + call StackDHC('Pop', _X_); + output; + end; + t = time() - t; + + call StackDHC("Height", _X_); + put t= / _X_=; + + %* clear for further reuse *; + call StackDHC('Clear', ''); + + run; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 2.** Dynamic, Hash-based, and Numeric stack: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %createDHStack(StackDHN); + options APPEND=(cmplib = WORK.DFAfcmp) ; + + data Example2; + + do _I_ = 1,.,2,.,3,.,4,.,5,.,6; + call StackDHN("Put", _I_); + end; + + call StackDHN("Sum", _I_); + put "Sum " _I_=; + + call StackDHN("Avg", _I_); + put "Avg " _I_=; + + call StackDHN("Cnt", _I_); + put "Cnt " _I_=; + + call StackDHN("Height", _I_); + put "Height " _I_=; + + _X_ = 0; + do _I_ = 1 to _I_; + call StackDHN('Pop', _X_); + output; + end; + + call StackDHN("Height", _I_); + put "Height " _I_=; + + run; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +--- + +## >>> `bit64orPROTOdfa()` proto function: <<< ####################### + +The **bit64orPROTOdfa()** is external *C* function, +this is the implementation of the *bitwise OR* operation +on doubles. A double is returned. + +**Caution!** For SAS numeric values *only* operations on first 53 bits are valid! + +The function is used **internally** by functions in the *DFA* package. + +### SYNTAX: ################################################################### + +The basic syntax is the following: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +bit64orPROTOdfa(i, j) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**Arguments description**: + +1. `i` - A double numeric argument. + +2. `j` - A double numeric argument. + +--- + +## >>> `bit64andPROTOdfa()` proto function: <<< ####################### + +The **bit64andPROTOdfa()** is external *C* function, +this is the implementation of the *bitwise AND* operation +on doubles. A double is returned. + +**Caution!** For SAS numeric values *only* operations on first 53 bits are valid! + +The function is used **internally** by functions in the *DFA* package. + +### SYNTAX: ################################################################### + +The basic syntax is the following: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +bit64andPROTOdfa(i, j) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**Arguments description**: + +1. `i` - A double numeric argument. + +2. `j` - A double numeric argument. + +--- + +## >>> `bit64orDFA()` subroutine: <<< ####################### + +The **bit64orDFA()** function is an alternative to +the 32 bit bitwise `BOR()` function working on SAS numerics. +Allows to work on *up to* 53 bits of SAS numeric value. + +The `bit64orDFA()` is an *internal* function of the `DFA` package. + +### SYNTAX: ################################################################### + +The basic syntax is the following, the `<...>` means optional parameters: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +bit64orDFA(a, b) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**Arguments description**: + +1. `a` - Argument is a SAS numeric values. + +2. `B` - Argument is a SAS numeric values. + +### EXAMPLES AND USECASES: #################################################### + +**EXAMPLE 1.** Basic test of `bit64orDFA()` and `bit64andDFA()` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + options ls = max ps = max; + %let M = 53 ; %* 53 is maximum valid value; + data _null_; + array bitmask [ 0: &M] _temporary_ ; + do P = 1 to &M ; + bitmask[P] = 2**(P-1) ; + put bitmask[P] = binary54. @; + put bitmask[P] = best32.; + end ; + bitmask[0] = bitmask[&M.] ; + put bitmask[0] = best32. /; + + a=0; + put a = binary54.; + do P = 1 to &M ; + a = BIT64ORDFA (a, bitmask[P]) ; + put a = binary54.; + end; + put; + + b = 0; + put b = binary54./; + do P = 1 to &M ; + b + (BIT64ANDDFA (a, bitmask[P]) ne .) ; + put b = best32.; + end; + run; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +--- + +## >>> `bit64andDFA()` subroutine: <<< ####################### + +The **bit64andDFA()** function is an alternative to +the 32 bit bitwise `BAND()` function working on SAS numerics. +Allows to work on *up to* 53 bits of SAS numeric value. + +The `bit64andDFA()` is an *internal* function of the `DFA` package. + +### SYNTAX: ################################################################### + +The basic syntax is the following, the `<...>` means optional parameters: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +bit64andDFA(a, b) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**Arguments description**: + +1. `a` - Argument is a SAS numeric values. + +2. `B` - Argument is a SAS numeric values. + +### EXAMPLES AND USECASES: #################################################### + +**EXAMPLE 1.** Basic test of `bit64orDFA()` and `bit64andDFA()` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + options ls = max ps = max; + %let M = 53 ; %* 53 is maximum valid value; + data _null_; + array bitmask [ 0: &M] _temporary_ ; + do P = 1 to &M ; + bitmask[P] = 2**(P-1) ; + put bitmask[P] = binary54. @; + put bitmask[P] = best32.; + end ; + bitmask[0] = bitmask[&M.] ; + put bitmask[0] = best32. /; + + a=0; + put a = binary54.; + do P = 1 to &M ; + a = BIT64ORDFA (a, bitmask[P]) ; + put a = binary54.; + end; + put; + + b = 0; + put b = binary54./; + do P = 1 to &M ; + b + (BIT64ANDDFA (a, bitmask[P]) ne .) ; + put b = best32.; + end; + run; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +--- + +## >>> `%createDFBitmap()` macro: <<< ####################### + +The `%createDFBitmap()` macro allows to generate +a `dynamic function bitmap` which is a FCMP based +approach to create *dynamically* allocated **numeric** +bitmnap. + +*Note:* Arrays provided by the macro are *one dimensional* arrays. + +The idea of a SAS bitmap is based on: +1. SGF Paper 3101-2019 + titeled **Re-Mapping A Bitmap** by *Paul M. Dorfman* and *Lessia S. Shajenko* + [https://www.sas.com/content/dam/SAS/support/en/sas-global-forum-proceedings/2019/3101-2019.pdf](https://www.sas.com/content/dam/SAS/support/en/sas-global-forum-proceedings/2019/3101-2019.pdf) +2. SUGI Paper 8-26 + titeled **Table Look-Up by Direct Addressing: Key-Indexing -- Bitmapping -- Hashing** by *Paul M. Dorfman* + [https://support.sas.com/resources/papers/proceedings/proceedings/sugi26/p008-26.pdf](https://support.sas.com/resources/papers/proceedings/proceedings/sugi26/p008-26.pdf) + +### SYNTAX: ################################################################### + +The basic syntax is the following, the `<...>` means optional parameters: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%createDFBitmap( + bitmapName + <,debug=0> + <,outlib=work.DFAfcmp.package> + <,type=32> + <,header=1> +) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**Arguments description**: + +1. `bitmapName` - *Required*, creates a FCMP call subroutine which is also + a bitmap name. In the data step it is used in form of + a call subroutine, e.g. `call bitmapName("Allocate", 3000)`. + Has to satisfy FCMP function naming requirements, but with + maximum of 24 characters. + +* `debug=` - *Optional*, the default value is `0`. + If set to `1` then it turns on a debugging mode. + +* `outlib=` - *Optional*, the default value is `work.DFAfcmp.package`. + It points the default location for new generated dynamic + function arrays compiled by FCMP. + *Hint!* Keep it as it is. + +* `type=` - *Optional*, the default value is `32`. Sets the type of + bitwise operations executed internaly on the bitmap. + The only valid values are `32` or `52`, + With 32 the `BOR()` and `BAND()` SAS functions are used + and with 52 the `bit64orDFA()` and `bit64and DFA()` FCMP + functions are used. + +* `header=` - *Optional*, the default value is `1`. Indicates if + the `proc fcmp outlib = &outlib.;` header is added to + the executed code. If not 1 then no header is added. + +**Created function arguments description**: + +A function generated by the macro is: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +call &bitmapName.(IO, position, value) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +and accepts the following list of arguments and values: + +1. `IO` - is a *character* steering argument, possible + values and behaviour they call are the following: + - `Check`, `Test`, `T` - to get information if a bit is set to 1 (on) or not, + - `On`, `1` - to set a selected bit to 1, + - `Off`, `0` - to set a selected bit to 0, + - `C`, `Clear` - to reduce a bitmat to a single empty cell, + - `A`, `Allocate` - to reserve space for a bitmap and set all bits to 0, + - `A0`, `Allocate0` - to reserve space for a bitmap and set all bits to 0, + - `A1`, `Allocate1` - to reserve space for a bitmap and set all bits to 1, + - `D`, `Dim`, `Dimension` - to returns minimal and maximal index of the bitmap. + +2. `position` - is a *numeric* argument and depends on the `IO` value. + Behaves in the following way: + - for `On`, `Off`, `1`, `0`/ `Check`, `Test`, `T` it is a bitmap index, + - for `C`, `Clear` is ignored, + - for `A`, `Allocate` sets the value of the minposition, i.e. the minimal position of the bitmap index, + - for `D`, `Dimension` it returns value of the minposition, + +.3 `value` - is a *numeric* argument and depends on the `IO` value. + Behaves in the following way: + - for `Check`, `Test`, `T` it holds value retrieved from a bitmap on a given position, + - for `On`, `Off`, `1`, `0`, `C`, `Clear` is ignored, + - for `A`, `Allocate` it sets the value of the maxposition, i.e. maximal position of the array index, + - for `D`, `Dimension` it returns value of the maxposition + +The `position` and the `value` arguments are **outargs**, i.e. can be changed by the function. + +### EXAMPLES AND USECASES: #################################################### + +**EXAMPLE 1.** Bitmap of type 32: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %createDFBitmap(MyBitmap32,type=32,debug=1); + options APPEND=(cmplib = WORK.DFAfcmp) ; + + data Example1; + call MyBitmap32("Allocate", -10, 100); + L = 0; H = 0; + call MyBitmap32("Dim", L, H); + put L= H=; + + * populate array with data ; + do i = L to H by 2; + put i @; + call MyBitmap32("1", i, .); + end; + put; + + * get values from the array ; + Value = .; + do i = L to H; + call MyBitmap32("T", i, Value); + put i= Value=; + end; + run; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**EXAMPLE 2.** Bitmap of type 52: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %createDFBitmap(MyBitmap52,type=52,debug=1); + options APPEND=(cmplib = WORK.DFAfcmp) ; + + data Example2; + call MyBitmap52("Allocate", -10, 100); + L = 0; H = 0; + call MyBitmap52("Dim", L, H); + put L= H=; + + * populate array with data ; + do i = L to H by 2; + put i @; + call MyBitmap52("1", i, .); + end; + put; + + * get values from the array ; + Value = .; + do i = L to H; + call MyBitmap52("T", i, Value); + put i= Value=; + end; + run; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**EXAMPLE 3.** Execution time test for type 52: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %createDFBitmap(MyBigBitmap52,type=52,debug=0); + options FULLSTIMER APPEND=(cmplib = WORK.DFAfcmp) ; + + data Example3; + call MyBigBitmap52("Allocate", -10, 2000000001); + L = 0; H = 0; + call MyBigBitmap52("Dim", L, H); + put L= H=; + + * populate bitmap with data ; + t = time(); + do i = L to H by 17; + call MyBigBitmap52("1", i, .); + x + 1; + end; + t = time() - t; + put "populate:" t= x=; + + * get values from the bitmap ; + t = time(); + Value = .; + do i = L to H; + call MyBigBitmap52("T", i, Value); + x + (-Value); + end; + t = time() - t; + put "search:" t= x=; + run; + +%* +L=-10 H=2000000001 +populate:t=55.902999878 x=117647060 +search:t=654.12900019 x=0 +NOTE: The data set WORK.EXAMPLE3 has 1 observations and 6 variables. +NOTE: DATA statement used (Total process time): + real time 11:50.42 + user cpu time 11:46.40 + system cpu time 0.45 seconds + memory 301791.12k + OS Memory 326332.00k +; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**EXAMPLE 4.** Execution time test for type 32: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %createDFBitmap(MyBigBitmap32,type=32,debug=0); + options FULLSTIMER APPEND=(cmplib = WORK.DFAfcmp) ; + + data Example4; + call MyBigBitmap32("Allocate", -10, 2000000001); + L = 0; H = 0; + call MyBigBitmap32("Dim", L, H); + put L= H=; + + * populate bitmap with data ; + t = time(); + do i = L to H by 17; + call MyBigBitmap32("1", i, .); + x + 1; + end; + t = time() - t; + put "populate:" t= x=; + + * get values from the bitmap ; + t = time(); + Value = .; + do i = L to H; + call MyBigBitmap32("T", i, Value); + x + (-Value); + end; + t = time() - t; + put "populate:" t= x=; + run; + +%* +L=-10 H=2000000001 +populate:t=50.417999983 x=117647060 +populate:t=611.13600016 x=0 +NOTE: The data set WORK.EXAMPLE4 has 1 observations and 6 variables. +NOTE: DATA statement used (Total process time): + real time 11:02.07 + user cpu time 10:59.07 + system cpu time 1.46 seconds + memory 489583.90k + OS Memory 513876.00k +; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +--- + +## >>> `generateArrays` exec: <<< ####################### + +The generateArrays exec file provides a **list of automatically generated examples** of functions +emulating data structures. + +The list of provided examples is the following: +- `SmpArray` - Simple Immutable Dynamic Function Array +- `SmpMtbArray` - Simple Mutable Dynamic Function Array +- `SrchArray` - Searchable Immutable Dynamic Function Array +- `SrchMtbArray` - Searchable Mutable Dynamic Function Array +- `DynArrayC` - Dynamic Hash-based Character Function Array (length 256 bytes) +- `StackC` - Dynamic Hash-based Character Stack (length 256 bytes) +- `StackN` - Dynamic Hash-based Numeric Stack +- `FifoC` - Dynamic Hash-based Character Fifo (length 256 bytes) +- `FifoN` - Dynamic Hash-based Character Fifo +- `DescStackC` - Dynamic Hash-based Character Descending Ordered Stack (length 256 bytes) +- `AscStackC` - Dynamic Hash-based Character Ascending Ordered Stack (length 256 bytes) +- `DescStackN` - Dynamic Hash-based Numeric Descending Ordered Stack +- `AscStackN` - Dynamic Hash-based Numeric Ascending Ordered Stack +- `PrtQueueNTC` - Dynamic Hash-based Character Priority Queue with *New on Top* (length 256 bytes) +- `PrtQueueNBC` - Dynamic Hash-based Character Priority Queue with *New on Bottom* (length 256 bytes) +- `PrtQueueNTN` - Dynamic Hash-based Numeric Priority Queue with *New on Top* +- `PrtQueueNBN` - Dynamic Hash-based Numeric Priority Queue with *New on Bottom* +- `Bitmap32` - Dynamic Function Bitmap on 32 bit +- `Bitmap52` - Dynamic Function Bitmap on 52 bit + +The `outlib=` option is set to `work.DFAfcmp.package`. The `cmplib=` option is updated automatically. + +--- +## >>> `generateArrays` clean: <<< ####################### + +The generateArrays clean file clears the list of automatically generated examples of functions +emulating data structures provided in the `generatearrays.sas` exec file. + +The `cmplib=` option is updated automatically. + +--- + +## License #################################################################### + +Copyright (c) 2019 Bartosz Jablonski + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +--- diff --git a/hist/0.5.7/dfa.zip b/hist/0.5.7/dfa.zip new file mode 100644 index 0000000000000000000000000000000000000000..657adca1e50615eead9b1a063f73fdc1ba6b7c20 GIT binary patch literal 48636 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 c>A$Z^6lK5x^B)ip2H