A Quadrature Signals Tutorial: Complex, But Not Complicated

Understanding the 'Phasing Method' of Single Sideband Demodulation

Complex Digital Signal Processing in Telecommunications

Introduction to Sound Processing

Introduction of C Programming for DSP Applications

There are **30** messages in this thread.

You are currently looking at messages 1 to .

**Is this discussion worth a thumbs up?**

Hey guys, I was wondering if you could help me optimize the code below (if possible): R = (B*X); tmp = (int16_t) (R>>15); R = ((int32_t)tmp)+Z; tmp = (int16_t)R; R = (A*((int32_t)Y)); tmp2 = -(int16_t) (R>>15); Rout=tmp+tmp2; Rout is a SINT16 variable containing a Q1.15 value A and B will be replaced by a number between -32768 and 32767 tmp and tmp2 are SINT16 variables; each containing a Q1.15 value Z is a SINT32 variable containing a Q1.15 value Y is a SINT16 variable containing a Q1.15 value R is a SINT32 variable containing the result of an operation on two Q1.15 values X is a SINT32 variable containing a Q1.15 value The above code looks too messy to me and I'm sure it can be optimized..Or maybe I am wrong? Basically I just want to do some operations on Q1.15 numbers in a 32-bit cell. Thank you in advance.

```
On Jun 8, 5:49 am, "Frank" <Fr...@invalidmail.com> wrote:
>
> Basically I just want to do some operations on Q1.15 numbers in a 32-bit
> cell.
so left-justify it and call it a Q1.31 number (where the 16 LSBs are
zero). or right justify it and call it a Q16.16 number.
the code looks like C where you've typedeffed some things.
r b-j
```

On 06/08/2010 02:49 AM, Frank wrote: > Hey guys, > > I was wondering if you could help me optimize the code below (if possible): > > R = (B*X); > tmp = (int16_t) (R>>15); > R = ((int32_t)tmp)+Z; > tmp = (int16_t)R; > R = (A*((int32_t)Y)); > tmp2 = -(int16_t) (R>>15); > Rout=tmp+tmp2; > > Rout is a SINT16 variable containing a Q1.15 value > A and B will be replaced by a number between -32768 and 32767 > tmp and tmp2 are SINT16 variables; each containing a Q1.15 value > Z is a SINT32 variable containing a Q1.15 value > Y is a SINT16 variable containing a Q1.15 value > R is a SINT32 variable containing the result of an operation on two > Q1.15 values > X is a SINT32 variable containing a Q1.15 value > > The above code looks too messy to me and I'm sure it can be > optimized..Or maybe I am wrong? > Basically I just want to do some operations on Q1.15 numbers in a 32-bit > cell. > > Thank you in advance. > > Is this C? Do you have to stick to C? C really doesn't like Q1.anything -- it's only native fixed-point data type is integer, and it sticks to it like glue. You can do fractional fixed-point arithmetic _much_ faster in assembly -- if I'm working with a processor that doesn't have really fast floating point math then I'll write one -- it usually takes less than a day. See chapter 10 of my book -- http://www.wescottdesign.com/actfes/actfes.html -- it presents a Q1.31 library for the x86; if you can understand assembly language programming at all it should make clear what you need to do for Q1.whatever math on your processor. -- Tim Wescott Control system and signal processing consulting www.wescottdesign.com

> Is this C? Do you have to stick to C? It is C and I have to stick to C. >C really doesn't like Q1.anything -- it's only native fixed-point data type >is integer, and it sticks to it like glue. You can do fractional >fixed-point arithmetic _much_ faster in assembly -- if I'm working with a >processor that doesn't have really fast floating point math then I'll write >one -- it usually takes less than a day. I was trying to do it with some defines like these: #define TOQ15(x32) (((int16_t)(x32>>15)) & (int16_t)(((x32>>31)<<15) | 65535)) The idea here is to shift a 32 bit value 15 bits down set bit 15 (the sign bit) correctly. #define MULXY(x16,y16) TOQ15(((int32_t)x16)*((int32_t)y16)) #define ADDXY(x16,y16) TOQ15(((int32_t)x16)+((int32_t)y16)) Some basic operations. However, there seems to be an error in the above defines...Have to debug it... > See chapter 10 of my book -- > http://www.wescottdesign.com/actfes/actfes.html -- it presents a Q1.31 > library for the x86; if you can understand assembly language programming > at all it should make clear what you need to do for Q1.whatever math on > your processor. Thank you. I will have a look at it (even though I still have to do the operations in C)....

```
>so left-justify it and call it a Q1.31 number (where the 16 LSBs are
>zero). or right justify it and call it a Q16.16 number.
Yeah...i guess...but how does that answer my question? :o)
```

