package
-- load a package of new
library functionspackage
(dirname)
loads a new library
package.
package(dirname <, Quiet> <, Forced>)
dirname |
- | a valid directory path: a character string |
Quiet |
- | suppresses screen output while loading the library |
Forced |
- | enforces reloading of libraries that are already loaded |
the value of the last statement in the initialization file
init.mu
of the package.
The 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.
export
, LIBPATH
, loadmod
, loadproc
, newDomain
, read
, READPATH
numlib
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.
In 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
We 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