Next Previous Table of Contents

# The BMath Class

    #include <linteger/bmath.hxx>

## Overview

This class provides methods to perform multiple precision arithmetic on unsigned magnitudes. The methods in this class are made public so that programmers may use them to implement algorithms which have been designed to run most effeciently on the direct binary representations of multiple precision integers. Those who are willing to treat `LInteger`s as black boxes, however, will have no need to know about the methods presented here, and can safely skip this section. (It is assumed that most people will want to treat `LInteger`s as black boxes when initially encountering the LInteger library.)

## Required Representation of Magnitudes

Magnitudes for BMath methods must be represented by arrays of `unsigned int`s. Each `unsigned int`s in the array is to represent a digit of the magnitude in a base equal to `2**(sizeof(unsigned int)*8)`. The digits within a given magnitude are to be stored in consecutive memory locations such that a digit at a lower memory address has greater significance than any digit at a higher memory address. For example, consider the 64-bit magnitude 0xfedcba9876543210. On a 32-bit machine this is to be stored in memory as:

starting memory address: | 0xfedcba98
starting memory address+4: | 0x76543210

Note that the 4 above is a byte displacement. If A is an `unsigned int*` pointing to the magnitude on this hypothetical 32-bit machine, then A[0]=0xfedcba98, while A[1]=0x76543210.

## Basic Algorithms

The following two algorithms are useful in explaining how some of the methods in the BMath class work.

### The Ripple Carry Algorithm

Given a starting location of start, rippling a carry works as described by the following pseudo-code:

    unsigned int* mem=start;
    while (1)
    {
       (*mem)++;
       if (increment did not cause a carry)
          break;
       mem--;
    }

### The Ripple Borrow Algorithm

Given a starting location of start, rippling a borrow works as described by the following pseudo-code:

    unsigned int* mem=start;
    while (1)
    {
       (*mem)--;
       if (decrement did not cause a borrow)
          break;
       mem--;
    }

## Public Constants

### SmallPrime[]

    static const unsigned int BMath::SmallPrime[];

This is an array of the first few primes. Check the public constant BMath::SmallPrimesAvailable to see how many small primes this array contains.

### SmallPrimesAvailable

    static const int BMath::SmallPrimesAvailable;

This constant tells how many small primes are available in the BMath::SmallPrime[] array.

## Public Methods

### SetBit

    static inline void BMath::SetBit(const int bitNum,
                                     unsigned int* x, const int digits);

Sets the (bitNum+1)th least significant bit in the magnitude pointed to by x to 1. digits indicates how many digits are in the magnitude.

### TestBit

    static inline void BMath::TestBit(const int bitNum,
                                      const unsigned int* x, const int digits);

Returns a non-zero value if the (bitNum+1)th least significant bit in the magnitude pointed to by x is equal to 1 and returns 0 otherwise. digits indicates how many digits are in the magnitude.

### BSR (Single Precision)

    static inline int BMath::BSR(const unsigned int x);

Returns the bit position (0 to LMisc::bitsPerUInt-1 with 0 being least significant) of the most significant bit which is 1 in x.

### BSF (Single Precision)

    static inline int BMath::BSF(const unsigned int x);

Returns the bit position (0 to LMisc::bitsPerUInt-1 with 0 being least significant) of the least significant bit which is 1 in x.

### BSR (Multiple Precision)

    static int BMath::BSR(const unsigned int* x, const int digits);

Returns the bit position (with 0 being least significant) of the most significant bit which is 1 in the magnitude pointed to by x. digits indicates how many digits are in the magnitude.

### BSF (Multiple Precision)

    static int BMath::BSF(const unsigned int* x, const int digits);

Returns the bit position (with 0 being least significant) of the least significant bit which is 1 in the magnitude pointed to by x. digits indicates how many digits are in the magnitude.

### GreaterThanOrEqualTo

    static inline char BMath::GreaterThanOrEqualTo(const unsigned int* x,
                                                   const unsigned int* y,
                                                   int digits);

Compares two magnitudes, returning 1 if the magnitude pointed to by x is greater than or equal to the magnitude pointed to by y and 0 otherwise. Both magnitudes must have an equal number of digits and this number is to be passed as digits.

### GreaterThan

    static inline char BMath::GreaterThan(const unsigned int* x,
                                          const unsigned int* y,
                                          int digits);

Compares two magnitudes, returning 1 if the magnitude pointed to by x is greater than the magnitude pointed to by y and 0 otherwise. Both magnitudes must have an equal number of digits and this number is to be passed as digits.

### LessThanOrEqualTo

    static inline char BMath::LessThanOrEqualTo(const unsigned int* x,
                                                const unsigned int* y,
                                                int digits);

Compares two magnitudes, returning 1 if the magnitude pointed to by x is less than or equal to the magnitude pointed to by y and 0 otherwise. Both magnitudes must have an equal number of digits and this number is to be passed as digits.

### LessThan

    static inline char BMath::LessThan(const unsigned int* x,
                                       const unsigned int* y,
                                       int digits);

