M
mike3
Hi.
(posted to both newsgroups since I was not sure of which would be
appropriate for this question or how specific to the given language it
is. If one of them is inappropriate, just don't send replies to it.)
I'm making a bignum package for use in a program I've got (this is
something different from the pi program you may have heard about). The
package is going to support manipulating long floating point numbers.
The way I have this set up right now is that there is a "raw" unsigned
integer package, from which the floating point package is built on top
of. The questions I have are about coding that lower-level package.
See, I have a routine here that adds up two unsigned integers, but it
also must be able to add so many digits of one starting at one point
in it's data, to so many digits of the other starting at a different
point in it's data, and finally store so many digits of the result at
yet another point in the data buffer holding the result.
This is what I've got (it's in C++, not C, by the way). The problem is
it just doesn't seem like a "neat", or "nice" piece of code. Anyone
know of a better way to approach this?:
/* Add two RawInts.
* Parameters:
* a: First RawInt
* b: Second RawInt
* rOrigin: offset of digit in this to store result at
* rLength: length of region in this to store result in
* aOrigin: offset of digit in a to start addition at
* aLength: length of region in a to add
* bOrigin: offset of digit in b to start addition at
* bLength: length of region in b to add
*
* Returns: carry.
*
* Operation: *this = a + b.
*
* Use ?Origin = 0 and ?Length = -1 for a simple integer addition
* operation.
*/
DIGIT RawInt::rawAdd(const RawInt &a,
const RawInt &b,
int rOrigin, int rLength,
int aOrigin, int aLength,
int bOrigin, int bLength)
{
int i;
DIGIT tmp, carry = 0;
int rlen2, alen2, blen2;
std::vector<DIGIT>::iterator di, de;
std::vector<DIGIT>::const_iterator ai, ae;
std::vector<DIGIT>::const_iterator bi, be;
/* Make sure we don't exceed the boundaries
* of the digit arrays.
*/
if(rLength != -1)
{
rlen2 = rLength;
if(rlen2 > (length - rOrigin))
rlen2 = (length - rOrigin);
} else {
rlen2 = (length - rOrigin);
}
if(aLength != -1)
{
alen2 = aLength;
if(alen2 > (a.length - aOrigin))
alen2 = (a.length - aOrigin);
} else {
alen2 = (a.length - aOrigin);
}
if(bLength != -1)
{
blen2 = bLength;
if(blen2 > (b.length - bOrigin))
blen2 = (b.length - bOrigin);
} else {
blen2 = (b.length - bOrigin);
}
if(rOrigin+alen2 >= length)
alen2 = length-rOrigin;
if(rOrigin+blen2 >= length)
blen2 = length-rOrigin;
if(alen2 > rlen2) alen2 = rlen2;
if(blen2 > rlen2) blen2 = rlen2;
if(alen2 < 0) alen2 = 0;
if(blen2 < 0) blen2 = 0;
/* Set up the iterators */
di = digits.begin()+rOrigin; de = digits.end();
ai = a.digits.begin()+aOrigin; ae = a.digits.end();
bi = b.digits.begin()+bOrigin; be = b.digits.end();
/* Now do the addition */
if(alen2 >= blen2)
{
/* Case 1: a is at least as long as b */
/* Add up a's and b's digits */
for(i=0;i<blen2;i++,++di,++ai,++bi)
{
tmp = *ai + *bi + carry;
if(carry) carry = (tmp <= *bi) ? 1 : 0;
else carry = (tmp < *bi) ? 1 : 0;
*di = tmp;
}
/* Now tackle the part of a that is longer than b */
for(i=blen2;i<alen2;i++,++di,++ai)
{
tmp = *ai + carry;
if(carry)
carry = (tmp == 0) ? 1 : 0;
*di = tmp;
}
/* Zeroize the rest of this. */
for(i=alen2;i<rlen2;i++,++di)
{
*di = carry;
carry = 0;
}
} else {
/* Case 2: b is longer than a */
/* Add up a's and b's digits */
for(i=0;i<alen2;i++,++di,++ai,++bi)
{
tmp = *ai + *bi + carry;
if(carry) carry = (tmp <= *bi) ? 1 : 0;
else carry = (tmp < *bi) ? 1 : 0;
*di = tmp;
}
/* Now tackle the part of b that is longer than a */
for(i=alen2;i<blen2;i++,++di,++bi)
{
tmp = *bi + carry;
if(carry) carry = (tmp <= *bi) ? 1 : 0;
else carry = (tmp < *bi) ? 1 : 0;
*di = tmp;
}
/* Zeroize the rest of this. */
for(i=blen2;i<rlen2;i++,++di)
{
*di = carry;
carry = 0;
}
}
/* Done! Return any leftover carry. */
return(carry);
}
(posted to both newsgroups since I was not sure of which would be
appropriate for this question or how specific to the given language it
is. If one of them is inappropriate, just don't send replies to it.)
I'm making a bignum package for use in a program I've got (this is
something different from the pi program you may have heard about). The
package is going to support manipulating long floating point numbers.
The way I have this set up right now is that there is a "raw" unsigned
integer package, from which the floating point package is built on top
of. The questions I have are about coding that lower-level package.
See, I have a routine here that adds up two unsigned integers, but it
also must be able to add so many digits of one starting at one point
in it's data, to so many digits of the other starting at a different
point in it's data, and finally store so many digits of the result at
yet another point in the data buffer holding the result.
This is what I've got (it's in C++, not C, by the way). The problem is
it just doesn't seem like a "neat", or "nice" piece of code. Anyone
know of a better way to approach this?:
/* Add two RawInts.
* Parameters:
* a: First RawInt
* b: Second RawInt
* rOrigin: offset of digit in this to store result at
* rLength: length of region in this to store result in
* aOrigin: offset of digit in a to start addition at
* aLength: length of region in a to add
* bOrigin: offset of digit in b to start addition at
* bLength: length of region in b to add
*
* Returns: carry.
*
* Operation: *this = a + b.
*
* Use ?Origin = 0 and ?Length = -1 for a simple integer addition
* operation.
*/
DIGIT RawInt::rawAdd(const RawInt &a,
const RawInt &b,
int rOrigin, int rLength,
int aOrigin, int aLength,
int bOrigin, int bLength)
{
int i;
DIGIT tmp, carry = 0;
int rlen2, alen2, blen2;
std::vector<DIGIT>::iterator di, de;
std::vector<DIGIT>::const_iterator ai, ae;
std::vector<DIGIT>::const_iterator bi, be;
/* Make sure we don't exceed the boundaries
* of the digit arrays.
*/
if(rLength != -1)
{
rlen2 = rLength;
if(rlen2 > (length - rOrigin))
rlen2 = (length - rOrigin);
} else {
rlen2 = (length - rOrigin);
}
if(aLength != -1)
{
alen2 = aLength;
if(alen2 > (a.length - aOrigin))
alen2 = (a.length - aOrigin);
} else {
alen2 = (a.length - aOrigin);
}
if(bLength != -1)
{
blen2 = bLength;
if(blen2 > (b.length - bOrigin))
blen2 = (b.length - bOrigin);
} else {
blen2 = (b.length - bOrigin);
}
if(rOrigin+alen2 >= length)
alen2 = length-rOrigin;
if(rOrigin+blen2 >= length)
blen2 = length-rOrigin;
if(alen2 > rlen2) alen2 = rlen2;
if(blen2 > rlen2) blen2 = rlen2;
if(alen2 < 0) alen2 = 0;
if(blen2 < 0) blen2 = 0;
/* Set up the iterators */
di = digits.begin()+rOrigin; de = digits.end();
ai = a.digits.begin()+aOrigin; ae = a.digits.end();
bi = b.digits.begin()+bOrigin; be = b.digits.end();
/* Now do the addition */
if(alen2 >= blen2)
{
/* Case 1: a is at least as long as b */
/* Add up a's and b's digits */
for(i=0;i<blen2;i++,++di,++ai,++bi)
{
tmp = *ai + *bi + carry;
if(carry) carry = (tmp <= *bi) ? 1 : 0;
else carry = (tmp < *bi) ? 1 : 0;
*di = tmp;
}
/* Now tackle the part of a that is longer than b */
for(i=blen2;i<alen2;i++,++di,++ai)
{
tmp = *ai + carry;
if(carry)
carry = (tmp == 0) ? 1 : 0;
*di = tmp;
}
/* Zeroize the rest of this. */
for(i=alen2;i<rlen2;i++,++di)
{
*di = carry;
carry = 0;
}
} else {
/* Case 2: b is longer than a */
/* Add up a's and b's digits */
for(i=0;i<alen2;i++,++di,++ai,++bi)
{
tmp = *ai + *bi + carry;
if(carry) carry = (tmp <= *bi) ? 1 : 0;
else carry = (tmp < *bi) ? 1 : 0;
*di = tmp;
}
/* Now tackle the part of b that is longer than a */
for(i=alen2;i<blen2;i++,++di,++bi)
{
tmp = *bi + carry;
if(carry) carry = (tmp <= *bi) ? 1 : 0;
else carry = (tmp < *bi) ? 1 : 0;
*di = tmp;
}
/* Zeroize the rest of this. */
for(i=blen2;i<rlen2;i++,++di)
{
*di = carry;
carry = 0;
}
}
/* Done! Return any leftover carry. */
return(carry);
}