The assignment short int b=0xc000;
alone is already implementation defined (vid.: ISO/IEC 9899:2018 6.3.1.3 p. 3) and would need to be done in two parts b = b1 * 2^15 + b0 = 0x1*2^15 + 0x4000
(assuming SHRT_MAX + 1 == 32768
). If you do both in two parts like that and understand the assignment in such a way that the result is an unsigned data type and do a*b == (a1 * 2^15 + a0) * (b1 * 2^15 + b0)
by using unsigned int ret2
for the result and signed int
temporary variables for the rest.
Assuming that the input is restricted to the capabilities of an unsigned short int
(unsigned
because of 0xc000
) and that all types must be signed types with the exception of the output:
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
int main(void)
{
/*
This whole thing has ben pulled apart for clarity and could (should!) be done
in less lines of code.
All implicit type conversions are made explicit.
We also assume 2s complement (and a little bit more, to be honest).
*/
/*
A and B limited to 0xffff to keep this code simple.
If you want to get rid of these limits you need to count the bits
of A and B and make sure that the sum does not exceed sizeof(int)*CHAR_BIT-1
*/
signed int A = 0x7fff;
signed int B = 0xc000;
short int a0, a1;
short int b0, b1;
signed int shift = SHRT_MAX+1;
unsigned int res1, res2;
/* Additional temporary variables for legibility */
signed int t0, t1, t2, t3;
/* Check input range */
if ((A > 0xffff) || (B > 0xffff)) {
fprintf(stderr,"Input must not exceed 0xffff! A = 0x%x, B = 0x%x\n",A,B);
exit(EXIT_FAILURE);
}
//unsigned multiplier
res1 = (unsigned int)A * (unsigned int)B;
//signed multiplier
/* Compute A*B == (a1 * shift + a0) * (b1 * shift + b0) */
a0 = (short int)(A % shift);
a1 = (short int)(A / shift);
b0 = (short int)(B % shift);
b1 = (short int)(B / shift);
/*
Multiply out for convenience:
A*B == (a1 * 2^15 + a0) * (b1 * 2^15 + b0)
== a1 * b1 *2^15 * 2^15
+ a0 * b1 * 2^15
+ a1 * b0 * 2^15
+ a0 * b0
*/
/*
Here a1 and b1 are either 0 (zero) or 1 (one) and (SHRT_MAX+1)^2 < INT_MAX
so t0 cannot overflow.
You should make use of that fact in production.
*/
t0 = (signed int)a1 * (signed int)b1 * shift * shift; /* t0 in {0,shift^2} */
t1 = (signed int)a0 * (signed int)b1 * shift; /* t1 in {0, a0 * shift} */
t2 = (signed int)a1 * (signed int)b0 * shift; /* t2 in {0, b0 * shift} */
t3 = (signed int)a0 * (signed int)b0; /* t3 can get larger than INT_MAX! */
/* Cannot overflow because floor(sqrt(2^32-1)) = 0xffff and both A and B < 0xfff */
res2 = (unsigned int)t0 + (unsigned int)t1 + (unsigned int)t2 + (unsigned int)t3;
printf("res1: 0x%x %d\nres2: 0x%x %d\n",res1, res1, res2, res2);
exit(EXIT_SUCCESS);
}
The assignment is rather under-defined, to keep it polite, but as I do not know if it is your fault, the teacher's fault or a bad zoom-connection I tried to give you a couple of directions. If it wasn't wat was expected you should at least be able to ask the right questions now.