Im trying to write an big integer multiplication for my first test its working but if the uint8_t number is more than one than the result is wrong. I tried it 2 days to find a solution and to understand what Im doing wrong...
void main(void){
uint8_t x[] = {0xFF};
uint8_t y[] = {0xFF};
uint8_t z[] = {0x00, 0x00};
mul(x,1,y,1,z);
printf("X*Y = Z: ");
for(int i = 0; i < 2; i )
printf("X ",z[i]);
printf("\n");
//Output: X*Y = Z: FE 01 == FE01 CORRECT!
uint8_t a[] = {0x0F, 0xFF};
uint8_t b[] = {0x0F, 0xFF};
uint8_t c[] = {0x00, 0x00, 0x00, 0x00};
mul(a,2,b,2,c);
printf("A*B = C: ");
for(int i = 0; i < 4; i )
printf("X ",c[i]);
printf("\n");
//Output: A*B = C: 00 FE E0 01 != FFE001 WRONG?!
}
void mul(uint8_t *a, int a_n,uint8_t *b, int b_n,uint8_t *c){
int i,j;
uint16_t A;
for(i = a_n-1; i >= 0; i--){
A=0;
for(j = b_n-1; j >= 0; j--){
A = (uint16_t) a[i] * b[j];
c[i j 1] = A;
A >>= 8;
}
c[i] = A;;
}
}
CodePudding user response:
At least 1 problem:
Overflow in c[]
c[i j 1] = A;
may overflow c[]
. @Barmar
// A = (uint16_t) a[i] * b[j];
// c[i j 1] = A;
// A >>= 8;
A = (uint16_t) a[i] * b[j] A c[i j 1];
c[i j 1] = A & 0xFFu; // or A % 256u
A >>= 8;
Sample fixed code (with other minor improvements)
// Using re-ordered parameters for better static code analysis
// Use const
// Idiomatic to use size_t for array sizing/indexing
// Perhaps return c[] to allow for chained calls.
uint8_t *mul(size_t a_n, const uint8_t a[a_n], size_t b_n, const uint8_t b[b_n],
uint8_t c[a_n b_n]) {
for (size_t i = a_n; i-- > 0;) {
unsigned A = 0; // Let compiler use the natural unsigned rather than force uint16_t
for (size_t j = b_n; j-- > 0;) {
A = 1u * a[i] * b[j] c[i j 1]; // 1u * vs. cast, let compiler optimize
c[i j 1] = A & 0xFFu;
A >>= 8;
}
c[i] = A;
}
return c;
}