Reply by Ken July 8, 20042004-07-08
johns@xetron.com (John Sampson) wrote in message news:<ae739955.0407070338.5482ba02@posting.google.com>...
> kenhusier@yahoo.com (Ken) wrote in message news:<46c498f7.0407060822.6197b9b7@posting.google.com>... > > Mark Borgerding <mark@borgerding.net> wrote in message news:<MmmFc.6272$m91.5379@fe1.columbus.rr.com>... > > > Ken wrote: > > > > > > > > I have a question, if I need to calculate float point exp()function, > > > I assume you mean fixed point exp(), right? > > > > > > > what should I do? have to change them back to float, right? if then, I > > > > still can't avoid from a floating point arithmatic. > > > > > > > > Thanx, > > > > Ken > > > > > > You left out a VERY important piece of info. What is your fixed point > > > representation? I'm assuming Q15 , since implementing an exp() function > > > for fixed-point representation with more than one or two integer bits > > > becomes ridiculous. exp(127) =~ 1e55 > > > > > > > > > First, decide how you'll represent the return value. > > > > > > If you're using Q15 ints, the range is [-1:1). > > > exp(-1) = 1/e =~ .367 > > > exp(1) = e = ~ 2.718 > > > > > > Assuming you can overcome a constant multiplier, I suggest returning > > > exp(x)/e to prevent overflow. > > > > > > The output range becomes [ exp(-2):1 ] =~ [ .13534... : 1 ] > > > > > > Second, figure out how to compute it. > > > > > > A quick look at the matlab/octave command > > > plot( exp( linspace(0,1) ) ) > > > shows that the exp function fairly linear over the range [0,1]. > > > It is a good candidate for a lookup table with linear interpolation. > > > > > > With Q.15 ints, then the input range 0:1 is all you need. > > > > > > If your input range can be > 1, you could either > > > extend the range of your lookup table > > > or > > > shift the input down to the range 0:1 and use the identity > > > e^x = ( e^(x/n) )^n. > > > > > > > > > Without more analysis, I'm not sure which would be better. > > > You must decide for yourself. Analyze it. Model it. Test it. Report > > > your results next week. (I'm not entirely kidding. I want to know. ) > > > > > > Exponentiation becomes increasingly non-linear (and non-representable in > > > fixed-point ) at higher input values. That might tend to offset the loss > > > of precision due to squaring of the interpolated answer. If you have > > > more than a few integer bits of the Q representation, you may want to > > > saturate the output answers at some point to avoid horrible loss of > > > precision at lower input values. > > > > > > > > > Cheers, > > > Mark > > > > Thank you very much. > > > > look up table is much faster, because I have a great external memory. > > But my input is varying in a big range(the results are from 1 to > > 1E18), so, I think I will analyze the two methods you said. I will > > paste the result. > > > > peace, > > > > Ken > > A common solution to this problem is to use range reduction followed > by a polynomial fit. For a discussion, see the book COMPUTER > APPROXIMATIONS, by J.F. Hart. > > There is free assembler code to do exp() in the TI DSPLIB software > package found at www.ti.com, document # SPRA480B. > > Regards, > > John
gotcha,a very useful document, thank you very much, peace, Ken
Reply by John Sampson July 7, 20042004-07-07
kenhusier@yahoo.com (Ken) wrote in message news:<46c498f7.0407060822.6197b9b7@posting.google.com>...
> Mark Borgerding <mark@borgerding.net> wrote in message news:<MmmFc.6272$m91.5379@fe1.columbus.rr.com>... > > Ken wrote: > > > > > > I have a question, if I need to calculate float point exp()function, > > I assume you mean fixed point exp(), right? > > > > > what should I do? have to change them back to float, right? if then, I > > > still can't avoid from a floating point arithmatic. > > > > > > Thanx, > > > Ken > > > > You left out a VERY important piece of info. What is your fixed point > > representation? I'm assuming Q15 , since implementing an exp() function > > for fixed-point representation with more than one or two integer bits > > becomes ridiculous. exp(127) =~ 1e55 > > > > > > First, decide how you'll represent the return value. > > > > If you're using Q15 ints, the range is [-1:1). > > exp(-1) = 1/e =~ .367 > > exp(1) = e = ~ 2.718 > > > > Assuming you can overcome a constant multiplier, I suggest returning > > exp(x)/e to prevent overflow. > > > > The output range becomes [ exp(-2):1 ] =~ [ .13534... : 1 ] > > > > Second, figure out how to compute it. > > > > A quick look at the matlab/octave command > > plot( exp( linspace(0,1) ) ) > > shows that the exp function fairly linear over the range [0,1]. > > It is a good candidate for a lookup table with linear interpolation. > > > > With Q.15 ints, then the input range 0:1 is all you need. > > > > If your input range can be > 1, you could either > > extend the range of your lookup table > > or > > shift the input down to the range 0:1 and use the identity > > e^x = ( e^(x/n) )^n. > > > > > > Without more analysis, I'm not sure which would be better. > > You must decide for yourself. Analyze it. Model it. Test it. Report > > your results next week. (I'm not entirely kidding. I want to know. ) > > > > Exponentiation becomes increasingly non-linear (and non-representable in > > fixed-point ) at higher input values. That might tend to offset the loss > > of precision due to squaring of the interpolated answer. If you have > > more than a few integer bits of the Q representation, you may want to > > saturate the output answers at some point to avoid horrible loss of > > precision at lower input values. > > > > > > Cheers, > > Mark > > Thank you very much. > > look up table is much faster, because I have a great external memory. > But my input is varying in a big range(the results are from 1 to > 1E18), so, I think I will analyze the two methods you said. I will > paste the result. > > peace, > > Ken
A common solution to this problem is to use range reduction followed by a polynomial fit. For a discussion, see the book COMPUTER APPROXIMATIONS, by J.F. Hart. There is free assembler code to do exp() in the TI DSPLIB software package found at www.ti.com, document # SPRA480B. Regards, John
Reply by Ken July 6, 20042004-07-06
Mark Borgerding <mark@borgerding.net> wrote in message news:<MmmFc.6272$m91.5379@fe1.columbus.rr.com>...
> Ken wrote: > > > > I have a question, if I need to calculate float point exp()function, > I assume you mean fixed point exp(), right? > > > what should I do? have to change them back to float, right? if then, I > > still can't avoid from a floating point arithmatic. > > > > Thanx, > > Ken > > You left out a VERY important piece of info. What is your fixed point > representation? I'm assuming Q15 , since implementing an exp() function > for fixed-point representation with more than one or two integer bits > becomes ridiculous. exp(127) =~ 1e55 > > > First, decide how you'll represent the return value. > > If you're using Q15 ints, the range is [-1:1). > exp(-1) = 1/e =~ .367 > exp(1) = e = ~ 2.718 > > Assuming you can overcome a constant multiplier, I suggest returning > exp(x)/e to prevent overflow. > > The output range becomes [ exp(-2):1 ] =~ [ .13534... : 1 ] > > Second, figure out how to compute it. > > A quick look at the matlab/octave command > plot( exp( linspace(0,1) ) ) > shows that the exp function fairly linear over the range [0,1]. > It is a good candidate for a lookup table with linear interpolation. > > With Q.15 ints, then the input range 0:1 is all you need. > > If your input range can be > 1, you could either > extend the range of your lookup table > or > shift the input down to the range 0:1 and use the identity > e^x = ( e^(x/n) )^n. > > > Without more analysis, I'm not sure which would be better. > You must decide for yourself. Analyze it. Model it. Test it. Report > your results next week. (I'm not entirely kidding. I want to know. ) > > Exponentiation becomes increasingly non-linear (and non-representable in > fixed-point ) at higher input values. That might tend to offset the loss > of precision due to squaring of the interpolated answer. If you have > more than a few integer bits of the Q representation, you may want to > saturate the output answers at some point to avoid horrible loss of > precision at lower input values. > > > Cheers, > Mark
Thank you very much. look up table is much faster, because I have a great external memory. But my input is varying in a big range(the results are from 1 to 1E18), so, I think I will analyze the two methods you said. I will paste the result. peace, Ken
Reply by Mark Borgerding July 2, 20042004-07-02
Ken wrote:
> > I have a question, if I need to calculate float point exp()function,
I assume you mean fixed point exp(), right?
> what should I do? have to change them back to float, right? if then, I > still can't avoid from a floating point arithmatic. > > Thanx, > Ken
You left out a VERY important piece of info. What is your fixed point representation? I'm assuming Q15 , since implementing an exp() function for fixed-point representation with more than one or two integer bits becomes ridiculous. exp(127) =~ 1e55 First, decide how you'll represent the return value. If you're using Q15 ints, the range is [-1:1). exp(-1) = 1/e =~ .367 exp(1) = e = ~ 2.718 Assuming you can overcome a constant multiplier, I suggest returning exp(x)/e to prevent overflow. The output range becomes [ exp(-2):1 ] =~ [ .13534... : 1 ] Second, figure out how to compute it. A quick look at the matlab/octave command plot( exp( linspace(0,1) ) ) shows that the exp function fairly linear over the range [0,1]. It is a good candidate for a lookup table with linear interpolation. With Q.15 ints, then the input range 0:1 is all you need. If your input range can be > 1, you could either extend the range of your lookup table or shift the input down to the range 0:1 and use the identity e^x = ( e^(x/n) )^n. Without more analysis, I'm not sure which would be better. You must decide for yourself. Analyze it. Model it. Test it. Report your results next week. (I'm not entirely kidding. I want to know. ) Exponentiation becomes increasingly non-linear (and non-representable in fixed-point ) at higher input values. That might tend to offset the loss of precision due to squaring of the interpolated answer. If you have more than a few integer bits of the Q representation, you may want to saturate the output answers at some point to avoid horrible loss of precision at lower input values. Cheers, Mark
Reply by Ken July 2, 20042004-07-02
axl_fugazi@yahoo.com (Pallav) wrote in message news:<baaddb55.0407010748.209d2360@posting.google.com>...
> > Here are some macros I define in kissfft for fixed point math (Q.15). > > > > > > > > #define smul(a,b) ( (long)(a)*(b) ) > > #define sround( x ) (short)( ( (x) + (1<<14) ) >>15 ) > > > > #define S_MUL(a,b) sround( smul(a,b) ) > > > > #define C_MUL(m,a,b) \ > > do{ (m).r = sround( smul((a).r,(b).r) - smul((a).i,(b).i) ); \ > > (m).i = sround( smul((a).r,(b).i) + smul((a).i,(b).r) ); while(0) > > > > > > > > Hope this helps, > > Mark > > Hi Mark, > > Thank you for your post. Yes, I made a typo in the posted code. Rather > than a comma it should have been a *. I will try out your macros. > > thanks again > pallav
hi, mark & pallav,... I have a question, if I need to calculate float point exp()function, what should I do? have to change them back to float, right? if then, I still can't avoid from a floating point arithmatic. Thanx, Ken
Reply by Pallav July 1, 20042004-07-01
> Here are some macros I define in kissfft for fixed point math (Q.15). > > > > #define smul(a,b) ( (long)(a)*(b) ) > #define sround( x ) (short)( ( (x) + (1<<14) ) >>15 ) > > #define S_MUL(a,b) sround( smul(a,b) ) > > #define C_MUL(m,a,b) \ > do{ (m).r = sround( smul((a).r,(b).r) - smul((a).i,(b).i) ); \ > (m).i = sround( smul((a).r,(b).i) + smul((a).i,(b).r) ); while(0) > > > > Hope this helps, > Mark
Hi Mark, Thank you for your post. Yes, I made a typo in the posted code. Rather than a comma it should have been a *. I will try out your macros. thanks again pallav
Reply by Mark Borgerding June 30, 20042004-06-30
Pallav wrote:
> hello, > > i'm trying to implement some fixed point arithmetic. the base i've > chosen is 22.10 format. to multiply two fixed point numbers i say the > following
Here are some macros I define in kissfft for fixed point math (Q.15). #define smul(a,b) ( (long)(a)*(b) ) #define sround( x ) (short)( ( (x) + (1<<14) ) >>15 ) #define S_MUL(a,b) sround( smul(a,b) ) #define C_MUL(m,a,b) \ do{ (m).r = sround( smul((a).r,(b).r) - smul((a).i,(b).i) ); \ (m).i = sround( smul((a).r,(b).i) + smul((a).i,(b).r) ); while(0) Hope this helps, Mark
Reply by Mark Borgerding June 30, 20042004-06-30
Pallav wrote:
> hello, > > i'm trying to implement some fixed point arithmetic. the base i've > chosen is 22.10 format. to multiply two fixed point numbers i say the > following > > #define FRACTION 10 /* about 3 digits of precision */ > #define FPMUL(a1, a2) (((long long int) a1, (long long int) a2) >> > FRACTION)
This doesn't look right. You've got a comma where I'd expect to see '*'. FPMUL(2,5) will evaluate as (a,b) >> 10 and so the comma will evaluate a, then b, and result will be b>>10 ... probably not what you want.
> #define FLOAT2FP(a) ((long) a * (1 << FRACTION)) > #define INT2FP(a) (a << FRACTION) > > and i have macros to convert from int to fp, float to fp, vice versa. > > so then I define a fixed point value of 40.6 > #define MAGIC_VALUE FLOAT2FP(40.6) > > then i write some test code > > long fpn; > double fpy; > > for (i = 0; ; i++) > { > fpn = INT2FP(i); // conver to fixed point > fpn = FMUL(fpn, MAGIC_VALUE); // multiply in fixed point
Wait a minute. This doesn't even match your previous defintion ( FMUL != FPMUL ) If you've typoed this by hand, which one is wrong? I doubt you posted the code you intended. I'm afraid I can't help much. -- Mark
Reply by Pallav June 30, 20042004-06-30
hello,

i'm trying to implement some fixed point arithmetic. the base i've
chosen is 22.10 format. to multiply two fixed point numbers i say the
following

#define FRACTION 10   /* about 3 digits of precision  */
#define FPMUL(a1, a2)  (((long long int) a1, (long long int) a2) >>
FRACTION)
#define FLOAT2FP(a) ((long) a * (1 << FRACTION))
#define INT2FP(a) (a << FRACTION)

and i have macros to convert from int to fp, float to fp, vice versa.

so then I define a fixed point value of 40.6
#define MAGIC_VALUE FLOAT2FP(40.6)

then i write some test code 

long fpn;
double fpy;

for (i = 0; ; i++)
{
 fpn = INT2FP(i); // conver to fixed point
 fpn = FMUL(fpn, MAGIC_VALUE); // multiply in fixed point

 fpy = 40.6 * i; // multiply in double format
 
 // compare values here to find out the error.
}

i'm noticing that as i gets large (say 2500), fpn and fpy differ by as
much as 2 and the difference continues to increase (this is mainly due
to the fractional part). this is becomign a problem. unfortunately, i
can't increase the fractional precision of the fixed point. is there
anything to remedy this? perhaps implementing the FPMUL in a better
way? i don't understand why this is happening given that i have 3
digits of precision?

i also tried doing 40 * i + 0.6 * i, that helps a little but not much.
If i could keep the difference less than 0.5 for all i (within the
limit of the size of an int) i'd be happy.

reason is because i use these values to index a fixed-point
sine/cosine tables and because of this difference (with very large i,
the difference can go upto 20), i'm getting the wrong values during
lookup.

thanks
pallav