# Class Library For Numbers Module

## Introduction

The module clnum adds arbitrary precision floating point and rational numbers to Python. Both real and complex types are supported. The module also contains arbitrary precision replacements for the functions in the standard library math and cmath modules.

The clnum module uses the Class Library for Numbers (CLN) to do all of the hard work. The module simply provides a proper type interface so that the CLN numbers work with the standard Python arithmetic operators and interact properly with the built-in Python numeric types.

## Installation

To install the clnum module, you need to have some other components installed on your system.

- The GNU g++ compiler and standard library installed so that you can build C++ programs.

- The Python header files and the distutils package.

- CLN library and development files.

On a Debian system, these are satisfied by installing the following packages: g++, libcln-dev, and python-dev. Other Linux systems will have similar packages. If your system does not have a CLN package, go to http://www.ginac.de/CLN/ and download the source. Then follow the instructions for building CLN.

Once you have the required components installed, installing the clnum module is simple. You need to download rpncalc from http://sourceforge.net/projects/calcrpnpy/ and unpack it. Go to the directory that was created and run the following command as root.

    python clnum_setup.py install --prefix=/usr/local

Verify the installation by running the unit test (test_clnum.py).

If you want information on customizing the install process, see the section titled "Installing Python Modules" in the standard Python documentation.

### Windows Users

A binary installer is now available for Windows thanks to the contribution of Frank Palazzolo. So all you need to get this module installed on Windows is to download and run the installer.

If you want to build the source on Windows, see the Windows build instructions.

## Types

The clnum package adds four numeric types to the standard set available in Python. The mpf type is an arbitrary precision floating point type. The mpq type is a rational type. The types cmpf and cmpq are complex versions of these types.

mpf(x, prec=0)
  Convert a string or a number to arbitrary precision floating point. If the x argument is a string, it must follow the syntax for a Python float. However, infinity and NaN are not supported. Otherwise, the x argument may be any of the types int, long, float, mpq, or mpf. The optional prec argument specifies the desired number of decimal digits in the fraction part (zero means use the global default). See the discussion on precision for more information.
mpq(numer, denom=None)
  Convert a string or a number to a rational number. If the numer argument is a string, it must have the form "[+-]numerator_digits/denominator_digits" (the "/denominator_digits" part is optional). Otherwise, the numer argument may be any of the types int, long, float, mpq, or mpf. If the second parameter is used, both values must be integer types (int or long). In that case, the numer parameter is the numerator and denom is the denominator of the rational number. The resulting number is always reduced to lowest terms.
cmpf(real, imag=None, prec=0)
  Convert a string or a number to arbitrary precision complex floating point. If the real argument is a string, it must follow the syntax for a Python complex. However, infinity and NaN are not supported. Otherwise, the real argument may be any of the types int, long, float, complex, mpq, mpf, cmpq or cmpf. If the optional imag parameter is used, both the real and imag values must be numbers from the set int, long, float, mpq, or mpf. The optional prec argument specifies the desired number of decimal digits in the fraction part (zero means use the global default). See the discussion on precision for more information.
cmpq(real, imag=None)
  Convert a string or a number to a complex rational number where both the real and imaginary parts are rationals. If the real argument is a string, it must follow the syntax for a Python complex with the real and imaginary parts following the syntax for mpq. Otherwise, the real argument may be any of the types int, long, float, complex, mpq, mpf, cmpq or cmpf. If the optional imag parameter is used, both the real and imag values must be numbers from the set int, long, float, mpq, or mpf.

## Precision

There are two major categories of numbers, those that are exact, and those that are approximate. The exact numbers are from the set int, long, mpq, and cmpq. The approximate numbers are from the set float, complex, mpf, and cmpf.

Whenever a calculation is performed with high-precision numbers, you want the result to reflect the precision used in all of the intermediate calculations. So if the result is exact, you want all of the intermediate calculations to be exact. This means that there can be no implicit conversions of approximate numbers to exact numbers. As a consequence, whenever mpq and cmpq types are used in an expression they can only be coerced to an approximate type not the other way around. Since the float and complex types do not recognize mpq and cmpq, an exception is raised whenever arithmetic between these types is attempted.

If you perform mixed arithmetic on two approximate types, the precision of the result always decays to the precision of the value with the lowest precision. There is one exception to this rule. Python float and complex types use the C type double to represent the values. While the CLN library has types that encapsulate doubles, they can lead to non-recoverable aborts when mixed with the extended precision type. To avoid this problem, doubles are converted to an extended precision type with the lowest possible precision (approximately 17 decimal digits).

## Attributes and Methods

The mpf and cmpf types have the following attribute.

