[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
For the following discussion, we will assume that you have installed
the CLN source in $CLN_DIR
and built it in $CLN_TARGETDIR
.
For example, for me it's CLN_DIR="$HOME/cln"
and
CLN_TARGETDIR="$HOME/cln/linuxelf"
. You might define these as
environment variables, or directly substitute the appropriate values.
11.1 Compiler options | ||
11.2 Compatibility to old CLN versions | ||
11.3 Include files | ||
11.4 An Example | ||
11.5 Debugging support |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Until you have installed CLN in a public place, the following options are needed:
When you compile CLN application code, add the flags
-I$CLN_DIR/include -I$CLN_TARGETDIR/include |
make
variable CFLAGS or CXXFLAGS).
When you link CLN application code to form an executable, add the flags
$CLN_TARGETDIR/src/libcln.a |
make
variable LIBS).
If you did a make install
, the include files are installed in a
public directory (normally /usr/local/include
), hence you don't
need special flags for compiling. The library has been installed to a
public directory as well (normally /usr/local/lib
), hence when
linking a CLN application it is sufficient to give the flag -lcln
.
Since CLN version 1.1, there are two tools to make the creation of software packages that use CLN easier:
cln-config
is a shell script that you can use to determine the
compiler and linker command line options required to compile and link a
program with CLN. Start it with --help
to learn about its options
or consult the manpage that comes with it.
AC_PATH_CLN
is for packages configured using GNU automake.
The synopsis is:
|
cln-config
, which
is either found in the user's path, or from the environment variable
CLN_CONFIG
. It tests the installed libraries to make sure that
their version is not earlier than MIN-VERSION (a default version
will be used if not specified). If the required version was found, sets
the CLN_CPPFLAGS
and the CLN_LIBS
variables. This
macro is in the file `cln.m4' which is installed in
`$datadir/aclocal'. Note that if automake was installed with a
different `--prefix' than CLN, you will either have to manually
move `cln.m4' to automake's `$datadir/aclocal', or give
aclocal the `-I' option when running it. Here is a possible example
to be included in your package's `configure.ac':
AC_PATH_CLN(1.1.0, [ LIBS="$LIBS $CLN_LIBS" CPPFLAGS="$CPPFLAGS $CLN_CPPFLAGS" ], AC_MSG_ERROR([No suitable installed version of CLN could be found.])) |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
As of CLN version 1.1 all non-macro identifiers were hidden in namespace
cln
in order to avoid potential name clashes with other C++
libraries. If you have an old application, you will have to manually
port it to the new scheme. The following principles will help during
the transition:
cl_
something.h
, include
cln/
something.h
now.
cl_
prefix. Exceptions are all the typenames of number types,
(cl_N, cl_I, cl_MI, ...), rings, symbolic types (cl_string,
cl_symbol) and polynomials (cl_UP_type). (This is because their
names would not be mnemonic enough once the namespace cln
is
imported. Even in a namespace we favor cl_N
over N
.)
cl_
in their name still
carry that cl_
if it is intrinsic part of a typename (as in
cl_I_to_int ()
).
cln
in one of your public header files by saying
using namespace cln;
. This would propagate to other applications
and can cause name clashes there.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Here is a summary of the include files and their contents.
<cln/object.h>
<cln/number.h>
<cln/complex.h>
<cln/real.h>
<cln/float.h>
<cln/sfloat.h>
<cln/ffloat.h>
<cln/dfloat.h>
<cln/lfloat.h>
<cln/rational.h>
<cln/integer.h>
<cln/io.h>
<cln/complex_io.h>
<cln/real_io.h>
<cln/float_io.h>
<cln/sfloat_io.h>
<cln/ffloat_io.h>
<cln/dfloat_io.h>
<cln/lfloat_io.h>
<cln/rational_io.h>
<cln/integer_io.h>
<cln/input.h>
<cln/output.h>
<cln/malloc.h>
malloc_hook
, free_hook
.
<cln/abort.h>
cl_abort
.
<cln/condition.h>
<cln/string.h>
<cln/symbol.h>
<cln/proplist.h>
<cln/ring.h>
<cln/null_ring.h>
<cln/complex_ring.h>
<cln/real_ring.h>
<cln/rational_ring.h>
<cln/integer_ring.h>
<cln/numtheory.h>
<cln/modinteger.h>
<cln/V.h>
<cln/GV.h>
<cln/GV_number.h>
<cln/GV_complex.h>
<cln/GV_real.h>
<cln/GV_rational.h>
<cln/GV_integer.h>
<cln/GV_modinteger.h>
<cln/SV.h>
<cln/SV_number.h>
<cln/SV_complex.h>
<cln/SV_real.h>
<cln/SV_rational.h>
<cln/SV_integer.h>
<cln/SV_ringelt.h>
<cln/univpoly.h>
<cln/univpoly_integer.h>
<cln/univpoly_rational.h>
<cln/univpoly_real.h>
<cln/univpoly_complex.h>
<cln/univpoly_modint.h>
<cln/timing.h>
<cln/cln.h>
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
A function which computes the nth Fibonacci number can be written as follows.
#include <cln/integer.h> #include <cln/real.h> using namespace cln; // Returns F_n, computed as the nearest integer to // ((1+sqrt(5))/2)^n/sqrt(5). Assume n>=0. const cl_I fibonacci (int n) { // Need a precision of ((1+sqrt(5))/2)^-n. float_format_t prec = float_format((int)(0.208987641*n+5)); cl_R sqrt5 = sqrt(cl_float(5,prec)); cl_R phi = (1+sqrt5)/2; return round1( expt(phi,n)/sqrt5 ); } |
Let's explain what is going on in detail.
The include file <cln/integer.h>
is necessary because the type
cl_I
is used in the function, and the include file <cln/real.h>
is needed for the type cl_R
and the floating point number functions.
The order of the include files does not matter. In order not to write
out cln::
foo in this simple example we can safely import
the whole namespace cln
.
Then comes the function declaration. The argument is an int
, the
result an integer. The return type is defined as `const cl_I', not
simply `cl_I', because that allows the compiler to detect typos like
`fibonacci(n) = 100'. It would be possible to declare the return
type as const cl_R
(real number) or even const cl_N
(complex
number). We use the most specialized possible return type because functions
which call `fibonacci' will be able to profit from the compiler's type
analysis: Adding two integers is slightly more efficient than adding the
same objects declared as complex numbers, because it needs less type
dispatch. Also, when linking to CLN as a non-shared library, this minimizes
the size of the resulting executable program.
The result will be computed as expt(phi,n)/sqrt(5), rounded to the nearest integer. In order to get a correct result, the absolute error should be less than 1/2, i.e. the relative error should be less than sqrt(5)/(2*expt(phi,n)). To this end, the first line computes a floating point precision for sqrt(5) and phi.
Then sqrt(5) is computed by first converting the integer 5 to a floating point number and than taking the square root. The converse, first taking the square root of 5, and then converting to the desired precision, would not work in CLN: The square root would be computed to a default precision (normally single-float precision), and the following conversion could not help about the lacking accuracy. This is because CLN is not a symbolic computer algebra system and does not represent sqrt(5) in a non-numeric way.
The type cl_R
for sqrt5 and, in the following line, phi is the only
possible choice. You cannot write cl_F
because the C++ compiler can
only infer that cl_float(5,prec)
is a real number. You cannot write
cl_N
because a `round1' does not exist for general complex
numbers.
When the function returns, all the local variables in the function are automatically reclaimed (garbage collected). Only the result survives and gets passed to the caller.
The file fibonacci.cc
in the subdirectory examples
contains this implementation together with an even faster algorithm.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
When debugging a CLN application with GNU gdb
, two facilities are
available from the library:
cl_abort()
is
called. Its default implementation is to perform an exit(1)
, so
you won't have a core dump. But for debugging, it is best to set a
breakpoint at this function:
(gdb) break cl_abort |
(gdb) where |
print
command doesn't know about
CLN's types and therefore prints mostly useless hexadecimal addresses.
CLN offers a function cl_print
, callable from the debugger,
for printing number objects. In order to get this function, you have
to define the macro `CL_DEBUG' and then include all the header files
for which you want cl_print
debugging support. For example:
#define CL_DEBUG #include <cln/string.h> |
cl_string s
, and
inspect it under gdb
, the output may look like this:
(gdb) print s $7 = {<cl_gcpointer> = { = {pointer = 0x8055b60, heappointer = 0x8055b60, word = 134568800}}, } (gdb) call cl_print(s) (cl_string) "" $8 = 134568800 |
cl_print
goes to the program's error output,
not to gdb's standard output.
Note, however, that the above facility does not work with all CLN types,
only with number objects and similar. Therefore CLN offers a member function
debug_print()
on all CLN types. The same macro `CL_DEBUG'
is needed for this member function to be implemented. Under gdb
,
you call it like this:
(gdb) print s $7 = {<cl_gcpointer> = { = {pointer = 0x8055b60, heappointer = 0x8055b60, word = 134568800}}, } (gdb) call s.debug_print() (cl_string) "" (gdb) define cprint >call ($1).debug_print() >end (gdb) cprint s (cl_string) "" |
[ << ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |