Using the Library¶
This chapter describes how to compile programs that use CML, and introduces its conventions.
An Example Program¶
The following short program demonstrates the use of the library
#include <stdlib.h>
#include <stdio.h>
#include <cml.h>
int
main(int argc, char const *argv[])
{
cml_complex_t z, w;
z = complex(1.0, 2.0);
w = csin(z);
printf("%g\n", sin(2.0));
printf("%g\n", atan2(2.0, 3.0));
printf("%g\n", creal(w));
printf("%g\n", cimag(w));
return 0;
}
The steps needed to compile this program are described in the following sections.
Compiling and Linking¶
The library header files are installed in their own cml
directory. You should write any preprocessor include statements with a
cml/
directory prefix thus:
#include <cml/math.h>
or simply requiring all the modules in the following way:
#include <cml.h>
If the directory is not installed on the standard search path of your
compiler you will also need to provide its location to the preprocessor
as a command line flag. The default location of the main header file
cml.h
and the cml
directory is /usr/local/include
.
A typical compilation command for a source file example.c
with
the GNU C compiler gcc
is:
$ gcc -Wall -I/usr/local/include -c example.c
This results in an object file example.o
. The default
include path for gcc
searches /usr/local/include
automatically so
the -I
option can actually be omitted when CML is installed
in its default location.
Linking programs with the library¶
The library is installed as a single file, libcml.a
. A shared
version of the library libcml.so
is also installed on systems
that support shared libraries. The default location of these files is
/usr/local/lib
. If this directory is not on the standard search
path of your linker you will also need to provide its location as a
command line flag. The following example shows how to link an application
with the library:
$ gcc -L/usr/local/lib example.o -lcml
The default library path for gcc
searches /usr/local/lib
automatically so the -L
option can be omitted when CML is
installed in its default location.
For a tutorial introduction to the GNU C Compiler and related programs, see “An Introduction to GCC” (ISBN 0954161793). [1]
ANSI C Compliance¶
The library is written in ANSI C and is intended to conform to the ANSI C standard (C89). It should be portable to any system with a working ANSI C compiler.
The library does not rely on any non-ANSI extensions in the interface it exports to the user. Programs you write using CML can be ANSI compliant. Extensions which can be used in a way compatible with pure ANSI C are supported, however, via conditional compilation. This allows the library to take advantage of compiler extensions on those platforms which support them.
When an ANSI C feature is known to be broken on a particular system the library will exclude any related functions at compile-time. This should make it impossible to link a program that would use these functions and give incorrect results.
To avoid namespace conflicts all exported function names and variables
have the prefix cml_
, while exported macros have the prefix
CML_
.
Inline functions¶
The inline
keyword is not part of the original ANSI C standard (C89)
so the library does not export any inline function definitions by default.
Inline functions were introduced officially in the newer C99 standard but
most C89 compilers have also included inline
as an extension for a
long time.
To allow the use of inline functions, the library provides optional inline versions of performance-critical routines by conditional compilation in the exported header files.
By default, the actual form of the inline keyword is extern inline
,
which is a gcc
extension that eliminates unnecessary function
definitions.
When compiling with gcc in C99 mode (gcc -std=c99) the header files automatically switch to C99-compatible inline function declarations instead of extern inline.
Long double¶
In general, the algorithms in the library are written for double
precision only. The long double
type is not supported for
every computation.
One reason for this choice is that the precision of long double
is platform dependent. The IEEE standard only specifies the minimum
precision of extended precision numbers, while the precision of
double
is the same on all platforms.
However, it is sometimes necessary to interact with external data in long-double format, so the structures datatypes include long-double versions.
It should be noted that in some system libraries the stdio.h
formatted input/output functions printf
and scanf
are
not implemented correctly for long double
. Undefined or
incorrect results are avoided by testing these functions during the
configure
stage of library compilation and eliminating certain
CML functions which depend on them if necessary. The corresponding
line in the configure
output looks like this:
checking whether printf works with long double... no
Consequently when long double
formatted input/output does not
work on a given system it should be impossible to link a program which
uses CML functions dependent on this.
If it is necessary to work on a system which does not support formatted
long double
input/output then the options are to use binary
formats or to convert long double
results into double
for
reading and writing.
Compatibility with C++¶
The library header files automatically define functions to have
extern "C"
linkage when included in C++ programs. This allows
the functions to be called directly from C++.
Thread-safety¶
The library can be used in multi-threaded programs. All the functions are thread-safe, in the sense that they do not use static variables. Memory is always associated with objects and not with functions. For functions which use workspace objects as temporary storage the workspaces should be allocated on a per-thread basis. For functions which use table objects as read-only memory the tables can be used by multiple threads simultaneously.
Footnotes
[1] | http://www.network-theory.co.uk/gcc/intro/ |
[2] | /etc/ld.so.conf on GNU/Linux systems |