XBCD_Math is a high performance floating point math package which supports extended precision operations optimized for calculator type applications. The choice of BCD (Binary Coded Decimal) representation as the intrinsic data type is a compromise which is tilted toward I/O intensive environments, such as calculators, where much of the calculation overhead is due to conversion from user input to internal format and back. BCD minimizes the conversion overhead and, as a convenient side effect, provides a number format which is easy to edit.

The package is written entirely in Intel x86 assembler language, except for the conversion routines between character string representation and internal BCD format. The supported functions include ordinary math operations, square root, all trig and inverse trig functions, logs and exponentials, all hyperbolic and inverse hyperbolic functions, and a full range gamma function. Miscellaneous utility routines for truncation, rounding, floor and ceiling are also supported, as are conversions from integers, floats, doubles, and back.

Internally, numbers are stored in 32-byte blocks consisting of 58 BCD digits of mantissa, 4 BCD digits of exponent, and 1 byte which contains the mantissa and exponent signs plus status bits. They dynamic range, excluding transient underflow conditions, is from 1.0000...E-9999 to 9.9999...E+9999 for positive numbers. Except in pathological computations involving catastrophic loss of precision, extended computations will return about 56 correct digits, considerably beyond the capabilities of quad-precision packages.

A number of advanced algorithms are employed. These include CORDIC, pseudo-multiplication and pseudo-division, non-restoring pseudo-division, etc. Special methods are used for ordinary multi-digit multiplication and division to reduce the number of repeated additions and subtractions normally associated with non-binary formats.

At other pages on this web site, you will find application packages written for or ported to XBCD_Math. These include linear algebra functions, eigensystem solvers, non-linear solvers, integrators, root-finders, C++ classes, etc. A scientific calculator demonstrating the capabilities of the package can be found here.

I have ported the C version of MINPACK available elsewhere on this web site to work with XBCD_Math. Although most applications for nonlinear solvers do not require extended precision, there are occasions when it is helpful. The extended precision port is available here. A sample program which fits a set of measured points to a Lorentzian pulse model is also included.

The complete XBCD Math library is now available as a DLL. This archive includes the DLL, a Borland compatible import library, a complete set of format conversion routines and the XFLOAT class. Although the XFLOAT class is not required, it supports operator overloading of the C++ math and stream operators so new applications can be easily created.

If you wish to use the DLL with a different compiler (different from Borland C++) you will want to create an import library from the DLL which is compatible with your compiler.

The code below is a simple example of the ease with which the XBCD library
can be incorporated into a C++ program. It is included in the archive. Many
existing C++ math codes can be converted to extended precision by simply
replacing all *doubles* with *xfloats* and including the library and
support files.

// XBCD test program: bcdtst1.cpp

//

// This file requires an import library created from 'fltpt8d.dll'.

//

// Compile and link with: fpconv.cpp, xfloat.cpp, fltpt8d.lib

//

#include <iostream.h>

#include "xfloat.h"

int main(void)

{

xfloat a=kpi,b=1.5;

cout << sqrt(a) << endl;

cout << gamma(b) << endl;

cout << factorial((xfloat)48) << endl;

}

The output from this program is shown below.

+1.772453850905516027298167483341145182797549456122387128213E+0000

+8.862269254527580136490837416705725913987747280611935641013E-0001

+1.241391559253607267086228904737337503852148635467776000000E+0061

The XBCD_Math package has been extended to include complex versions of all supported functions. These complex functions are easily accessed through the complex class available here. The files available include example applications for extended precision complex numeric date types. Note that this package contains a static library which is currently only available for Borland compilers.

Here is a brief example of a simple C++ file using the package.

#include "xcomplex.h"

static xcomplex I(0,1);

int main(void)

{

xcomplex x;

cout << "I^I = " << pow(I,I) << endl;

x = xcomplex(2,1);

cout << "sin(2+I) = " << sin(x) << endl;

x = (xfloat)1;

cout << "Pi = " << 4*atan(x) << endl;

}

The output from this file is:

**I^I =
(+2.07879576350761908546955619834978770033877841631769608075E-0001,
0.00000000000000000000000000000000000000000000000000000000E+0000)**

**sin(2+I) =
(+1.403119250622040585019490859767712944070947553407072439774E+0000,
-4.890562590412936735864545685485159211585108846785949657029E-0000)**

**Pi = (3.141592653589793238462643383279502884197169399375105820975E+0000,
0.000000000000000000000000000000000000000000000000000000000E+0000)**

Using *xcomplex *introduces additional real and complex
numeric types into the programming environment and imposes additional burdens on
the programmer. One of these burdens involves proper management of the various
numeric types.

Promotion of C/C++ primitive types (int, float, etc) to *xcomplex
*is not fully implemented, but casting is supported to simplify interfacing
with typical numeric software. The preferred way to manage low precision numbers
and constants is to cast them to *xfloat *type, which will be automatically
promoted to *xcomplex* as needed. (Part of the fun of converting real types
to complex types is that complex numbers require more information, not just more
precision, than real numbers.*)*

The constructors for *xcomplex* do support promotions
of low precision data types, so it is possible to bypass casting when variables
are created. Just keep in mind that an expression such as:

z = 4*atan(1)

will evaluate to an ordinary float at low precision. If you want to establish and maintain extended precision, use:

z = 4*atan((xfloat)1)

This, by the way, is the same type of problem that is found in mixing integer types with floats in standard C and C++. It is no more burdensome, but does demand undivided attention from the programmer.

The current version of the downloadable software includes static libraries for the math package and classes which were created under Borland C++. Hence, they are not usable with other platforms. As the software moves toward a releasable form, it will be compiled under other platforms, probably Microsoft VC++ and Linux. You can try things out with this zip archive.