prec
  The number of decimal digits of precision.

The complex types cmpq and cmpf have the following attributes and method. They behave the same as the corresponding attributes and method of the built-in complex type.

conjugate()
  Returns the complex conjugate of the complex number.
imag
  The imaginary part of the complex number.
real
  The real part of the complex number.

In addition, the cmpf type has the following attribute.

phase
  The phase angle in radians of the complex number. Range is -pi...pi.

The mpq type has the following attributes.

denom
  The denominator of the rational number.
numer
  The numerator of the rational number.

## Functions

Most of the functions in the clnum module are arbitrary precision floating point versions of Python builtins. See the Python documentation in the math, cmath, and builtins sections for the following functions: acos, acosh, asin, asinh, atan, atan2, atanh, ceil, cos, cosh, degrees, exp, floor, hypot, log, log10, radians, round, sin, sinh, sqrt, tan, and tanh. Note that these functions can operate on both real and complex numbers. If the inputs are real, they work like the functions in the math module. If the inputs are complex, they work like the functions in the cmath module.

Since there is no longer a fixed form for the constants `e` and `pi`, they become the functions `exp1` and `pi` in the clnum module. These functions take the number of decimal digits as the parameter and return the constant with at least the requested precision. The parameter is optional and if not provided, the default precision is used.

binomial(m,n)
  `m` and `n` must be small integers >= 0. This function returns the binomial coefficient (`m` choose `n`) = `m`! / `n`! `(m-n)`! for 0 <= n <= m, 0 otherwise.
cis(x)
  Returns the value of the expression `cos(x)+1j*sin(x)`.
doublefactorial(n)
  `n` must be a small integer >= 0. This function returns the doublefactorial `n`!! = `1*3*...*n` or `n`!! = `2*4*...*n`, respectively.
factorial(n)
  `n` must be a small integer >= 0. This function returns the factorial `n`! = `1*2*...*n`.
find_root(func, x1, x3, eps=1e-12, imax=40)
  Find a root of the user-defined function func that is bracketed by the values x1 and x3. The function must take a single real parameter and return a single real number. The optional argument eps specifies the convergence criterion. The optional argument imax specifies the maximum number of iterations to try before raising an exception.
get_default_precision()
  Returns the approximate number of decimal digits of precision used for conversions where the default precision is specified.
iscomplex(x)
  Returns True if x is one of the types complex, cmpf, or cmpq. Otherwise, False.
isexact(x)
  Returns True if x is one of the types int, long, mpq, or cmpq. Otherwise, False.
isreal(x)
  Returns True if x is one of the types int, long, float, mpf, or mpq. Otherwise, False.
number_str(s, prec=0, prefer_cmpf=False)
  Converts a string representing a number to the most appropriate type from the set int, long, mpq, mpf, cmpq, and cmpf. If prefer_cmpf is True, integers in complex input are treated as floating point. Otherwise, integers in complex input are treated as rationals. Integers may have an optional base specification prefix from the set (0x - hex, 0o - octal, 0b - binary). If the string represents one of the floating point types mpf or cmpf, the value of prec is used in the conversion.
ratapx(x, maxint=0x7FFF)
  Returns a rational approximation to the number x where the numerator and denominator are constrained to be less than or equal to maxint.
set_default_precision(prec)
  Set the number of decimal digits to use in conversions that specify the default precision.

## Examples

All of the examples assume the following import.

`from clnum import *`

    >>> x = mpq(1,3); y = mpq(1,5); z = cmpq(mpq(2,3),mpq(3,5))
    >>> print x+y
    8/15
    >>> print x-y
    2/15
    >>> print x*y
    1/15
    >>> print x/y
    5/3
    >>> print x+1 # Mix with integers.
    4/3
    >>> print x+z
    (1+3/5j)
    >>> print z**3
    (-286/675+73/125j)
    >>> print abs(cmpf(z)), degrees(cmpf(z).phase)  # Polar form of complex number
    0.89690826980491402114 41.987212495816660054
    >>> print hypot(z.real, z.imag) # Another way to compute abs(z)
    0.89690826980491402114
    >>> print get_default_precision()
    26
    >>> print repr(pi(40))
    mpf('3.141592653589793238462643383279502884197169399376',46)
    >>> print repr(exp1(40))
    mpf('2.7182818284590452353602874713526624977572470937',46)
    >>> def f(x): return x*x-2
    >>> r = find_root(f, 1, 2, 1e-20)
    >>> print r
    1.4142135623730950488
    >>> print abs(r - sqrt(2))
    1.5692147344401202195e-24
    >>> print ratapx(pi())
    355/113