Compares two magnitudes, returning 1 if the magnitude pointed to by x is less than the magnitude pointed to by y and 0 otherwise. Both magnitudes must have an equal number of digits and this number is to be passed as digits.

### EqualTo

    static inline char BMath::EqualTo(const unsigned int* x,
                                      const unsigned int* y,
                                      int digits);

Compares two magnitudes, returning 1 if the magnitude pointed to by x is equal to the magnitude pointed to by y and 0 otherwise. Both magnitudes must have an equal number of digits and this number is to be passed as digits.

### NotEqualTo

    static inline char BMath::NotEqualTo(const unsigned int* x,
                                         const unsigned int* y,
                                         int digits);

Compares two magnitudes, returning 1 if the magnitude pointed to by x is not equal to the magnitude pointed to by y and 0 otherwise. Both magnitudes must have an equal number of digits and this number is to be passed as digits.

### BasicAdd

    static inline char BMath::BasicAdd(const unsigned int* x,
                                       const unsigned int* y,
                                       unsigned int* z,
                                       int digits);

Adds the magnitude pointed to by x to the mangitude pointed to by y, storing the digits least significant digits of the result into memory starting at the location pointed to by z. If the addition results in a carry, 1 is returned, otherwise 0 is returned.

x and y must have the same number of digits, and this number is to be passed as digits.

### RippleAdd

    static inline void BMath::RippleAdd(const unsigned int* x,
                                        const unsigned int* y,
                                        unsigned int* z,
                                        int digits);

Adds the magnitude pointed to by x to the mangitude pointed to by y, storing the digits least significant digits of the result into memory starting at the location pointed to by z. If the addition results in a carry, it is rippled out via the ripple carry algorithm with a starting point equal to z-1.

x and y must have the same number of digits, and this number is to be passed as digits.

### Add

    static char BMath::Add(const unsigned int* x, const int digitsX,
                           const unsigned int* y, const int digitsY,
                           unsigned int* z);

Adds the digitsY digit mangitude pointed to by y to the digitsX digit mangitude pointed to by x. The magnitude pointed to by x must have at least as many digits as the magnitude pointed by y for this to work. The digitsX least significant digits of the sum are stored into memory starting at the location pointed to by z. If the sum is a digitsX+1 digit number, 1 is returned, otherwise 0 is returned.

### BasicSubtract

    static inline char BMath::BasicSubtract(const unsigned int* x,
                                            const unsigned int* y,
                                            unsigned int* z,
                                            int digits);

Subtracts the magnitude pointed to by y from the mangitude pointed to by x, storing the digits least significant digits of the result into memory starting at the location pointed to by z. If the subtraction requires a borrow, 1 is returned, otherwise 0 is returned.

x and y must have the same number of digits, and this number is to be passed as digits.

### RippleSubtract

    static inline void BMath::RippleSubtract(const unsigned int* x,
                                             const unsigned int* y,
                                             unsigned int* z,
                                             int digits);

Subtracts the magnitude pointed to by y from the mangitude pointed to by x, storing the digits least significant digits of the result into memory starting at the location pointed to by z. If the subtraction requires a borrow, it is rippled out via the ripple borrow algorithm with a starting point equal to z-1.

x and y must have the same number of digits, and this number is to be passed as digits.

### Subtract

    static void BMath::Subtract(const unsigned int* x, const int digitsX,
                                const unsigned int* y, const int digitsY,
                                unsigned int* z);

Subtracts the digitsY digit magnitude pointed to by y from the digitsX digit mangitude pointed to by x, storing the digitsX least significant digits of the result into memory starting at the location pointed to by z. The magnitude poitned to by x must be greater than or equal to the magnitude pointed to by y and must have at least as many digits if this method is to work.

### Ripple Increment

    static inline void BMath::RippleIncrement(unsigned int* x, int digits);

Increments the magnitude pointed to by x by 1. If this increment results in a carry, it is rippled out via the ripple carry algorithm with a starting point equal to x-1. digits indicates the number of digits (before incrementing) in the magnitude pointed to by x.

### Increment

    static char BMath::Increment(unsigned int* x, int digits);

Increments the digits digit magnitude pointed to by x by 1. If this increment result in a carry, 1 is returned, otherwise 0 is returned.

### RippleDecrement

    static inline void BMath::RippleDecrement(unsigned int* x, int digits);

Decrements the digits digit magnitude pointed to by x by 1. If this decrement results in a borrow, it is rippled out via the ripple borrow algorithm with a starting point equal to x-1. digits indicates the number of digits (before decrementing) in the magnitude pointed to by x.

### BasicMultiply

    static inline void BMath::BasicMultiply(const unsigned int* x,
                                            const unsigned int y,
                                            unsigned int* z,
                                            int digitsX);

Multiplies the digitsX digit magnitude pointed to by x by y and adds the digitsX+1 digit result to the digitsX+1 digit magnitude pointed to by z. If this addition results in a carry it is rippled out via the ripple carry algorithm with a starting point equal to z-1.

