Jack Klein said:
Eric Sosman said:
Randy Yates wrote:
Consider the following code:
#include "dsptypes.h"
Nice of you to hide the crucial details where
nobody can see them ...
/* definitions */
#define VECTOR_LENGTH 64
/* local variables */
/* local function prototypes */
/* function definitions */
int main(int margc, char **margv)
{
UINT16_T n;
INT16_T x[VECTOR_LENGTH];
INT16_T y[VECTOR_LENGTH];
INT32_T acc;
INT16_T result;
acc = 0;
for (n = 0; n < VECTOR_LENGTH; n++)
{
x[n] = n;
y[n] = VECTOR_LENGTH - n - 1;
}
acc = 0;
for (n = 0; n < VECTOR_LENGTH; n++)
{
acc += x[n] * y[n];
}
result = (INT16_T)(acc >> 16);
return result;
}
What does ISO C say about how the conversions in the
acc += x[n] * y[n];
line are to be done? Specifically, is the multiply to be done with 16
bits, then the result promoted to 32 bits, or are x and y first to be
promoted to 32 bits before the multiply? Does the standard specify?
Unanswerable with the information provided: you
haven't revealed what INT16_T and INT32_T are.
If INT16_T is `short' and INT32_T is `int', the
two array elements are promoted to `int', multiplied
to produce a 32-bit product, and added to `acc'.
If INT16_T is `int' and INT32_T is `long', the
two array elements are not promoted, the multiplication
produces a 16-bit product, and finally the product is
promoted to `long' and added to `acc'.
If ... ah, pfui. I'm tired of running through all
the possible combinations; look 'em up yourself.
Gladly, but I don't have the spec, and I understand it's
not cheap.
Here are the relevent typedefs:
typedef short INT16_T;
typedef long INT32_T;
Unfortunately, that does not provide enough information to answer your
question. Either short or long happens to have the same size and
representation as int on your platform, and that is what matters.
On a 32 bit desktop/DSP/micro where int is 32 bits, same as long, then
the two 16-bit shorts will be promoted to 32-bit ints before the
multiplication and it will produce a 32-bit result, as you probably
want.
On an 8-bit or 16-bit micro/DSP where int has 16 bits, those two
16-bit shorts are still "promoted" to ints, but since ints also have
16 bits the promotion is in theory only. The result will be a 16x16
multiply with a 16-bit result.
Some early compilers for the TI 28xx DSP actually got this wrong, if
you compiled with no optimization, and if you stored the result of a
16x16 multiply into a 32-bit object, it actually stored the entire 32
bit contents of the accumulator. That is actually an example of
non-conformance with the C standard, and they fixed it in later
versions.
Thanks for the response, Jack. In fact it is the TI 54xx compiler I
was using. For the following C code,
#include "dsptypes.h"
/* definitions */
#define VECTOR_LENGTH 64
/* local variables */
/* local function prototypes */
/* function definitions */
int main(int margc, char **margv)
{
UINT16_T n;
INT16_T x[VECTOR_LENGTH];
INT16_T y[VECTOR_LENGTH];
INT32_T acc;
INT16_T result;
acc = 0;
for (n = 0; n < VECTOR_LENGTH; n++)
{
x[n] = n;
y[n] = VECTOR_LENGTH - n - 1;
}
acc = 0;
for (n = 0; n < VECTOR_LENGTH; n++)
{
acc += x[n] * y[n];
}
result = (INT16_T)(acc >> 16);
return result;
}
that compiler produced the following assembly
0000:0108 main
0000:0108 4A11 PSHM 11h
0000:0109 4A17 PSHM 17h
0000:010A EE80 FRAME -128
0000:010B E781 MVMM SP,AR1
0000:010C 6DE9 MAR *+AR1(64)
0000:010E E787 MVMM SP,AR7
0000:010F E782 MVMM SP,AR2
0000:0110 E800 LD #0h,A
0000:0111 771A STM 3fh,1ah
0000:0113 F072 RPTB 11ah
0000:0115 L1
0000:0115 8092 STL A,*AR2+
0000:0116 E93F LD #3fh,B
0000:0117 F520 SUB A,0,B
0000:0118 8191 STL B,*AR1+
0000:0119 F000 ADD #1h,0,A,A
0000:011B L2
0000:011B E782 MVMM SP,AR2
0000:011C 6DEA MAR *+AR2(64)
0000:011E E783 MVMM SP,AR3
0000:011F E800 LD #0h,A
0000:0120 EC3F RPT #3fh
0000:0121 L3
0000:0121 B089 MAC *AR2+,*AR3+,A,A
0000:0122 L4
0000:0122 F0E0 SFTL A,0,A
0000:0123 F0F0 SFTL A,-16,A
0000:0124 6BF8 ADDM 80h,*(18h)
0000:0127 F495 NOP
0000:0128 F495 NOP
0000:0129 8A17 POPM 17h
0000:012A 8A11 POPM 11h
0000:012B F4E4 FRET
It is obvious here that the two shorts are multiplied using
32-bit accuracy, not 16. The C manual for the 54x states that
an int is 16 bits. So isn't this compiler in violation of
the ANSI standard as well?