The R engine is usable in a variety of ways – one of the lesser-known features is that it provides a standalone math library that can be linked to from an external application. This library provides some nice functionality such as:
* Probability distribution functions (density/distribution/quantile functions);
* Random number generation for a large number of probability distributions
In order to make use of this functionality from q, I built a simple Rmathlib wrapper library. The C wrapper can be found here and is simply a set of functions that wrap the appropriate calls in Rmathlib. For example, a function to generate N randomly-generated Gaussian values using the underlying rnorm()
function is:
K rnn(K n, K mu, K sigma) { int i,count = n->i; K ret = ktn(KF, count); for (i = 0; i < count; ++i) kF(ret)[i] = rnorm(mu->f, sigma->f); return ret; }
These have to be imported and linked from a kdb+ session, which is done using special directives (the 2:
verb). I decided to automate the process of generating these directives – the code shell script below parses a set of function declarations in a delimited section of a C header file and produces the appropriate load statements:
INFILE=rmath.h DLL=\`:rmath echo "dll:$DLL" DECLARATIONS=$(awk '/\/\/ BEGIN DECL/ {f=1;next} /\/\/ END DECL/ {f=0} f {sub(/K /,"",$0);print $0}' $INFILE) for decl in $DECLARATIONS; do FNAME=${decl%%(*} ARGS=${decl##$FNAME} IFS=, read -r -a CMDARGS <<< "$ARGS" echo "${FNAME}:dll 2:(\`$FNAME;${#CMDARGS[*]})" done echo "\\l rmath_aux.q"
This generates a set of link commands such as the following:
dll:`:rmath rn:dll 2:(`rn;2) rnn:dll 2:(`rnn;3) dn:dll 2:(`dn;3) pn:dll 2:(`pn;3) qn:dll 2:(`qn;3) sseed:dll 2:(`sseed;2) gseed:dll 2:(`gseed;1) nchoosek:dll 2:(`nchoosek;2)
It also generates a call to load a second q script, rmath_aux.q, which contains a bunch of q wrappers and helper functions (I will write a separate post about that later).
A makefile is included which generates the shared lib (once the appropriate paths to the R source files is set) and q scripts. A sample q session looks like the following:
q) \l rmath.q
q) x:rnorm 1000 / generate 1000 normal variates
q) dnorm[0;0;1] / normal density at 0 for a mean 0 sd 1 distribution
The project is available on github: https://github.com/rwinston/kdb-rmathlib.
Note that loading rmath.q loads the rmath dll, which in turn loads the rmathlib dll, so the rmathlib dll should be available on the dynamic library load path.
[Check out Part 2 of this series]