### MultDouble

    static inline void BMath::MultDouble(const unsigned int* x,
                                         const unsigned int* y,
                                         unsigned int* z);

Multplies the two digit magnitude pointed to by x by the two digit magnitude pointed to by y, storing the four digit result into memory starting at the location pointed to by z.

### Multiply

    static void BMath::Multiply(const unsigned int* x, int digitsX,
                                const unsigned int* y, int digitsY,
                                unsigned int* z);

Multiplies the digitsX digit magnitude pointed to by x by the digitsY digit magnitude pointed to by y, storing the digitsX+digitsY digit result into memory starting at the location pointed to by z. The memory locations from z to z+digitsX+digitsY-1 inclusive must be zero before this method is called if it is to work.

### SquareDouble

    static inline void BMath::SquareDouble(const unsigned int* x,
                                           unsigned int* y);

Squares the two digit magnitude pointed to by x, storing the four digit result into memory starting at the location pointed to by y. This is method is equivalent to `MultDouble(x,x,y)` except that it is faster.

### Square

    static void BMath::Square(const unsigned int* x, const int digitsX,
                              unsigned int* y);

Squares the digitsX digit magnitude pointed to by x, storing the 2*digitsX result into memory starting at the location pointed to by y. The memory locations from y to y+2*digitsX-1 inclusive must be zero before this method is called if it is to work. This method is equivalent to `Multiply(x,digitsX,x,digitsX,y)` except that it is faster.

### BasicDivide

    static inline void BMath::BasicDivide(unsigned int dividendHigh,
                                          unsigned int dividendLow,
                                          unsigned int divisor,
                                          unsigned int& quotient,
                                          unsigned int& remainder);

Divides the two digit dividend given by dividendHigh*base+dividendLow by divisor, storing the quotient in quotient and the remainder in remainder.

Warning: Be sure that the quotient can fit into an `unsigned int` before calling this method, or you will get a floating exception!

### Divide

    static void BMath::Divide(const unsigned int* dividend, const int dividendSize,
                              const unsigned int* divisor, const int divisorSize,
                              unsigned int*& quotient,
                              unsigned int*& remainder);

Divides the dividendSize digit dividend pointed to by dividend by the divisorSize digit divisor pointed to by divisor. Upon return, quotient will point to a dynamically allocated memory block containing the dividendSize-divisorSize+1 digit magnitude of the quotient, while remainder will point to a dynamically allocated memory block of dividendSize+1 digits containing the remainder.

The caller is assumed to own the memory pointed to by quotient and remainder after this method is called, and is, therefore, responsible for deleting it.

Note: dividendSize must be greater than or equal to divisorSize, and the magnitude pointed to by divisor may not have lead zeros, if this method is to work.

### ModSmall

    static inline unsigned int BMath::ModSmall(const unsigned int* dividend,
                                               int digits,
                                               const unsigned int divisor);

Returns the remainder when the digits digit magnitude pointed to by dividend is divided by divisor.

### ShortShiftRight

    static inline void BMath::ShortShiftRight(unsigned int* x, int digits,
                                              const char distance);

Shifts the bits of the digits digit magnitude pointed to by x to the right by the number of positions given by the 5 least significant bits of distance. Zeros are shifted in on the left, while bits shifted out on the right are lost.

### ShortShiftLeft

    static inline void BMath::ShortShiftLeft(unsigned int* x, int digits,
                                             const char distance);

Shifts the bits of the digits digit magnitude pointed to by x to the left by the number of positions given by the 5 least significant bits of distance. Zeros are shifted in on the right, while bits shifted out on the left are lost.

### ShiftRight

    static void BMath::ShiftRight(unsigned int*& x, int& digits,
                                  const int distance);

Shifts the bits of the digits digit magnitude pointed to by x to the right by the number of positions given by distance. Zeros are shifted in on the left, while bits shifted out on the right are lost. If the shift results in a magnitude with lead zeros, the magnitude is copied without its lead zeros, deleted, and x is modified to point to the copy. Upon return, digits will contain the number of digits in the magnitude that x points to.

### ShiftLeft

    static void BMath::ShiftLeft(unsigned int*& x, int& digits,
                                 const int distance);

Shifts the bits of the digits digit magnitude pointed to by x to the left by the number of positions given by distance. Zeros are shifted in on the right, and no bits are lost. If the shift results in a magnitude with more digits than the magnitude before shifting, the magnitude is copied, deleted, and x is modified to point to the copy. Upon return, digits will contain the number of digits in the magnitude that x points to.

### Div2

    static inline void BMath::Div2(unsigned int* x, int digits);

Shifts the bits of the digits digit magnitude pointed to by x to the right once place. A zero is shifted into the most significant bit of the magnitude, while the least significant bit is lost. This method is equivalent to `BMath::ShiftRight(x,digits,1)` except that it is faster.

Next Previous Table of Contents