It was thus said that the Great Jerome H. Fine once stated:
By the way, are there any standard algorithms for the
4 basic operations (add, subtract, multiply and divide)
for 128 bit numbers which are composed of 8 * 16 bit
words? As per your suggestion, I would probably use:
CHARACTER * 16 ARRAY ( nnn )
What language? In assembly addition and subtraction are pretty trivial if
you have a carry bit you can use (not all RISC based CPUs have a carry bit).
Just make sure you keep track of endian issues (given an array A[n] is A[0]
the Most Significant or Least Significant word?).
So, in Intel x86, the addition routine may look like (A[0] = LSW)
multi_byte_add: mov ebx,[esp+8] ; source A value
mov esi,[esp+12] ; source B value
mov edi,[esp+16] ; destination
mov ecx,[esp+20] ; size (in 32-bit words)
clc ; clear carry bit
.mba_loop: mov eax,[ebx]
adc eax,[esi]
mov [edi],eax
lea ebx,[ebx+4]
lea esi,[esi+4]
lea edi,[edi+4]
dec ecx
jnz .mba_loop
ret
Subtraction works simularly. A full multiplication routine is a bit more
daunting---if you know that you are only going to multiply a big number with
a word, then it's a bit easier, but still, it comes down do how one does
multiplication by hand:
A B C D
W X Y Z
---------------------
AZ BZ CZ DZ
AY BY CY DY
AX BX CX DX
AW BW CW DW
(and don't forget the carries!) One trick you might want to try is to take
advantage of the fact that these are binary values so multiplication becomes
shifts and adds but with larger values like these, doing the multibyte
rotates may not be as effective as using the actual MUL instructions.
Division is nasty, but again, works like long division.
Doing this stuff in C is possible, but you loose out in speed big time. A
multibyte addition will look like (warning---untested code! and A[0] = LSW):
#include <limits.h>
void multi_byte_add(unsigned short *s1,unsigned short *s2,unsigned short *dest,size_t
size)
{
int result;
int carry;
for (carry = 0 ; size ; size-- , s1++ , s2++ , dest++)
{
result = *s1 + *s2 + carry;
if ((carry = (result > USHRT_MAX)))
result -= SHRT_MAX;
*dest = (unsigned short)result;
}
}
I have some C code that does some of this---one is a C implementation of a
techique Woz used in calculating e to 100,000 digits (as described in Byte
magazine of either Dec 1980 or Dec 1981) and another one that does division
in C, if you are interested.
-spc (Good luck)