Eric Young (eay@cryptsoft.com)
Wed, 25 Mar 1998 14:56:17 +1000 (EST)
On Tue, 24 Mar 1998, Martin G. Diehl wrote:
> In that case you would be getting digits starting at the left as
> though you were doing division "by hand" -- forgetting for the moment
> about negative numbers and assuming that the number is > zero, I think
> your algorithm would be similar to:
>
> result := '';
> DivideBy := 1000000000L;
> while DivideBy > 0 do
> begin
> digit := 0;
> while NumberToConvert > DivideBy do
> begin
> digit := digit + 1;
> NumberToConvert := NumberToConvert div DivideBy;
> end;
> result := result + chr(ord('0') + digit);
> DivideBy := DivideBy div 10;
> end;
>
> I think that's what you said.
>
> Although you used the largest power of 10 that can be expressed in a
> 32 bit integer, you should use the largest power of 10 that can be
> expressed and handled by your BigNum library. In both this and my
> prior example, I intended that div and mod would be done by
> the corresponding BigNum Library functions.
Ok, my reason for using the 32bit size was so that I could use sprintf() to
print digits. I'm assuming whoever wrote the C library will have made a good
effort to get the "%ld" stuff fast :-). In my particular library I have a
fast 'divide by word' function, which is much more effiecent that the bignum
divide. I was a bit quick with the post. My BN_div_word returns the mod
function of from the divisions, so it does do a mod, as a sort of side
effect, but because it is doing 64/32 divides, it is quite effiect, again,
because if I don't have asm for this operation, most compilers have support
in their library for the 'long long' divison my C code uses (or if I don't
use it, my 64/32 C code is not too bad either :-).
So the inner loop is actually
#define BN_ULONG unsigned long
#define BN_DEC_CONV (1000000000L)
#define BN_DEC_FMT1 "%lu"
#define BN_DEC_FMT2 "%09lu"
/* The above defines are for 32bit builds, and I've left out
* some other code */
/* bn_data is malloc()ed to fit the results, code left out*/
BN_LONG *bn_data,*lp;
lp=bn_data;
i=0;
while (!BN_is_zero(t))
{
*lp=BN_div_word(t,BN_DEC_CONV);
lp++; /* take remainders, in reverse */
}
lp--;
/* We now have a series of blocks, BN_DEC_NUM chars
* in length, where the last one needs trucation.
* The blocks need to be reversed in order. */
sprintf(p,BN_DEC_FMT1,*lp);
while (*p) p++;
while (lp != bn_data)
{
lp--;
sprintf(p,BN_DEC_FMT2,*lp);
while (*p) p++;
}
}
eric (putting the 'code' back into CodherPlunks :-)
The following archive was created by hippie-mail 7.98617-22 on Fri Aug 21 1998 - 17:16:13 ADT