Module/package creation in julia

We have previously talked about package creation in lisp and in R, and library creation in C. Packages or modules for julia are pretty easy to build, so let’s put together an example.

  • In your shell, go into your development directory where you will create the package.
  • Julia has two environments/REPLs, we first start julia (get julia> prompt), then type ], which puts us into the pkg environment.
  • We will create some very simple numerical integration package (“NumInt”) that uses Gaussian quadrature to integrate functions on the domain [0,oo] using Laguerre polynomials.  All of our integrals will be of the form

    \[I=\int_0^\infty x^{1/2} \, e^{-x}\, f(x)\, dx\]

and so we need the abscissas and weights for L_n^{1/2}(x) for some n, and for simplicity we use n=9. I have previously computed the abscissa and weights, and I want to include them in the package as a dictionary, which is a hashfile datatype. This is about as close to the way R incorporates data as is possible. We don’t have to do it this way, but it lets us illustrate how a global data type can be built into a module.

  • In the pkg environment type
     
generate NumInt

This creates a directory containing a Project.toml file, and a src directory. We edit the Project.toml file and populate  the  src directory with our source code. Here is my Project.toml  file. The uuid was selected by generate

name = "NumInt"
uuid = "e34ad496-2e32-499f-9af0-d0e24cd90786"
authors = ["Jeff Schmidt "]
version = "0.1.0"

[deps]
  • I will have one single source file in src, NumInt.jl, containing all of the functions and objects that I want to export. Here it is:
module NumInt

import FileIO
import JLD
using FileIO,JLD

export LagP
export dLagP
export LagGQ
export RootLagP
export LagW
export LagA

"LagGQ(f): Numerical integration of function f on [0,inf]"
LagGQ=function(f)
 sum(f(LagA[j])*LagW[j] for j in 1:9)
end

"LagP(x,n,a): Laguerre polynomial L_n^a(x)"
LagP=function(x,n,a)
if n<0
0.0
elseif n==0
1.0
elseif n==1
1-x+a
else
(2*n-x+a-1)*LagP(x,n-1,a)/n-(n-1+a)*LagP(x,n-2,a)/n
end
end

"dLagP(x,n,a): derivative of Laguerre polynomial L_n^a(x)"
dLagP=function(x,n,a)
-LagP(x,n-1,a+1)
end

"RootLagP(n,a,xL,xR,iters): root of L_n^a(x) on [xL,xR]"
RootLagP=function(n,a,xL,xR,iters)
r=(xL+xR)/2.0
for j in 1:iters
r=r-LagP(r,n,a)/dLagP(r,n,a)
end
r
end

function __init__()
    Base.rehash!(LagA)
    Base.rehash!(LagW)
end


LagA=Dict{Int,Float64}();
LagA=merge(LagA,Dict(1 => 0.253532554974419))
LagA=merge(LagA,Dict(2 => 1.020844277720390))
LagA=merge(LagA,Dict(3 => 2.323096077022466))
LagA=merge(LagA,Dict(4 => 4.199350600657294))
LagA=merge(LagA,Dict(5 => 6.71397431661503))
LagA=merge(LagA,Dict(6 => 9.972009159539347))
LagA=merge(LagA,Dict(7 => 14.154053671278081))
LagA=merge(LagA,Dict(8 => 19.611902819165948))
LagA=merge(LagA,Dict(9 => 27.251236523027060))
LagW=Dict{Int,Float64}();
LagW=merge(LagW,Dict(1 => 0.198571270656713))
LagW=merge(LagW,Dict(2 => 0.374920814473676))
LagW=merge(LagW,Dict(3 => 0.236074839771482))
LagW=merge(LagW,Dict(4 => 0.06709611033811))
LagW=merge(LagW,Dict(5 => 0.009008509612924))
LagW=merge(LagW,Dict(6 => 0.00054266078178))
LagW=merge(LagW,Dict(7 => 0.000012705367889))
LagW=merge(LagW,Dict(8 => 0.000000084843099))
LagW=merge(LagW,Dict(9 => 0.000000000072286))

end # module
  • Note that I import my dependencies FileIO, JLD (we don’t need them, they are an example of how it’s done), list my exports, define each function and place a document string immediately above it, and I have an init function that rehashes the dictionaries containing my abscissas and weights every time the module is started. You must do this with hashed data.
  • Once all of this is assembled and edited, in your shell go into the NumInt directory, start julia, type ] to enter into the pkg environment, and activate the NumInt environment
activate .
  • Quit the pkg environment (leave the pkg prompt and return to the julia prompt). We need to make the correct dependencies by making julia see which versions of FileIO and JLD you have on your system, so at the julia prompt type
add FileIO
add JLD

Julia will precompile and update the Project.toml file, which for me now looks like this

name = "NumInt"
uuid = "e34ad496-2e32-499f-9af0-d0e24cd90786"
authors = ["Jeff Schmidt "]
version = "0.1.0"

[deps]
FileIO = "5789e2e9-d7fb-5bc7-8068-2c6fae9b9549"
JLD = "4138dd39-2aa7-5051-a626-17a0bb65d9c8"
  • At this point you can quit julia, tar/gz or zip the NumInt directory (tar cvzf NumInt.tar.gz NumInt)  and distribute it.
  • Suppose I want to use this. First I un-tar/gz it, in the shell go into the NumInt directory, activate it it and load it
jeff@archangel:~/Dev$ tar xvzf NumInt.tar.gz  (shell)
jeff@archangel:~/Dev$ cd NumInt
jeff@archangel:~/Dev$ julia
julia > ]
pkg > activate .
pkg > CTRL-c
julia > import NumInt
julia > using NumInt
julia > names(NumInt)
7-element Array{Symbol,1}:
 :LagA
 :LagGQ
 :LagP
 :LagW
 :NumInt
 :RootLagP
 :dLagP

# now type a question mark to get into help

help?> LagGQ
search: LagGQ

  LagGQ(f): Numerical integration of function f on [0,inf]


julia> LagGQ(x-> x)
1.3293404938768747  # 3*sqrt(pi)/4, very nice
Home 2.0
error: Content is protected !!