MFC Template Class CLongInt

The template class template <UINT bits, class T = USHORT, class LT = ULONG> class CLongInt<bits> supports long integer arithmetic. Internally, a CLongInt is represented by n digits of the integral type T (specified by the second template parameter). T must be unsigned. The first digit is the most significant digit, the last digit is the least significant digit. The number base of the internal representation of a CLongInt is 2sizeof(T)*CHAR_BIT. For example, if T is an unsigned short, the number base of the CLongInt is 65536. For internal calculations, there must also exist an unsigned integral type LT (specified by the third template parameter) which must have double the size as T. To achieve maximum portability to other C++ compilers, I've chosen unsigned short for T and unsigned long for LT.

The template parameter bits specifies the size of a CLongInt in bits. bits should be at least 64+sizeof(T)*CHAR_BIT. For smaller bit numbers, use any of the built-in simple types int, long, or __int64.

The CLongInt class implements the complete integer arithmetic. There are friend operator functions to mix CLongInt operands with int or long operands. You can easily expand the class CLongInt to mix it with __int64 operands, too.

To prevent the specification of an invalid template parameter for T or LT, the technique of compile-time assertions is applied (see header file StaticCheck.h). This technique is presented by Andrei Alexandrescu in his book Modern C++ Design (see Chapter 2.1).

CLongInt class members:

Constructors:

CLongInt()

Constructs an uninitialized CLongInt.

CLongInt(const CLongInt& u)

Constructs a CLongInt from another CLongInt u.

CLongInt(int u)CLongInt(UINT u)CLongInt(long u)CLongInt(ULONG u)

Constructs a CLongInt from an integral number u.

CLongInt(LPCTSTR psz, UINT nBase=10)

Constructs a CLongInt from the string psz which
represents an integral number with the base nBase.

Public member functions:

int Compare(const CLongInt& v) const

Returns zero if the CLongInts are identical, <0 if this CLongInt is less than v, or >0 if this CLongInt is greater than v.

I would be happy if you translate this algorithm into your excellent work. If you do this, the audience will probably ask for corresponding optimizations for
CLongInt<bits> / long
CLongInt<bits> * long
CLongInt<bits> + long
CLongInt<bits> - long

Good work, but there's a better implementation.

In many applications, it's very common to work with very different integer sizes.

A situation where long integers are very used are encryption algorithms. Allmost all public key algorithms used to sign and encrypt information all over the world are based on long integers, which may have 1024 or more bits.

In this kind of applications, it's very common to work with integer of 512, 768, 1024 and 2048 bits.
In some situations, you require even more bits to perform some kind of operations.

If you use the maximun bit size allways, you'll get a very poor performance (encryption requires extremely fast algorithms), but compiling the code with many different integer sizes would result in an inneficient code also. If we also consider converting from a bit size to another this would becomes a caos.

I once had to programm a class to do this, and I rather prefer to use a code which dinamically allocates memory and can handle any bit size.

Of course, allocating memory has a cost, but in many application this is preferred.

Bug in function Divide. Here's the fix...

Very nice class, but I found a bug in Divide function.
When working with very large numbers (I'm working with 1024 bit values)
the result of the Divide function is not always correct.
This happens due to the error in the implementation of Knuth's long division algorithm.
Here's the fix I've come up with.
Maybe someone can come up with the better one, but this seems to be working fine for me.
I've done a lot of testing.