package -- load a package of new
library functions
Introductionpackage(dirname) loads a new library
package.
Call(s)package(dirname <, Quiet> <, Forced>)
Parametersdirname |
- | a valid directory path: a character string |
OptionsQuiet |
- | suppresses screen output while loading the library |
Forced |
- | enforces reloading of libraries that are already loaded |
Returnsthe value of the last statement in the initialization file
init.mu of the package.
Side
EffectsThe path dirname/lib is prepended to the
search path LIBPATH.
The path dirname/modules/OSName is prepended to
the search path READPATH (OSName is
the name of the operating system; cf. sysname). This way, library
functions are first searched for in the package. Modules contained in the package are found
automatically. In case of a naming conflict, a package function
overrides a function of the system's main library.
Related
Functionsexport, LIBPATH, loadmod, loadproc, newDomain, read, READPATH
Detailsnumlib is the library for number
theory, numeric is the
library for numerical algorithms etc. Also the user should organize
collections of related functions as a library package. With a suitable
structure of the folder containing the files with the source code, the
whole library can be loaded into the MuPAD session via a call to
package.:: as in numlib::fibonacci, numeric::int etc.package, or new functions
are to be added to an existing library domain of MuPAD's
standard installation. The detailed example 1 below is devoted to the former case, whereas
example 2 covers the latter case. Special
care should be taken, when existing libraries are modified: the user
should make sure that existing functionality is not overwritten or
destroyed by the modification.mypack, say, containing the library package
to be loaded can be placed anywhere in the filesystem. The pathname
specified in a package call may be an absolut path (from
the root to mypack). Alternatively, a path relative to the
``working directory'' may be specified.
Note that the ``working directory'' is different on different operating systems. On Windows systems, for example, the ``working directory'' is the folder, where MuPAD is installed. On UNIX or Linux systems, it is the directory in which the current MuPAD session was started.
mypack must have the same hierarchical
structure as the standard MuPAD library. In particular, it must
have a subfolder lib containing the source files of the
package. Inside the lib folder, an initialization file
init.mu must exist.
For example, on a UNIX or Linux system, the folder mypack should have the following structure (up to different path separators, the same holds for other operating systems as well):
mypack/lib/init.muTypically, the initialization file
mypack/lib/LIBFILES/mylib.mu
mypack/lib/MYLIB/stuff.mu
mypack/lib/MYLIB/...
mypack/lib/MYLIB/SUBDIR/morestuff.mu
mypack/lib/MYLIB/SUBDIR/...
init.mu uses loadproc commands to define
the objects (new library domains and/or functions) of the package.
If a new library domain is to be created, the lib
folder should contain a subfolder LIBFILES with a file
LIBFILES/mylib.mu. The loadproc commands inside
init.mu should refer to the file mylib.mu.
Inside this file, the new library domain should be created via newDomain. The functions
(slots) of this new library domain should again be declared via
loadproc commands
that refer to the actual location of the files containing the source
code of these functions. The code files should be organized in folders
such as lib/MYLIB, lib/MYLIB/SUBDIR etc.
This structure and the loading mechanism corresponds to the
organization of MuPAD's main library. It uses the initialization
file MuPAD_ROOT_PATH/lib/sysinit.mu.
mylib, say, is to be generated
by the package, the initialization file mypack/lib/init.mu
should refer to the file LIBFILES/mylib.mu where the
library is actually created:
// -------- file mypack/lib/init.mu --------
// load the library domain 'mylib'
alias(path = pathname("LIBFILES")):
mylib := loadproc(mylib, path, "mylib"):
unalias(path):
stdlib::LIBRARIES := stdlib::LIBRARIES union {"mylib"}:
// The return value of the package call:
null():
// ---------- end of file init.mu ----------
By adding the new library domain mylib to the set
stdlib::LIBRARIES, a call to package will
automatically launch the info function to print information
about the new package. The information includes the string
mylib::info that should be defined in
LIBFILES/mylib.mu.
The value of the last statement in the file init.mu is
the return value of a package call. Typically, this is the
null() object to avoid
any unwanted screen output when loading the package. Alternatively,
some useful information such as the string "package 'mylib'
successfully loaded" may be returned.
Cf. example 1 for further details.
LIBFILES/mylib.mu should generate the new
library domain via newDomain. Some standard entries
such as mylib::Name, mylib::info, and
mylib::interface should be defined. The functions
mylib::function1 etc. of the new library should refer to
the actual code files via loadproc:
// ---- file mypack/lib/LIBFILES/mylib.mu ----
// mylib -- a library containing my functions
mylib := newDomain("mylib"):
mylib::Name := "mylib":
mylib::info := "Library 'mylib': a library with my functions":
mylib::interface := {hold(function1), hold(function2), ...}:
// define the functions implemented in ../MYLIB/function1.mu etc:
alias(path = pathname("MYLIB")):
mylib::function1 := loadproc(mylib::function1, path, "function1"):
mylib::function2 := loadproc(mylib::function2, path, "function2"):
...
unalias(path):
// define the functions implemented in ../MYLIB/SUBDIR/more1.mu etc:
alias(path = pathname("MYLIB", ßUBDIR")):
mylib::more1 := loadproc(mylib::more1, path, "more1"):
mylib::more2 := loadproc(mylib::more2, path, "more2"):
...
unalias(path):
null():
// -------- end of file mylib.mu ------------
Cf. example 1 for further details.
Option: Quiet
Option: Forced
Example
1In the following, we demonstrate how a package should be organized that generates a new library domain containing user-defined functions. In example 2, we load the same functions, but include them in one of MuPAD's standard libraries rather than create a new library domain.
Suppose we have implemented some functions operating on integers
such as a factorial function and a new function for computing powers of
integers. It is a good idea to combine these functions into one
package. The new library domain is to be called numfuncs
(for elementary number theoretic functions). It is organized as a
package stored in the folder demoPack1. This folder has
the following structure:
demoPack1/lib/init.mu
demoPack1/lib/LIBFILES/numfuncs.mu
demoPack1/lib/NUMFUNCS/factorial.mu
demoPack1/lib/NUMFUNCS/russian.mu
The initialization file init.mu may be
implemented as follows:
// ----- file demoPack1/lib/init.mu -----
// loads the library 'numfuncs'
alias(path = pathname("LIBFILES")):
numfuncs := loadproc(numfuncs, path, "numfuncs"):
stdlib::LIBRARIES := stdlib::LIBRARIES union {"numfuncs"}:
unalias(path):
// return value of package:
"library 'numfuncs' successfully loaded":
// -------- end of file init.mu ---------
The function pathname is used to create the
pathname in a form that is appropriate for the currently used operating
system. The loadproc
call refers to the actual definition of the new library domain in the
file LIBFILES/numfuncs.mu:
// --- file demoPack1/lib/LIBFILES/numfuncs.mu ---
// numfuncs -- the library for elementary number theory
numfuncs := newDomain("numfuncs"):
numfuncs::Name := "numfuncs":
numfuncs::info := "Library 'numfuncs': the library of ".
"functions for elementary number theory":
numfuncs::interface := {hold(factorial), hold(russianPower)}:
// define the functions implemented in ../NUMFUNCS/factorial.mu etc:
alias(path = pathname("NUMFUNCS")):
numfuncs::factorial :=
loadproc(numfuncs::factorial, path, "factorial"):
numfuncs::odd :=
loadproc(numfuncs::odd, path, "russian"):
numfuncs::russianPower :=
loadproc(numfuncs::russianPower, path, "russian"):
unalias(path):
null():
// --------- end of file numfuncs.mu ---------
Here, the new library domain is created via newDomain. Any library domain
should have the entries Name and info. One
may also define an interface entry, which is to contain
all the functions a user should be aware of.
This file also contains the definitions of the functions
factorial, odd, and russianPower
which are implemented in the subfolder
demoPack1/lib/NUMFUNCS. (See example 2 for details of the implementation; just replace
numlib by numfuncs.)
The function numfuncs::factorial is implemented in a
separate file. The functions numfuncs::odd and
numfuncs::russianPower are both installed in the file
russian.mu.
Note that numfuncs::odd is not added to the interface
slot, because it is a utility function that should not be seen and used
by the user.
Finally, we demonstrate the loading of the library package. Suppose
that we have several packages, installed in the folder
myMuPADFolder:
/home/myLoginName/myMuPADFolder/demoPack1
/home/myLoginName/myMuPADFolder/demoPack2
...
The library numfuncs installed in
demoPack1 is loaded by a call to the package
function:
>> package("/home/myLoginName/myMuPADFolder/demoPack1")
Library 'numfuncs': the library of functions for elementary \
number theory
-- Interface:
numfuncs::factorial, numfuncs::russianPower
"library 'numfuncs' successfully loaded"
In the initialization file init.mu, the new
library was added to stdlib::LIBRARIES. For the reason,
loading causes the above information about the library to be printed.
By default, a library package can be loaded only once:
>> package("/home/myLoginName/myMuPADFolder/demoPack1")
Warning: Package already defined. For redefinition use option \
Forced [package]
Following the warning, we overwrite the existing library
numfuncs by another call to package using the
option Forced:
>> package("/home/myLoginName/myMuPADFolder/demoPack1",
Forced)
Warning: Package redefined [package]
"library 'numfuncs' successfully loaded"
After loading, the new library numfuncs is
fully integrated into the system. Its functions can be called like any
other function of MuPAD's main library:
>> numfuncs::factorial(41)
33452526613163807108170062053440751665152000000000
>> numfuncs::russianPower(123, 12)
11991163848716906297072721
Example
2We demonstrate how a package should be organized that adds new functions to an existing library domain.
We consider the same functions as in example 1. However, instead of creating a new library
domain, we wish to add these functions to the existing library domain
numlib of
MuPAD's main library. In particular, the package is to install
the new functions numlib::factorial and
numlib::russianPower. Before loading such functions, we
should make sure that they do not overwrite existing functions of the
standard numlib
installation. As a simple test to check that the standard installation
does not provide a function numlib::factorial, one may
simply try to call this function:
>> numlib::factorial
FAIL
Indeed, this function does not exist yet and shall now
be provided by an extension installed in a folder
demoPack2:
demoPack2/lib/init.mu
demoPack2/lib/NUMLIB/factorial.mu
demoPack2/lib/NUMLIB/russian.mu
In this case, no new library domain is to be created.
Hence, in contrast to example 1, no
file demoPack2/lib/LIBFILES/numlib.mu needs to be
installed (which would be in conflict with the corresponding file
defining the numlib
library domain of the standard installation). Instead, the new
functions may be declared directly in the initialization file
init.mu as follows:
// ------ file demoPack2/lib/init.mu -------
// loads additional functions for the existing library 'numlib'
numlib::interface := numlib::interface
union {hold(factorial), hold(russianPower)}:
// define the functions implemented in ../NUMLIB/factorial.mu etc:
alias(path = pathname ("NUMLIB")):
numlib::factorial :=
loadproc(numlib::factorial, path, "factorial"):
numlib::odd :=
loadproc(numlib::odd, path, "russian"):
numlib::russianPower :=
loadproc(numlib::russianPower, path, "russian"):
unalias(path):
// return value of package:
"new numlib functions successfully loaded":
// ---------- end of file init.mu ----------
Similar to example 1, we
added the main functions to the existing interface slot of
numlib.
We now have a look into the files factorial.mu and
russian.mu containing the source code of the
functions:
// ---- file demoPack2/lib/NUMLIB/factorial.mu ----
numlib::factorial :=
proc(n : Type::NonNegInt) : Type::PosInt
// factorial(n) computes n!
begin
if n = 0 then 1
else n*numlib::factorial(n - 1)
end_if
end_proc:
// -------- end of file factorial.mu ---------
The routine numlib::odd is a utility
function for numlib::russianPower. Bothe functions are
coded in one file:
// ---- file demoPack2/lib/NUMLIB/russian.mu ----
numlib::odd := m -> not(iszero(m mod 2)):
numlib::russianPower :=
proc(m : DOM_INT, n : Type::NonNegInt) : DOM_INT
// computes the n-th power of m using the
// russian peasant method of multiplication
local d;
begin
d := 1;
while n>0 do
if numlib::odd(n) then
d := d*m;
n := n - 1;
else
m := m*m;
n := n div 2;
end_if
end_while;
d
end_proc:
// ----------- end of file russian.mu ------------
Finally, we demonstrate the loading of the functions.
Suppose that we have several packages, installed in the folder
myMuPADFolder:
/home/myLoginName/myMuPADFolder/demoPack1
/home/myLoginName/myMuPADFolder/demoPack2
...
The functions installed in demoPack2 are
loaded by a call to the package function:
>> package("/home/myLoginName/myMuPADFolder/demoPack2")
"new numlib functions successfully loaded"
The new functions added to the interface
slot of numlib are listed by an info call:
>> info(numlib)
Library 'numlib': the package for elementary number theory
-- Interface:
numlib::Lambda, numlib::Omega,
...
numlib::factorial, numlib::fibonacci,
...
numlib::proveprime, numlib::russianPower,
...
After loading, the new functions are fully integrated into the library and can be called like any other function of MuPAD's library:
>> numlib::factorial(41)
33452526613163807108170062053440751665152000000000
>> numlib::russianPower(123, 12)
11991163848716906297072721