In general there is no easy way to do this.
Firstly you need to implement the multiply with carry between A and B for each uint8_t block. See the answer here.
Division with 2^16
really mean "disregard" the last 16 bits, "don't use" the last two uint8_t
(as you use the array of int.). As you have the modulus operator, this means just the opposite, so you only need to get the last two uint8_t
s.
Take the lowest two uint8
of A
(say a0
and a1
) and B
(say b0
and b1
):
split each uint8
in high and low part
a0h = a0 >> 4; ## the same as a0h = a0/16;
a0l = a0 % 16; ## the same as a0l = a0 & 0x0f;
a1h = a1 >> 4;
a1l = a1 % 16;
b0h = b0 >> 4;
b0l = b0 % 16;
b1h = b1 >> 4;
b1l = b1 % 16;
Multiply the lower parts first (x
is a buffer var)
x = a0l * b0l;
The first part of the result is the last four bits of x
, let's call it s0l
s0l = x % 16;
The top for bits of x
are carry.
c = x>>4;
multiply the higher parts of first uint8
and add carry.
x = (a0h * b0h) + c;
The first part of the result is the last four bits of x
, let's call it s0h
. And we need to get carry again.
s0h = x % 16;
c = x>>4;
We can now combine the s0
:
s0 = (s0h << 4) + s0l;
Do exactly the same for the s1 (but don't forget to add the carry!):
x = (a1l * b1l) + c;
s1l = x % 16;
c = x>>4;
x = (a1h * b1h) + c;
s1h = x % 16;
c = x>>4;
s1 = (s1h << 4) + s1l;
Your result at this point is c
, s1
and s0
(you need carry for next multiplications eg. s2
, s3
, s4
,). As your formula says %(2^16) you already have your result - s1
and s2
. If you have to divide with something else, you should do something similar to the code above, but for division. In this case be careful to catch the dividing with zero, it will give you NAN
or something!
You can put A, B, C and S in array and loop it through the indexes to make code cleaner.