Welcome to the MAPM Home Page
By: Michael C. Ring


View my article reprinted from the November 2001 issue of C/C++ Users Journal.

MAPM, A Portable Arbitrary Precision Math Library in C.


NOTE:
With the release of version 4.9.5, I have updated the license to allow distribution of modified library source code. In the DOCS directory of the distribution, there is a file 'license.txt' which should be inserted before any modified source files. Simply edit the 'license.txt' template accordingly, and permission is granted to distribute modified source code.


My Arbitrary Precision Math library is a set of functions that allow the user to perform math to any level of accuracy that is desired. The precision of a number is only limited by 'INT_MAX' and available memory. For a 16 bit compiler, a number may have 2^15 digits (or ~32,000). For a 32 bit compiler, a number may have 2^31 digits (or ~2.14E+9). See the README file (in the distribution as well as a link below) for a more complete discussion of the actual numerical limitations.

This library has a natural support for floating point values. From most of the other 'C' libraries I looked at, they seem to have a preference for integer only type math manipulations. (This library will also do integer only math if you desire.)

And if a library can only do integers, it can't do ...

Trig functions and other common C math library functions. This library will perform the following functions to any desired precision level : SQRT, CBRT, SIN, COS, TAN, ARC-SIN, ARC-COS, ARC-TAN, ARC-TAN2, LOG, LOG10, EXP, POW, SINH, COSH, TANH, ARC-SINH, ARC-COSH, ARC-TANH, FLOOR, CEIL, GCD, LCM, and also FACTORIAL. The full 'math.h' is not duplicated, though I think these are most of the important ones. My definition of what's important is what I've actually used in a real application.

This library also has a random number generator with a period of 1.0E+15, i.e. the generator will produce 1.0E+15 unique random numbers before the pattern repeats.

This library utilizes a fast multiplication algorithm. This results in much faster multiplications than the typical O(n^2) algorithm. It uses an FFT (fast fourier transform) based multiplication algorithm. This results in only O(n * Log2(n)) growth.

The library is written in 'C' and the distribution includes all source code and documentation. It has been tested under Linux (x86), FreeBSD, HP-UX, Sun Solaris, Venix, MAC OSX, DOS, and Win 2000, NT, XP. GCC was the primary compiler used in the Unix environment. For DOS/NT/XP, the MAPM library has been tested with the the following compilers:

o) GCC (2.8.1, 2.95.2, and 3.2.3) for DOS (D.J. Delorie's DJGPP)
o) Borland C++ 5.x (32 bit) and Turbo C++ 3.0 (16 bit)
o) Microsoft Visual C++ 6.0 (32 bit) and Microsoft C 5.1, 8.00c (16 bit)
o) LCC-Win32 Ver 3.2/3.3
o) MINGW-32 Version mingw-1.0.1-20010726
o) Metrowerks CodeWarrior Pro 7.0
o) Watcom C/C++ 11.x, Open Watcom 1.0
o) DEV-C++ 5.0 Beta 8 Release 4.9.8.0
o) Digital Mars Compiler 8.49
o) National Instruments LabWindows CVI 6.0, 9.0

Great care was taken during design to make the library as portable as possible. If you are using a compiler not listed above, you should have minimal problems getting the library to compile on your system. If you compile the library with a compiler that I don't have access to, feel free to send me your makefile/build script and I'll include it with the next release.


NOTES ON A MICROSOFT COMPILER BUG IN Visual C++ 7.x .NET 2003

There is a COMPILER BUG in Microsoft's Visual C++ 7.x (VS.NET 2003) which prevents a C++ MAPM application from compiling.

This only affects C++ applications. C applications are OK.

The compiler bug creates an error C2676 similar to this:

