DSPRelated.com
Forums

Q1.15 calculation

Started by Frank June 8, 2010
On 06/09/2010 03:22 PM, Raymond Toy wrote:
> On 6/9/10 10:33 AM, Tim Wescott wrote: >> >> So generally on an 8- or 16-bit machine the tools will set short and int >> to 16 bits, and long to 32. On a 64-bit machine, everything will be 64 >> bits. > > Did you really mean a 64-bit machine uses 64 bits for short and int and > long? That's not true for every 64-bit machine. Don't most C compilers > for 64-bit machines have 16-bit shorts, 32-bit ints, and 64-bit longs?
I was generalizing. Probably most C compilers for 64-bit byte-addressed machines will do it the way you said (plus 8-bit characters). But if it's a 64-bit word-addressed machine, then everything including chars will be 64-bit. -- Tim Wescott Control system and signal processing consulting www.wescottdesign.com
Tim Wescott <tim@seemywebsite.now> wrote:
(snip, someone wrote)

>> Did you really mean a 64-bit machine uses 64 bits for short and int and >> long? That's not true for every 64-bit machine. Don't most C compilers >> for 64-bit machines have 16-bit shorts, 32-bit ints, and 64-bit longs?
> I was generalizing. Probably most C compilers for 64-bit byte-addressed > machines will do it the way you said (plus 8-bit characters). But if > it's a 64-bit word-addressed machine, then everything including chars > will be 64-bit.
I believe that some Cray machines (not currently in production) are 64 bit word addressed. But even that doesn't mean that all the types need to be word sized. There are C compilers for the 36 bit word addressed PDP-10 that use, I believe, 9 bits for char. It is a little tricky, but it can be done. -- glen
On 06/09/2010 04:46 PM, glen herrmannsfeldt wrote:
> Tim Wescott<tim@seemywebsite.now> wrote: > (snip, someone wrote) > >>> Did you really mean a 64-bit machine uses 64 bits for short and int and >>> long? That's not true for every 64-bit machine. Don't most C compilers >>> for 64-bit machines have 16-bit shorts, 32-bit ints, and 64-bit longs? > >> I was generalizing. Probably most C compilers for 64-bit byte-addressed >> machines will do it the way you said (plus 8-bit characters). But if >> it's a 64-bit word-addressed machine, then everything including chars >> will be 64-bit. > > I believe that some Cray machines (not currently in production) > are 64 bit word addressed. But even that doesn't mean that > all the types need to be word sized. > > There are C compilers for the 36 bit word addressed PDP-10 that > use, I believe, 9 bits for char. It is a little tricky, but > it can be done.
It depends on how hard the compiler writer wants to work for it. In C, a pointer has to fit in a long, and it has to be able to point to a unique character. If you want to use a smaller element of storage than what the machine points to natively, you have to kludge up your own pointer representation, and use it _everywhere_, or have a non-compliant compiler. -- Tim Wescott Control system and signal processing consulting www.wescottdesign.com
Tim Wescott <tim@seemywebsite.now> writes:

> On 06/08/2010 06:58 PM, Randy Yates wrote: >> Tim Wescott<tim@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. > > In most processor instruction sets, multiplying two N-bit registers > coughs up an 2*N bit answer. In most of the rest there's a "multiply > and return high" and a "multiply and return low". In most of the slim > remainder (getting fatter with all the fixed point DSP's out there) > there is some fast way of getting one or the other part -- including > many DSP chips that have a straight "multiply fractional and > accumulate"
I've worked on the TI C5x, C55x, C64x, ADI SHARC 21369, and TigerSHARC TS201. I've not seen a "multiply fractional and accumulate" on these. Can you give me an example? Yes, the old Moto 56k did an automatic shift left by one. That's one out of how many? It's not the norm.
> or "multiply with shift and accumulate".
There is an option on several for automatically shifting right by 1 after multiplying so the result is fractional. Is that what you mean? If so, that's hardly a great reason for avoiding fixed-point in C. I'm the last person in the world that would advocate C over assembly. But in this case, it's usually justified.
> C discards the high half, and returns the low.
Are you really complaining this hard about having to do an explicit typecast? (See my other post tonight for an example.)
> For fractional arithmetic, you want the high half, shifted up one.
Big whup.
> C is just fine for _integer_ processing, but wastes a lot of steps for > fixed point _fractional_ processing.
Maybe one or two, and maybe not even that. It depends on how smart the compiler is, e.g., can it utilize the auto-left-shift mode present in some fixed-point processors. But in any case, I don't call that "a lot." Also, there are many cases (most?) where you are not just doing one multiply and then socking away the result, but rather a series of multiplies. In those cases the extra shift is amortized over the whole block of instructions and is hard worth noting. One thing that *is* rather expensive in fixed-point processing that I've not heard mentioned is saturating. Yes, if you're implementing an equalizer with lots of saturates, shifts, etc., at a high sample rate in a tight inner loop on a small fixed-point DSP with power constraints, yada yada yada, it's going to be worth going to assembly. That's hardly the norm, though. -- Randy Yates % "How's life on earth? Digital Signal Labs % ... What is it worth?" mailto://yates@ieee.org % 'Mission (A World Record)', http://www.digitalsignallabs.com % *A New World Record*, ELO
Randy Yates <yates@ieee.org> writes:

