Prev: Kenlighten - A social network for knowledge seekers and providers
Next: help on abs() within matlab
From: Tim Wescott on 8 Jun 2010 14:18 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
From: Frank on 8 Jun 2010 15:07 > 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 x2=4915; // 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?
From: Tim Wescott on 8 Jun 2010 18:24 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 x2=4915; // 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
From: Randy Yates on 8 Jun 2010 21:51 "Frank" <Frank(a)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 x2=4915; // 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://yates(a)ieee.org % got no one..." http://www.digitalsignallabs.com % 'Waterfall', *Face The Music*, ELO
From: Randy Yates on 8 Jun 2010 21:58
Tim Wescott <tim(a)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://yates(a)ieee.org % til then, I'll leave her alone." http://www.digitalsignallabs.com % 'Yours Truly, 2095', *Time*, ELO |