...\mapm-49\M_APM.H(###) : error C2676: binary operator '-': 'MAPM' doesn't define this operator or a conversion to a suitable type for the predefined operator.

To work around this bug, go to http://www.microsoft.com

In the upper right corner of web page, search for "814455".

The results of the search will point you to an article on how to work around the problem.



USING MAPM IN A MULTI-THREADED APPLICATION :

Note that the default MAPM library is NOT thread safe. MAPM internal data structures could get corrupted if multiple MAPM functions are active at the same time. The user should guarantee that only one thread is performing MAPM functions. This can usually be achieved by a call to the operating system to obtain a 'semaphore' or 'critical code section' so the operating system will guarantee that only one MAPM thread will be active at a time.

Martin Pfingstl (Martin.Pfingstl@epost.de) created a set of stand-alone function wrappers so the MAPM library is thread-safe when using these functions. The thread-safe functions currently only work with Micosoft's compiler. As other users send me compiler specific thread-safe functions, I'll add them to the distribution.

NOTE: As of MAPM Version 4.7 , the thread safe function wrappers are included in the distribution. I will leave this link here for users that are still using older versions of MAPM but need the thread safe functions.



USING MAPM WITH COMPLEX NUMBERS :

Ivano Primi (ivano.primi@tin.it) has graciously submitted a set of wrapper functions so MAPM can perform arbitrary precision arithmetic on complex numbers. His library is not part of MAPM, it is a stand-alone library which just calls the MAPM functions. The (Unix and Win) complex number library can be found below in the download section, the files begin with MAPMX- ... Many thanks to Ivano for his work, since a few other people have asked about complex number capability.


C++ Wrapper Class


Orion Sky Lawlor (olawlor@acm.org) has added a very nice C++ wrapper class to m_apm.h. This C++ class will have no effect if you just use a normal C compiler. The library will operate as before with no user impacts.

The syntax is the same as if you were just writing normal code, but all the computations will be performed with the high precision math library, using the new 'datatype' MAPM.

Using the C++ wrapper allows you to do things like:


// Compute the factorial of the integer n

MAPM Factorial(MAPM n)
{
        MAPM i;
        MAPM product=1;
        for (i=2; i<=n; i++)
           product*=i;

        return product;
}


MAPM  a, f;            // a,f are uninitialized (value is undefined)
MAPM  b = "4.5e12";    // b is 4.5 trillion
MAPM  c = 3;           // c is now three
MAPM  d = -6.1;        // d is now minus six point one
MAPM  e = c;           // e is now three
MAPM  array[8];        // use normal array notation
MAPM  array2d[8][4];   


e = -c * (23.9022 - b * d);
a = sqrt(b);
f = cbrt(e);

for (ii=0; ii < 8; ii++)
  {
   array[ii] = sin(ii + 0.21) * exp(-ii / e);

   for (jj=0; jj < 4; jj++)
     {
      array2d[ii][jj] = array[ii] - sqrt(jj * 17.7654 + 2 * c);
     }
  }

c = "1.0e+9131";
d = log10(c);
e = sqrt(fabs(d)); 


/* quick and dirty example with output */

/*
 *    Note the use of literal character strings as constants.
 *
 *    This allows the user to specify constants that cannot be
 *    represented by a standard C datatype, such as a number with 
 *    200 digits or a number with a very large or small exponent 
 *    (i.e., 6.21E-3714).
 */

char  obuf[256];
MAPM  u, v, w, x, y, z;         // arbitrary precision datatype

m_apm_cpp_precision(50);        // set MINIMUM precision level
                                // for all calculations

x = 9.34231;
y = -21;
z = "-8.982349249829824921479824924792347921E-17";

w = (82.30421 + sin(x / "21.11") / exp(y * 0.0726426)) 
                                 * "4.32917E-2" / z;
v = "3.742416" * log(-w);
u = sqrt(v) + cbrt(v);

printf("\n");
x.toString(obuf, 50);   printf("x = [%s] \n",obuf); 
y.toString(obuf, 50);   printf("y = [%s] \n",obuf); 
z.toString(obuf, 50);   printf("z = [%s] \n",obuf); 
w.toString(obuf, 50);   printf("w = [%s] \n",obuf); 
v.toString(obuf, 50);   printf("v = [%s] \n",obuf); 
u.toString(obuf, 50);   printf("u = [%s] \n",obuf); 


Output from above code sample code :

x = [9.34231000000000000000000000000000000000000000000000E+0] 
y = [-2.10000000000000000000000000000000000000000000000000E+1] 
z = [-8.98234924982982492147982492479234792100000000000000E-17] 
w = [-4.06165846135776503301770738763183914451375637893923E+16] 
v = [1.43121038693447060414449698088102300924570797933606E+2] 
u = [1.71941170788317776083850581271655444461072359345223E+1] 

Projects/Applications Using MAPM :


(If you have a project or application which uses MAPM and would like to have a link here to your S/W or Web page, please feel free to let me know.)


Polynomial Curve Fitting [Version 1.2 December 9 2007]

By Michael Ring

This software will allow the user to curve fit any number of x,y 
data samples to an Nth order polynomial. Currently, the software 
will support order 'N' from 1-48. Higher values of polynomial 
order (> 48) can easily be obtained by simple modifications to 
the source.  This curve fitting software assumes you already 
have the MAPM library available. (See below to download the 
MAPM library).


Lua Binding for MAPM


Lua is a powerful, light-weight programming language designed for extending 
applications. Lua is also frequently used as a general purpose, stand-alone 
language. Lua combines simple procedural syntax (similar to Pascal) with 
powerful data description constructs based on associative arrays and extensible
sematics. Lua is dynamically typed, interpretted from bytecodes, and has 
automatic memory management with garbage collection, making it ideal for 
configuration, scripting, and rapid prototyping.


Chicken


CHICKEN - A practical and portable Scheme system.

CHICKEN is a compiler for the Scheme programming language. CHICKEN produces 
portable, efficient C, supports almost all of the current Scheme language 
standard, R5RS and includes many enhancements and extensions. CHICKEN 
runs on MacOS X, Windows, and many Unix flavours. 


Computational Linear Algebra -- Version 3.0 (*)

By Lenimar N. Andrade (lenimar@mat.ufpb.br)

My application is called "Computational Linear Algebra -- 
Version 3.0" (*). I hope it will be concluded and uploaded to 
ftp.simtel.net by December 2000. I'm testing it and rewriting 
some functions presently.

It is an ambitious project, I've been thinking about it for years.  
Given  an  n x n  complex matrix, the CLA provides important 
information about it: determinant, inverse, characteristic and 
minimal polynomials, eigenvalues, eigenvectors, Jordan canonical 
form. 

(If the reader studies Mathematics, I say simply: "The CLA program 
calculates the Jordan canonical form of a n x n complex matrix"  
and this is all!  It's a difficult calculation. As far as I know 
the all-mighty Mathematica cannot calculate Jordan's form of a 
simple 7 x 7 matrix, for example. It calculates it only for small 
matrices. The Jordan form is a very important theme from Linear 
Algebra and its applications.)

It is being tested by using GCC and by Borland's C.

Arbitrary precision is important to calculate with security all 
of the complex roots of a polynomial equation of high degree. 
Handling big integer numbers is very important also.

=============================================================

A little example: 

Let M be the complex matrix:

  20+9i   7+21i  -12-35i      7-2i      -19   -15+7i  -20-22i
 32-27i  10-29i  -17+19i   -29-13i  -31+38i   30+10i    15-6i
   24+i -10-33i    -37-i   -29+26i   35+33i  -36+28i  -34+25i
   1-6i  33+26i     34-i    -21-5i  -13-24i   -3-29i   33+19i
-20-27i  35+17i   -8+23i     -2-8i   -7-31i  -10-13i  -23+11i
-18+18i -16-28i   -9+32i   -11+20i    7+11i   20-22i    13-2i
  32-8i  34+35i   -18-9i     7-17i   21-11i  -29-30i  -21+36i

Using CLA (that uses the MAPM library) one can easily calculate
its determinant.  It's equal to

              -347964138525 + 420266812927i

Please note the huge integers above!

(*) an out of date version (9 years ago) is available at 

ftp://ftp.simtel.net/pub/simtelnet/msdos/math/cla20.zip

CUBA: Codon Usage and Bias Analysis Version 1.7.0

By David Morrison (david.morrison@uts.edu.au

By Michael Bedward (mbedward@ozemail.com.au)

http://.... to be announced
 
CUBA is a cross-platform program (Windows NT/9x, various 
unixes) for the analysis of genetic data in the form of 
codon usage tables. MAPM is used for multinomial probability 
calculations on gene sequence data. This involves large 
factorials (up to 8000! so far), division, logs, and Nth
power calculations.
 
The multinomial expression that used is:
   [N! / (n1! * n2! * ... nT!)] * (p1^n1 * p2^n2 * ... * pT^nT)
 
where N is the total number of codons in the gene sequence 
(which varies between 200 and 8000 for the data so far); 
n1, n2 etc are the counts for each of the 61 possible codons 
that we look at; and p1, p2 etc are the expected counts for 
codons calculated in various ways for different versions of 
this measure.

Interpcom Version 2.3

By Jean-Marc Drezet

In this command interpreter, it is possible to 
use several expression evaluators, and I made one
using the MAPM library. See one of the above links
to get more details.

Jean-Marc Drezet

ChaosPro -- Version 3.1 (*)

By Martin Pfingstl (Martin.Pfingstl@epost.de)

ChaosPro is a MDI fractal generator compatible with FractInt and
UltraFractal. It can read FractInt's *.par, *.frm, *.ifs,
*.l and *.map files, and UltraFractal's *.upr, *.uxf, *.ufm
and *.ucl files. It is completely based on 24 bit color and thus can
create smooth true color images. Its palette editor lets you have
full control over the colors. With its keyframing technique and
it's spline interpolation algorithm it can create smooth (AVI)
animations of any parameter. It can 3D transform 2D fractals
(height fields). You can write your own formulas using the built
in language, which gets compiled in real time into ready to run
optmized machine code. The compiler natively knows about complex
and quaternion numbers, which enables it to produce Quaternions
(true 3D fractals). ChaosPro has support for layers (similar to
Photoshop) which allows you to merge different fractals and thus
to combine coloring modes.

And why does ChaosPro need MAPM?

ChaosPro allows the user to zoom in. In addition to that, it
allows the user to calculate animations based on any parameters.
So if parameter values responsible for zooming would be only
double (or 80 bit TEMPREAL) values, then zooming in or creating
animations would not work if you zoomed in about 40 times.
Calculating the exact point where to zoom in would be inaccurate
and thus would be very irritating.

Creating zoom animations would be even worse. The animation
system in ChaosPro uses cubic splines for smooth interpolation,
so ChaosPro needs to solve linear equation systems in order to
calculate all the coefficients of that cubic spline. That means it
needs high precision math. ChaosPro uses MAPM to make it possible
to create animations.

(*) version 3.1 will be available in summer 2003.

Follow the links below to view the README or to download the MAPM library. Ivano Primi's complex number wrapper package are the files beginning with MAPMX- ... If you need complex numbers, then you need both the MAPM-... files as well as MAPMX-... files. The complex number wrapper package runs on top of MAPM, they are two independent libraries.

The '.zip' files should be unzipped such that the directory structure is maintained (option '-d' on the command line : pkunzip -d mapm-$$$.zip)


The views and opinions expressed in this page are strictly those of the page author.
The contents of this page have not been reviewed or approved by the University of Minnesota.