> There is an option on several for automatically shifting > right by 1 after multiplying so the result is fractional. > Is that what you mean?
Correction: left by 1. -- Randy Yates % "She tells me that she likes me very much, Digital Signal Labs % but when I try to touch, she makes it mailto://yates@ieee.org % all too clear." http://www.digitalsignallabs.com % 'Yours Truly, 2095', *Time*, ELO
On 6/9/10 7:52 PM, Tim Wescott wrote:
> On 06/09/2010 04:46 PM, glen herrmannsfeldt wrote: >> Tim Wescott<tim@seemywebsite.now> wrote: >> (snip, someone wrote) >> >>>> Did you really mean a 64-bit machine uses 64 bits for short and int and >>>> long? That's not true for every 64-bit machine. Don't most C >>>> compilers >>>> for 64-bit machines have 16-bit shorts, 32-bit ints, and 64-bit longs? >> >>> I was generalizing. Probably most C compilers for 64-bit byte-addressed >>> machines will do it the way you said (plus 8-bit characters). But if >>> it's a 64-bit word-addressed machine, then everything including chars >>> will be 64-bit. >> >> I believe that some Cray machines (not currently in production) >> are 64 bit word addressed. But even that doesn't mean that >> all the types need to be word sized. >> >> There are C compilers for the 36 bit word addressed PDP-10 that >> use, I believe, 9 bits for char. It is a little tricky, but >> it can be done. > > It depends on how hard the compiler writer wants to work for it. In C, > a pointer has to fit in a long, and it has to be able to point to a > unique character. If you want to use a smaller element of storage than > what the machine points to natively, you have to kludge up your own > pointer representation, and use it _everywhere_, or have a non-compliant > compiler. >
Long ago I used a 24-bit word addressable machine. It had 8-bit chars that were packed into a word. I don't remember exactly how it worked, but you could address each char. Somehow a 24-bit address indicated which char. It was a pretty bizarre architecture. The Fortran compiler supported integer*3 and integer*6, but integer*6 wasn't twice the size of integer*3. Two words were used, but some bits weren't used, so the max size was less than 2^48. This was long ago. I might have gotten the details wrong. Ray
Randy Yates <yates@ieee.org> writes:
> [...]
I should also add that I use stdint.h extensively. It's the mostest wonderfullest thing that's happened to C in 3 decades. --Randy
> Tim Wescott <tim@seemywebsite.now> writes: > >> On 06/08/2010 06:58 PM, Randy Yates wrote: >>> Tim Wescott<tim@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. >> >> In most processor instruction sets, multiplying two N-bit registers >> coughs up an 2*N bit answer. In most of the rest there's a "multiply >> and return high" and a "multiply and return low". In most of the slim >> remainder (getting fatter with all the fixed point DSP's out there) >> there is some fast way of getting one or the other part -- including >> many DSP chips that have a straight "multiply fractional and >> accumulate" > > I've worked on the TI C5x, C55x, C64x, ADI SHARC 21369, and TigerSHARC > TS201. I've not seen a "multiply fractional and accumulate" on these. > Can you give me an example? Yes, the old Moto 56k did an automatic > shift left by one. That's one out of how many? It's not the norm. > >> or "multiply with shift and accumulate". > > There is an option on several for automatically shifting > right by 1 after multiplying so the result is fractional. > Is that what you mean? > > If so, that's hardly a great reason for avoiding fixed-point > in C. > > I'm the last person in the world that would advocate C over > assembly. But in this case, it's usually justified. > >> C discards the high half, and returns the low. > > Are you really complaining this hard about having to do an explicit > typecast? (See my other post tonight for an example.) > >> For fractional arithmetic, you want the high half, shifted up one. > > Big whup. > >> C is just fine for _integer_ processing, but wastes a lot of steps for >> fixed point _fractional_ processing. > > Maybe one or two, and maybe not even that. It depends on how smart the > compiler is, e.g., can it utilize the auto-left-shift mode present in > some fixed-point processors. But in any case, I don't call that "a > lot." > > Also, there are many cases (most?) where you are not just doing one > multiply and then socking away the result, but rather a series of > multiplies. In those cases the extra shift is amortized over the > whole block of instructions and is hard worth noting. > > One thing that *is* rather expensive in fixed-point processing that I've > not heard mentioned is saturating. Yes, if you're implementing an > equalizer with lots of saturates, shifts, etc., at a high sample rate in > a tight inner loop on a small fixed-point DSP with power constraints, > yada yada yada, it's going to be worth going to assembly. That's hardly > the norm, though.
-- Randy Yates % "How's life on earth? Digital Signal Labs % ... What is it worth?" mailto://yates@ieee.org % 'Mission (A World Record)', http://www.digitalsignallabs.com % *A New World Record*, ELO
Tim Wescott <tim@seemywebsite.now> wrote:
(snip, I wrote)

