This project is still in its infancy and is updated regularly.
This project is a collection of code written in C89/C90 (commonly called ANSI C) for mathematicians and physicists to use on various types of projects. It started with rss_ringoccs, a suite of tools written for processing the Cassini radio science data, which is written mostly in C (but also Python), but eventually grew beyond the scope of just astronomy.
There are no dependencies other than a C compiler and the C standard library. The library is written entirely in ISO C89/C90 compliant code, and no C99/C11 or GCC extensions are used. It compiles with C99 and C11/C18 compilers, so it is more fitting to say it is written in the intersection of these standards.
Run the Makefile with (FreeBSD users should use gmake):
make
The Makefile is parallelizable which saves quite a bit of time, especially on emulated architectures:
make -j
Options to pass to make:
OMP=1
Compile with
OpenMPsupport. WARNING Apple's version of clang does NOT support OpenMP, and the-fopenmpoption will result in an error. Homebrew has versions of clang and gcc that do support OpenMP. This option is particularly recommended if you will be doing a lot of computations with special functions in Python using thetmpyllibrary and have a CPU with a decent number of cores.
NO_INLINE=1
Do not use any inline code. This may (pending other options) result in a smaller
libtmpl.sofile, but several functions become significantly slower (not recommended). If your compiler does not supportC99or higher, and does not support thegccinlineextension, enable this option.
NO_MATH=1
Do not use
libtmpl's implementation oflibm, the C standard library for mathematical tools, instead using your compilers implementation. This may be recommended. Tests againstglibc,FreeBSD libc, andMSVC's implementation oflibmshow thatlibtmplcan be significantly faster while achieving 1 ULP in error (all functions have benchmarks in thetests/directory and you may see for yourself), but this has only been tested on the architectures supported by the Debian GNU/Linux operating system (amd64/x86_64,i386,aarch64/arm64,armhf,armel,mipsel,mips,mips64el,ppc64el,powerpc,s390x,alpha,riscv,sh4,sparc). All architectures other thanamd64/x86_64andaarch64/arm64were emulated usingdebootstrap+chrootwithQEMU. Time-tests showlibtmplperforms well on these architectures, but results may not be indicative of actual hardware. Users of architectures not listed may wish to use their defaultlibm. Also, if your compiler does not support theIEEE-754standard (most do), or does not support type-punning forunion, the portable algorithms (algorithms that do not useIEEE-754or type-punning) are much slower. In these instances you may wish to use the defaultlibm.
NO_INT=1
A few functions (like
tmpl_Double_Mod_2) can get significant performance boosts if 32-bit and 64-bit fixed width integers are available. This is not required by the C language, however, and the typesuint64_tanduint32_tare not required to be defined instdint.h, even for C99 compliant compilers (but these types usually are, in practice). Theconfig.cfile will attempt to detect these integer sizes in a C89 compatible manner by examining the macros inlimits.h. If you wish to skip all of this (not recommended), enable this option. The alternative algorithms use manipulations of the bit-fields that represent 32-bitfloatand 64-bitdouble, rather than type-punning 32-bit and 64-bit integers.
NO_LONGLONG=1
Skip
long longfunctions. If your compiler supports C99 or higher, thelong longtype is available. In certain environments (most modern machines running GNU/Linux, FreeBSD, or macOS)long longandlongare identical, meaning it is somewhat wasteful to have two versions of the same function. Enable this option if you only wish to uselongfunctions.
NO_IEEE=1
Disable use of the
IEEEformats forfloatanddouble. Theconfig.cfile should detect if your compiler supports this, and type-punning forunion, so you should not need to set this option manually (not recommended).
NO_ASM=1
Only applicable if
NO_MATHis not set, and forx86_64/amd64,i386,arm64/aarch64, andarmv7lmachines. Some functions, likesqrt, can be handled efficiently in assembly code. If you wish to use only C code, set this option (not recommended).
FASM=1
Use the flat assembler instead of the assembly language used by
gccandclang. You must havefasminstalled to use this. This option is ignored ifNO_ASM=1is set. Only applicable onx86_64/amd64machines.
CC=cc
The C compiler you use. On Debian GNU/Linux and derivatives (Ubuntu, etc.)
gcc,clang,tcc, andpcchave all been tested and work as expected. Fortccyou MUST either pass theNO_ASM=1option since this compiler (as of this writing) does not support assembly language, or useFASM=1if you havefasminstalled.
EXTRA_FLAGS=
Any extra compiler flags you wish to pass. For example, with
CC=clangyou can passEXTRA_FLAGS="-Weverything -Wno-padded -Wno-float-equal"to see iflibtmplbuilds with all flags (except-Wpaddedand-Wfloat-equal) enabled.
ARCH=
Manually set the name of the architecture you are using. The Makefile attempts to detect your architecture via the
uname -munix command. This will most likely work for you. The sole exception I came across is emulating ani386machine on anx86_64/amd64host. The result ofuname -misx86_64, even though the emulated architecture isi386. As a result the wrong assembly code is used and the compiling fails. SetARCH=i386to manually override this if you're in a similar situation. (Note: Emulatingaarch64,mips,powerpc, etc. on anx86_64host works fine without the need to set this option).
Afterwords, if you would like to install libtmpl in /usr/local/lib, run:
sudo make install
You may need to update the LD_LIBRARY_PATH environment variable.
Add the following to your .bashrc, .shrc, or whichever shell you're using.
export LD_LIBRARY_PATH="/usr/local/lib:$LD_LIBRARY_PATH"
If you did not install libtmpl to /usr/local/lib, try:
export LD_LIBRARY_PATH="/path/to/libtmpl:$LD_LIBRARY_PATH"
To remove all build and .so files, run:
make clean
To uninstall, run:
sudo make uninstall
To install into a directory tree other than /usr/local, set the prefix variable
when running make, e.g. make prefix=/opt install will install into /opt/lib etc.
A bash script is available, but results in a larger and less performant build.
By default it has nearly all compiler warnings enabled for gcc and clang
(including -Weverything with clang) and is used internally as a
quick error check.
To use, run:
sudo bash make.sh
Options:
-cc=
Ccompiler to be used. Tested withgcc,clang,tcc, andpccon Debian GNU/Linux.
-std=
Cstandard to use. Default is-std=c89.
-omp
Compile with OpenMP support.
-inplace
Do not install
libtmplinto/usr/local/lib/and/usr/local/include/. Use this option if you do not havesudoprivileges.
-inline
Use inline code. You must have
-stdset toc99or higher.
-nomath
Do not use
libtmpl's implementation oflibm. Same asNO_MATH=1in the Makefile.
-noieee
Do not use any type-punning code or code that takes advantage of the
IEEE-754floating point format.
-noint
Do not use any code that uses fixed-width integers.
-longlong
Compile
long longcode. Must have-std=c99or higher.
-monster
libtmplwas written in a way that allows all.cfiles to be#included into one file and then compiled. While this may seem silly, compilers lacking link-time optimization can optimize the library at compile time, resulting in a very performant build. Astronomical computations performed byrss_ringoccsare about twice as fast this way. If your compiler has decent link-time optimization it makes only a small difference. This option creates a single.cfile that#includes the entirety oflibtmpl, appropriately namedmonster.c, and then compiles this.
A very primitive batch script exists for Windows users. Run the script with:
C:\Users\ryan\source\repos\libtmpl>make.bat
This creates libtmpl.lib in the libtmpl/ directory.
It does not copy the include/ directory or the library to any system
directories. This has been tested using a Windows 10 virtual machine and it
worked as expected. It compiles with MSVC's cl by default. Pass the option
clang or clang-cl to use LLVM's clang compiler.
Almost all mathematical functions of real or complex variables are computed via one of two methods:
- Argument reduction:
Reduce the input
xto a small range[a, b]and then accurately compute the function in the range using some numerical method. Ex:sin,cos,log,sqrt.
- Separate argument into windows:
Determine if the input
xfalls in one of the ranges[a_0, b_0], ...,[a_n, b_n], allowing fora_0 = -infandb_n = +inf, and then compute the function in this range using some numerical method. Ex:Bessel_J0,Bessel_I0. Usually Taylor series for small inputs and asymptotic expansions for large.
The numerical methods are typically one of the following:
- Taylor / Maclaurin Series.
- Pade Approximants.
- Asymptotic Expansions.
- Chebyshev Polynomials.
- Remez exchange.
Inside data/ lies all of the code for computing the coefficients of these
approximations. None of the code is directly used in libtmpl, indeed most
files are in Python. This directory is kept in this repository for the sake
of studying algorithms. In particular, for seeing where these approximations
come from.
All functions have examples of basic usage.
All header and inline files for libtmpl.
The source files. Mostly .c, but a few assembly files are found for certain
architectures.
Time and accuracy tests of libtmpl against other libraries. To run these
tests will require these libraries being available. Running these tests is
not required, and they are mostly for internal use and to verify the
algorithms implemented in libtmpl.
Language bindings, or wrappers, are provided for C++, Python,
and IDL (also the Free/Open-Source implementation GDL). All bindings require
libtmpl being built beforehand. The source codes used to live in this
repository, but have since moved to their own for easier management. These
can be found via the following links.
libtmpl is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
libtmpl is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with libtmpl. If not, see <https://www.gnu.org/licenses/>.