On 06/08/2010 09:55 AM, Frank wrote: >> Is this C? Do you have to stick to C? > > It is C and I have to stick to C. > > >> C really doesn't like Q1.anything -- it's only native fixed-point data >> type is integer, and it sticks to it like glue. You can do fractional >> fixed-point arithmetic _much_ faster in assembly -- if I'm working >> with a processor that doesn't have really fast floating point math >> then I'll write one -- it usually takes less than a day. > > I was trying to do it with some defines like these: > > #define TOQ15(x32) (((int16_t)(x32>>15)) & (int16_t)(((x32>>31)<<15) | > 65535)) > > The idea here is to shift a 32 bit value 15 bits down set bit 15 (the > sign bit) correctly. > > #define MULXY(x16,y16) TOQ15(((int32_t)x16)*((int32_t)y16)) > #define ADDXY(x16,y16) TOQ15(((int32_t)x16)+((int32_t)y16)) > > Some basic operations. However, there seems to be an error in the above > defines...Have to debug it... > > >> See chapter 10 of my book -- >> http://www.wescottdesign.com/actfes/actfes.html -- it presents a Q1.31 >> library for the x86; if you can understand assembly language >> programming at all it should make clear what you need to do for >> Q1.whatever math on your processor. > > Thank you. I will have a look at it (even though I still have to do the > operations > in C).... You can do it all in ANSI-C as well (and I show it in the book, although in the context of implementing Q1.31 using long long for arithmetic). I just make functions and a test framework rather than using defines -- even with function call overhead you'll still be way faster than floating point if the processor doesn't support it. You're on the right track. -- Tim Wescott Control system and signal processing consulting www.wescottdesign.com

```
> You're on the right track.
>
Worked on it and came up with these macros:
#define TOQ15(x32) (((x32>>31)<<15)|(x32&0x7fff))
#define MULXY(x32,y32) TOQ15(((x32*y32)>>15))
So when I execute this code:
int16_t x1=-24576; // representing -0.75 in Q1.15
int16_t x2I15; // representing 0.15 in Q1.15
int32_t acc=0; // expected 16bit signed integer value -3687
acc=MULXY(x1,x2);
I get -3687 in acc.....
Any comments ? Have I overlooked something?
```

On 06/08/2010 12:07 PM, Frank wrote: > >> You're on the right track. >> > > Worked on it and came up with these macros: > > #define TOQ15(x32) (((x32>>31)<<15)|(x32&0x7fff)) > #define MULXY(x32,y32) TOQ15(((x32*y32)>>15)) > > So when I execute this code: > > int16_t x1=-24576; // representing -0.75 in Q1.15 > int16_t x2I15; // representing 0.15 in Q1.15 > int32_t acc=0; // expected 16bit signed integer value -3687 > > acc=MULXY(x1,x2); > > I get -3687 in acc..... > > Any comments ? Have I overlooked something? Test the hell out of it. In particular test it for x1 = x2 = 0x8000 -- that's an amazing number in two's complement, and it can cause much grief. -- Tim Wescott Control system and signal processing consulting www.wescottdesign.com

"Frank" <F...@invalidmail.com> writes: >> You're on the right track. >> > > Worked on it and came up with these macros: > > #define TOQ15(x32) (((x32>>31)<<15)|(x32&0x7fff)) > #define MULXY(x32,y32) TOQ15(((x32*y32)>>15)) > > So when I execute this code: > > int16_t x1=-24576; // representing -0.75 in Q1.15 > int16_t x2I15; // representing 0.15 in Q1.15 > int32_t acc=0; // expected 16bit signed integer value -3687 > > acc=MULXY(x1,x2); > > I get -3687 in acc..... > > Any comments ? Have I overlooked something? Hi Frank, You're making a mess! First note that the compiler promotes the 16x16 bit multiply to a 32-bit result in MULXY. Then note that shifting a 32-bit value right 31 bits makes the LSB of the result either 0 or 1. Since these are signed values, the compiler sign-extends the shift. Shifting 0 or 1 back left 15 bits gives you 0 or -32768, respectively. OR'ing that with the x32&0x7FFF buys you nothing. So all the work is really done in the argument to TOQ15, x32*y32 >> 15, which is the right way to multiply two Q1.15 numbers and get a Q17.15 result. -- Randy Yates % "So now it's getting late, Digital Signal Labs % and those who hesitate mailto://y...@ieee.org % got no one..." http://www.digitalsignallabs.com % 'Waterfall', *Face The Music*, ELO

Tim Wescott <t...@seemywebsite.now> writes: > [...] > Is this C? Do you have to stick to C? C really doesn't like > Q1.anything -- it's only native fixed-point data type is integer, and > it sticks to it like glue. Er, all fixed-point processing uses plain integer operations. Fixed-point is all in how you interpret things. There is nothing inherently "non-fixed-point" in C. C is just fine for fixed-point processing. -- Randy Yates % "Maybe one day I'll feel her cold embrace, Digital Signal Labs % and kiss her interface, mailto://y...@ieee.org % til then, I'll leave her alone." http://www.digitalsignallabs.com % 'Yours Truly, 2095', *Time*, ELO