hi,i have a simple question,please help me.
in C language how to multiply two numbers in Q15 and save the result in a
Q15 number?
For example, consider the following program:
short dly,h;
void main()
{
dly=-14;//Q15//fraction=-0.000427//
main
ST #0fff2h,*(dly)
h=-29772;//Q15//fraction=-0.9.8569h
//* ST #8BB4h,*(h)
yn=(h*dly);
//* LD *(dly),T
//* MPY *(h),AA
//* STL A,*(bss)
}
I want this product in a real number is stored. But with the above
instructions, only low sixteen bits of the result is stored.while I am
interested in the top sixteen bits.
please,help me.
store multiply in a Q number
Started by ●August 19, 2010
Reply by ●August 19, 20102010-08-19
On Aug 19, 7:07=A0am, "mahsad" <mahdi_kbm@n_o_s_p_a_m.yahoo.com> wrote:> hi,i have a simple question,please help me. > in C language how to multiply two numbers in Q15 and save the result in a > Q15 number? > For example, consider the following program: > > =A0 =A0short dly,h; > void main() > { > dly=3D-14;//Q15//fraction=3D-0.000427// > =A0 main > =A0 =A0 =A0 =A0 =A0 =A0 =A0ST #0fff2h,*(dly) > =A0h=3D-29772;//Q15//fraction=3D-0.9.8569h > =A0 =A0 =A0 =A0 =A0 =A0//* ST =A0#8BB4h,*(h) > yn=3D(h*dly); > =A0 =A0 =A0 =A0 =A0 //* =A0LD =A0*(dly),T > =A0 =A0 =A0 =A0 =A0 //* =A0MPY *(h),AA > =A0 =A0 =A0 =A0 =A0 //* STL =A0A,*(bss) =A0} > > I want this product in a real number is stored. But with the above > instructions, only low sixteen bits of the result is stored.while I am > interested in the top sixteen bits. > please,help me.Q15 multiplication in goes like this yn =3D ((long)h * (long)dly) >> 15;
Reply by ●August 19, 20102010-08-19
On Aug 19, 1:40=A0am, Korenje <kore...@yahoo.co.uk> wrote:> On Aug 19, 7:07=A0am, "mahsad" <mahdi_kbm@n_o_s_p_a_m.yahoo.com> wrote: > > > > > hi,i have a simple question,please help me. > > in C language how to multiply two numbers in Q15 and save the result in=a> > Q15 number? > > For example, consider the following program: > > > =A0 =A0short dly,h; > > void main() > > { > > dly=3D-14;//Q15//fraction=3D-0.000427// > > =A0 main > > =A0 =A0 =A0 =A0 =A0 =A0 =A0ST #0fff2h,*(dly) > > =A0h=3D-29772;//Q15//fraction=3D-0.9.8569h > > =A0 =A0 =A0 =A0 =A0 =A0//* ST =A0#8BB4h,*(h) > > yn=3D(h*dly); > > =A0 =A0 =A0 =A0 =A0 //* =A0LD =A0*(dly),T > > =A0 =A0 =A0 =A0 =A0 //* =A0MPY *(h),AA > > =A0 =A0 =A0 =A0 =A0 //* STL =A0A,*(bss) =A0} > > > I want this product in a real number is stored. But with the above > > instructions, only low sixteen bits of the result is stored.while I am > > interested in the top sixteen bits. > > please,help me. > > Q15 multiplication in goes like this > > yn =3D ((long)h * (long)dly) >> 15;in fact, you might want to round to nearest like this: yn =3D ((long)h * (long)dly + 0x4000) >> 15; maybe half the time you want to do it this way: yn =3D ((long)h * (long)dly + 0x3FFF) >> 15; it really only makes a difference when the bottom 15 bits are 0x4000 and you are exactly midway between the two possible rounded numbers. r b-j
Reply by ●August 19, 20102010-08-19
On 08/18/2010 10:48 PM, robert bristow-johnson wrote:> On Aug 19, 1:40 am, Korenje<kore...@yahoo.co.uk> wrote: >> On Aug 19, 7:07 am, "mahsad"<mahdi_kbm@n_o_s_p_a_m.yahoo.com> wrote: >> >> >> >>> hi,i have a simple question,please help me. >>> in C language how to multiply two numbers in Q15 and save the result in a >>> Q15 number? >>> For example, consider the following program: >> >>> short dly,h; >>> void main() >>> { >>> dly=-14;//Q15//fraction=-0.000427// >>> main >>> ST #0fff2h,*(dly) >>> h=-29772;//Q15//fraction=-0.9.8569h >>> //* ST #8BB4h,*(h) >>> yn=(h*dly); >>> //* LD *(dly),T >>> //* MPY *(h),AA >>> //* STL A,*(bss) } >> >>> I want this product in a real number is stored. But with the above >>> instructions, only low sixteen bits of the result is stored.while I am >>> interested in the top sixteen bits. >>> please,help me. >> >> Q15 multiplication in goes like this >> >> yn = ((long)h * (long)dly)>> 15; > > in fact, you might want to round to nearest like this: > > yn = ((long)h * (long)dly + 0x4000)>> 15; > > maybe half the time you want to do it this way: > > yn = ((long)h * (long)dly + 0x3FFF)>> 15; > > it really only makes a difference when the bottom 15 bits are 0x4000 > and you are exactly midway between the two possible rounded numbers.Note that with most C compilers you're better off writing an assembly language library to do this for you if you want the last little bit of speed. One chapter of my book is devoted to fractional arithmetic (I should have used "Q31" notation); in it I have an ANSI C implementation and an example implementation for 32-bit x86 machines. -- Tim Wescott Wescott Design Services http://www.wescottdesign.com Do you need to implement control loops in software? "Applied Control Theory for Embedded Systems" was written for you. See details at http://www.wescottdesign.com/actfes/actfes.html
Reply by ●August 19, 20102010-08-19
robert bristow-johnson <rbj@audioimagination.com> wrote:>in fact, you might want to round to nearest like this: > > yn = ((long)h * (long)dly + 0x4000) >> 15; > >maybe half the time you want to do it this way: > > yn = ((long)h * (long)dly + 0x3FFF) >> 15; > >it really only makes a difference when the bottom 15 bits are 0x4000 >and you are exactly midway between the two possible rounded numbers.This is (one of the reasons) why you should use System C / IEEE 1666 instead of Q notation; the rounding modes are defined and there is no ambiguity. (SC_RND, i.e. rounding towards positive infinity, is what you want to do 99% of the time if you're trying to model hardware.) Q notation should be sunsetted. Steve
Reply by ●August 19, 20102010-08-19
On Aug 19, 1:58=A0am, spop...@speedymail.org (Steve Pope) wrote:> robert bristow-johnson =A0<r...@audioimagination.com> wrote: > > >in fact, you might want to round to nearest like this: > > > =A0 yn =3D ((long)h * (long)dly + 0x4000) >> 15; > > >maybe half the time you want to do it this way: > > > =A0 yn =3D ((long)h * (long)dly + 0x3FFF) >> 15; > > >it really only makes a difference when the bottom 15 bits are 0x4000 > >and you are exactly midway between the two possible rounded numbers. > > This is (one of the reasons) why you should use System C / IEEE 1666 > instead of Q notation; the rounding modes are defined and there is > no ambiguity.sometimes ambiguity is a good thing. that's the whole idea of using dither. long ago, i wrote a fixed-point library in C that used a random number generator instead of 0x4000 to round. so it didn't have repeatability unless you reset the RNG seed for each run.> =A0(SC_RND, i.e. rounding towards positive infinity,+inf ??> is what you want to do 99% of the time if you're trying to model > hardware.)why would 99% of hardware always round up? i could see a large proportion always rounding down (you just drop the bits), but always rounding up takes more work. you have to add something before losing the low-order bits.> Q notation should be sunsetted.it's just a notation. it's not like it represents an obsoleted technology that should be sunsetted, no? r b-j
Reply by ●August 19, 20102010-08-19
robert bristow-johnson <rbj@audioimagination.com> wrote:>On Aug 19, 1:58�am, spop...@speedymail.org (Steve Pope) wrote:>> �(SC_RND, i.e. rounding towards positive infinity,>+inf ??>> is what you want to do 99% of the time if you're trying to model >> hardware.)>why would 99% of hardware always round up? i could see a large >proportion always rounding down (you just drop the bits), but always >rounding up takes more work. you have to add something before losing >the low-order bits.You're right that truncation (which could be called "rounding down" but I prefer truncation) is also very common. But if one is rounding instead of truncating, it is usually simplest in hardware to take the most significant bit among those truncated, and add it to the truncated result to obtain a rounded result. This happens to be the same as SC_RND for both unsigned values, and 2's complement values. (Here's a graphic on SC_RND: slide 34 of http://www2.itu.edu.tr/~orssi/dersler/SLD/systemc1.pdf . Note that the author believes SC_RND is "what you expect". I think the System C designers felt the same way, as they gave it the shortest moniker among the different rounding modes.)>> Q notation should be sunsetted.>it's just a notation. it's not like it represents an obsoleted >technology that should be sunsetted, no?I can see that; however when the world has gravitated to a standard that states the number of integer bits along with the number of total bits, it can be confusing to use an older notation that instead states the number of fractional bits. OTOH a lot of engineering involves juggling different notations, so why not. Steve
Reply by ●August 19, 20102010-08-19
Tim Wescott <tim@seemywebsite.com> wrote: (snip, someone wrote)>>> Q15 multiplication in goes like this>>> yn = ((long)h * (long)dly)>> 15;(snip)> Note that with most C compilers you're better off writing an assembly > language library to do this for you if you want the last little bit of > speed. One chapter of my book is devoted to fractional arithmetic (I > should have used "Q31" notation); in it I have an ANSI C implementation > and an example implementation for 32-bit x86 machines.For many C compilers now (long long) is a 64 bit type. I don't know about most, but many, including gcc, recognize that two 32 bit values are multiplied for a 64 bit product, and use the appropriate multiply instruction. That includes IA32. I haven't tested compilers for generating a 32 bit product from 16 bit (short) values. I would expect it, but maybe not. Note that you might have function call overhead for an assembly library, unless you can inline them. -- glen
Reply by ●August 19, 20102010-08-19
On Aug 19, 2:36=A0am, spop...@speedymail.org (Steve Pope) wrote:> robert bristow-johnson =A0<r...@audioimagination.com> wrote: > > >On Aug 19, 1:58=A0am, spop...@speedymail.org (Steve Pope) wrote: > >> =A0(SC_RND, i.e. rounding towards positive infinity, > >+inf ?? > >> is what you want to do 99% of the time if you're trying to model > >> hardware.) > >why would 99% of hardware always round up? =A0i could see a large > >proportion always rounding down (you just drop the bits), but always > >rounding up takes more work. =A0you have to add something before losing > >the low-order bits. > > You're right that truncation (which could be called "rounding down" > but I prefer truncation) is also very common.i would think far more common than rounding up (toward +inf) all of the time. like using the ceil() function.> > But if one is rounding instead of truncating, it is usually simplest > in hardware to take the most significant bit among those truncated, > and add it to the truncated result to obtain a rounded result.that is equivalent to adding 1 to that MSB among those truncated (and carrying to higher bits) before truncating. either way, 0x4000 gets rounded up and 0x3FFF gets rounded down.> =A0This > happens to be the same as SC_RND for both unsigned values, and 2's > complement values. =A0 > > (Here's a graphic on SC_RND: slide 34 ofhttp://www2.itu.edu.tr/~orssi/der=sler/SLD/systemc1.pdf. =A0Note> that the author believes SC_RND is "what you expect".sure, it's round-to-nearest and when you're exactly halfway between, it rounds up. that is the same as adding 0x4000 and masking off the bottom 15 bits.> =A0I think > the System C designers felt the same way, as they gave it > the shortest moniker among the different rounding modes.)it has a slight bias (upward). that's why the Mot 56K people decided to put in "convergent rounding" which was round-to-nearest and when it was exactly half-way, it was round-to-nearest-even. that was to get rid of the bias in some probabilistic manner. r b-j
Reply by ●August 19, 20102010-08-19
On 08/19/2010 12:07 AM, glen herrmannsfeldt wrote:> Tim Wescott<tim@seemywebsite.com> wrote: > (snip, someone wrote) > >>>> Q15 multiplication in goes like this > >>>> yn = ((long)h * (long)dly)>> 15; > (snip) > >> Note that with most C compilers you're better off writing an assembly >> language library to do this for you if you want the last little bit of >> speed. One chapter of my book is devoted to fractional arithmetic (I >> should have used "Q31" notation); in it I have an ANSI C implementation >> and an example implementation for 32-bit x86 machines. > > For many C compilers now (long long) is a 64 bit type. > > I don't know about most, but many, including gcc, recognize that > two 32 bit values are multiplied for a 64 bit product, and use > the appropriate multiply instruction. That includes IA32.That would be a violation of the ANSI C standard, then -- the result of a mathematical expression with variables all of a given type is supposed to be of that type, which implies truncation. To get a 64 bit result from 32 bit integers means you should cast the integers up _first_.> I haven't tested compilers for generating a 32 bit product > from 16 bit (short) values. I would expect it, but maybe not.Again, a violation of the standard if so. And on many tool chains for 16 bit processors 'int' is 16 bit.> Note that you might have function call overhead for an assembly > library, unless you can inline them.True, but often the function call overhead is less than the overhead to do three extra multiplies and all the bit-shifting that is necessary when doing a fractional multiply in pure C. -- Tim Wescott Wescott Design Services http://www.wescottdesign.com Do you need to implement control loops in software? "Applied Control Theory for Embedded Systems" was written for you. See details at http://www.wescottdesign.com/actfes/actfes.html