>> I believe that some Cray machines (not currently in production) >> are 64 bit word addressed. But even that doesn't mean that >> all the types need to be word sized.
>> There are C compilers for the 36 bit word addressed PDP-10 that >> use, I believe, 9 bits for char. It is a little tricky, but >> it can be done.
> It depends on how hard the compiler writer wants to work for it. In C, > a pointer has to fit in a long, and it has to be able to point to a > unique character. If you want to use a smaller element of storage than > what the machine points to natively, you have to kludge up your own > pointer representation, and use it _everywhere_, or have a non-compliant > compiler.
C allows for a different representation for different pointers, as long as the casts work right. One possibility is to use high order bits for the character in word. The basic PDP-10 addressing is 18 bits in the low half of the word, so it isn't so hard to do. -- glen
glen herrmannsfeldt <gah@ugcs.caltech.edu> writes:

> Randy Yates <yates@ieee.org> wrote: > (snip) > >> Er, all fixed-point processing uses plain integer >> operations. Fixed-point is all in how you interpret things. > > Yes, but you need different product bits for multiply,
Then tell me glen what's the difference between the result of a fixed-point product and an integer product? -- Randy Yates % "My Shangri-la has gone away, fading like Digital Signal Labs % the Beatles on 'Hey Jude'" mailto://yates@ieee.org % http://www.digitalsignallabs.com % 'Shangri-La', *A New World Record*, ELO
In article <4c0e124a$0$272$14726298@news.sunsite.dk>,
Frank <Frank@invalidmail.com> 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;
The first thing is to get rid of the casts. They don't generate code, they just supress warnings. But you want to hear the warnings! The second is to inspect the assembly code generated. The code must be the same after getting rid of the casts. Furthermore the assembler code may be much easier to understand. Secondly, I can't believe that you supply this code without the declarations of R and tmp. But of course R is 32 bit and tmp is 16 bit. Make tmp 32 bit and we need not worry about a thing. Thirdly extract the formula: Scale = 1<<15 result = (B*X)/scale + (A*Y)/scale + Z So apparently we are talking about fixed point numbers. If we multiply them we need to scale them back, but this may require a double precision intermediate result. In Forth this would be \ Fixed point multiplication : *F $8000 */ ; \ And then the code looks like this: : calc A X *F B Y *F + Z + ;
>The above code looks too messy to me and I'm sure it can be optimized..Or >maybe I am wrong?
This code looks messy, so surely it is "optimized".
>Basically I just want to do some operations on Q1.15 numbers in a 32-bit >cell. > >Thank you in advance.
This triggers me to throw a rant that belongs in comp.lang.c int sf( int B, X ) { long R; int result; R = (B*X)/$8000; result = R; return; } This code has a defect and will generate the warning result = R conversion of int to a long without a cast, might not fit. This is stupid. If I store the result of a long in an int, that is what I want to do. Of course I have checked that it fits. Even more stupid, is a management that wants a clean compile, without warnings, such that a cast is added to this line. The poor programmer wastes his time, and the defect is not cured. The line that is wrong is R = (B*X)/0x8000; I have never seen the warning: Possible overflow on intermediate result. Correct code would be (long calculations throughout) R = B; R *= X; R /= 0x8000; Groetjes Albert -- -- Albert van der Horst, UTRECHT,THE NETHERLANDS Economic growth -- being exponential -- ultimately falters. albert@spe&ar&c.xs4all.nl &=n http://home.hccnet.nl/a.w.m.van.der.horst