Table of Contents

libmpdec quick start

This section contains the bare minimum required to get started. Refer to the libmpdec manual for anything more advanced.

libmpdec/libmpdec++ install

For a custom build, refer to INSTALL.txt. For a Windows build, see vcbuild\README.txt.

# Unix:
./configure
make

# Run the tests (optional). This downloads the official test cases
# (text files):
make check

# As root, install the libraries:
sudo make install

# Depending on your system (e.g., Ubuntu), you may need to run ldconfig.
# Replace "/usr/local/lib" with the actual install location that appears
# in the "make install" output:
sudo ldconfig /usr/local/lib

libmpdec example program

# Unix:
cd libmpdec
make examples

# Try a couple of values:
./pow 2 1234567
4.9963964863286026867472463500015498863E+371641  Inexact Rounded

libmpdec++ quick start

This section contains the bare minimum required to get started. Refer to the libmpdec++ manual for anything more advanced.

libmpdec++ install

libmpdec++ is installed by default, unless –disable-cxx is passed to ./configure. For a Windows build, see vcbuild\README.txt.

libmpdec++ example program

Build the examples:

# Unix:
cd libmpdec++
make examples

# Try a couple of values:
./pi 7
3.141593

./pi 40
3.141592653589793238462643383279502884197

./factorial 5
120

./factorial 40
815915283247897734345611269596115894272000000000

time ./factorial 1000000 > /dev/null
real    0m2.204s

Write Python in C++

Compare the pi function to the Python version further down. There is not much difference:

Decimal
pi(int prec)
{
    context.prec(prec + 2);

    Decimal lasts = 0;
    Decimal t = 3;
    Decimal s = 3;
    Decimal n = 1;
    Decimal na = 0;
    Decimal d = 0;
    Decimal da = 24;

    while (s != lasts) {
        lasts = s;
        n += na;
        na += 8;
        d += da;
        da += 32;
        t = (t * n) / d;
        s += t;
    }

    context.prec(prec);
    return +s;
}

cdecimal quick start

Install

Unix, Mac OS X

As for every C extension, the build requires a working C compiler. For most Linux distributions, the Python header files have to be installed explicitly, since they are shipped as a separate package:

# Debian, Ubuntu:
sudo apt-get install gcc make
sudo apt-get install python-dev

# Fedora, RedHat:
sudo yum install gcc make
sudo yum install python-devel

# openSUSE:
sudo zypper install gcc make
sudo zypper install python-devel

# BSD:
# You know what to do.

# Mac OS X:
# Install Xcode and Python headers.

If pip is present on the system, installation should be as easy as:

pip install cdecimal

Otherwise:

tar xvzf cdecimal-2.3.tar.gz
cd cdecimal-2.3
python setup.py install

If problems arise, read the file PYINSTALL.txt which comes with the distribution.

Windows

The easiest way is to use the binary installers. Otherwise, the build requires Visual Studio.

Factorial in pure Python

Showing off cdecimal’s bignum speed. Note that the factorial function is entirely written in Python and does not call a C factorial function.

from cdecimal import *

def _factorial(n, m):
    if (n > m):
        return _factorial(m, n)
    elif m == 0:
        return 1
    elif n == m:
        return n
    else:
        return _factorial(n, (n+m)//2) * _factorial((n+m)//2 + 1, m)

def factorial(n):
    return _factorial(n, 0)

c = getcontext()
c.prec = MAX_PREC

# 1000000! in pure Python
x = factorial(Decimal(1000000))
sx = str(x)

# Compare to Python integers:
y = factorial(1000000)
sy = str(y)

Calculating pi in pure Python

Showing off cdecimal’s speed for small precisions. Again, the algorithm is in pure Python and does not involve calling a custom C pi-function. This is also the benchmark where cdecimal is often faster than Java’s BigDecimal.

import cdecimal
import decimal

def pi(module, prec):
    """From the decimal.py documentation"""
    module.getcontext().prec = prec + 2
    D = module.Decimal
    lasts, t, s, n, na, d, da = D(0), D(3), D(3), D(1), D(0), D(0), D(24)
    while s != lasts:
        lasts = s
        n, na = n+na, na+8
        d, da = d+da, da+32
        t = (t * n) / d
        s += t
    module.getcontext().prec -= 2
    return +s

for i in range(10000):
    x = pi(cdecimal, 28)

for i in range(10000):
    y = pi(decimal, 28)

Telco benchmark

The telco benchmark was devised by Mike Cowlishaw as a way of measuring decimal performance in a real world telecom application.

Get telco.py, telco.testb, expon180-1e6b.zip and unzip expon180-1e6b.zip.

# decimal.py
python telco.py         # sanity check
python telco.py full    # benchmark

# Edit telco.py and change decimal to cdecimal.
# Speedups should be about 30x.
python telco.py         # sanity check
python telco.py full    # benchmark

Use cdecimal globally

This is a nice tip from the sqlalchemy developers. Since cdecimal.Decimal currently does not support mixed operations with decimal.Decimal, the easiest way to enforce global use of cdecimal is to occupy both places for cdecimal and decimal in sys.modules. This must take place at program start, before importing anything else.

This technique is used in the following section in the file psycopg.py.

# At program start:
import sys
import cdecimal
sys.modules["decimal"] = cdecimal

# Further imports:
import psycopg2       # psycopg2 imports cdecimal, masquerading as decimal
from decimal import * # same here, this is now cdecimal
...

PostgreSQL

The PostgreSQL database adapter psycopg supports PostgreSQL’s numeric type. For a speed comparison, download setup_dectest.sql and psycopg.py. Naturally, both PostgreSQL and psycopg2 are required for this benchmark.

The benchmark inserts 100000 rows containing numeric data into the test database. Subsequently, it fetches all rows. Since INSERT has a lot of database overhead, the main speed gains are in FETCHALL. Similar speed gains (10x) have also been reported by Informix database users.

# Setup a test database:
psql < setup_dectest.sql

# Run the benchmark for decimal.py:
python psycopg.py

# Edit psycopg.py and uncomment the top two import lines to
# use cdecimal globally.
# The speedup should be about 1.7x for INSERT and 12x for FETCHALL.
python psycopg.py