LinuxQuestions.org
Share your knowledge at the LQ Wiki.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 06-19-2012, 11:44 PM   #1
geewhan
LQ Newbie
 
Registered: Mar 2012
Posts: 16

Rep: Reputation: Disabled
How to write a fixed point function?


I would like to ask how to use fixed point in the linux kernel because the two functions, kernel_fpu_begin() and kernel_fpu_end(), does not work. So another method for solving this floating number is to use fixed point. My partner and I talked about this and we came upon to this function.


Code:
/*new "fixed" function -----------------------------------------*/global int cy; //comment: use global variable  cy .
global int x, int y;


int  filter(int x, int y) 
{
   cy = 10000*a*x + b*cy; // comment: cy = 10000*y; x is input;
   y = cy/10000;   //comment: 1>a >0; 1>b>0;
   return y;
}

/*----------------------------*/

I am still having trouble understanding this function. Okay so you take the values x and y and multiple the values okay. I do not see how this help for floating numbers.

The code below looks exactly the same as the fixed point function.
So how is this possible if I cannot use decimals/floating numbers?
Code:
avgRTT = ((255/256)*avgRtt) + ((1/256)*rtt);
Do you know any links or examples. I really want to figure this out because there is really no other way to go around this beside the fixed point function lol.

Thanks
 
Old 06-21-2012, 09:07 AM   #2
pixellany
LQ Veteran
 
Registered: Nov 2005
Location: Annapolis, MD
Distribution: Mint
Posts: 17,809

Rep: Reputation: 743Reputation: 743Reputation: 743Reputation: 743Reputation: 743Reputation: 743Reputation: 743
Confused I am......
In my book, "fixed point" and "integer" are not the same thing. You are declaring and integer data type, which means there is NO decimal point. C also has a "float" data type------does it also have a "fixed" data type?----I don't remember.
 
Old 06-21-2012, 06:04 PM   #3
Nominal Animal
Senior Member
 
Registered: Dec 2010
Location: Finland
Distribution: Xubuntu, CentOS, LFS
Posts: 1,723
Blog Entries: 3

Rep: Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948
Perhaps an illustrated example will help you understand.

Consider the linear blending function
Code:
float blend(const float x, const float y0, const float y1)
{
    return (1.0f - x) * y0 + x * y1;
}
The parameter x is between 0 and 1, inclusive. The function simply returns the linearly interpolated value y(x) where y(0)=y0 and y(1)=y1.

To use fixed-point math, you scale the floating-point value by a fixed integer S . So, instead of 0 to 1, integer x would get integer values from 0 to S .

When multiplying two fixed-point values, you must divide the result by S, because
Code:
 S * x * y = (S * x) * (S * y) / S
With integer computation, you wish to do the division last, because intermediate results are also always integers, i.e.
Code:
 (S * x) * (S * y) / S = trunc( ( trunc(S * x) * trunc(S * y) ) / S )     with integers
For example,
Code:
 ( ( x * y ) / 256 ) * 256 * 256 ) = trunc(x * y / 256) * 256 * 256 != 256 * x * y    with integers
For similar reasons, you need to multiply a value by S before dividing it by a fixed-point value. Addition and subtraction need no special handling.

Finally, this code may not work with optimizations disabled:
Code:
avgRTT = ((255/256)*avgRtt) + ((1/256)*rtt);
because the divisions evaluate to zero; it is equivalent to
Code:
avgRTT = (trunc(255/256) * avgRtt) + (trunc(1/256) * rtt);
and evaluates to zero. However, if you are using any sort of optimization, the compiler masks the issue by reordering the operations.

Without explicit casts, C compilers may always reorder the order of the operations, as long as no precision is lost. They will never evaluate x*y/256 as trunc(x/256)*y . When optimizations are disabled, the C compiler may not reorder the operations at all. Explicit casts (in C99) require the compiler to evaluate the expression so that the cast part is limited to the precision of the cast type; i.e. (int)(x/256)*y will always be equivalent to trunc(x/256)*y in C99, regardless of optimization flags.

When the multiplication and division are done in the correct order,
Code:
avgRTT = (255 * avgRtt + rtt) / 256;
the code always works. That is, it works if and only if 255*avgRtt and 255*avgRtt+rtt fit into the integer type used; otherwise the result is garbage. It is evaluated effectively as
Code:
avgRtt = trunc(trunc(trunc(255 * avgRtt) + rtt) / 256);
In other words, when you work with integers, you must remember the implicit truncation to integers at every single step. True, it is a bit complicated, because without explicit casts the C compiler is allowed to optimize the order of the operations (as long as mathematical equivalence remains), so you cannot always tell where the implicit truncation would go.. but the reordered expressions never lose precision compared to the original: they may have more, but never less precision.

Returning back to the initial blending function: Assume x varies between 0 and 255, with scale factor S = 256, i.e. 256 = 1.0, and that we assume both y0 and y1 are integers that can be multiplied by 256 without overflowing. Then,
Code:
int blend(const int x, const int y0, const int y1)
{
    return ((256 - x) * y0 + x * y1) / 256;
}
is the equivalent fixed-point function.

Finally, we can optimize away one multiplication in both floating-point and integer cases. The end result is actually more numerically stable (for floats), too:
Code:
float blendf(const float x, const float y0, const float y1) { return y0 + x * (y1 - y0); }
int blendi(const int x, const int y0, const int y1) { return y0 + (x * (y1 - y0)) / 256; }
This function can even be written for any integer scale factor S, simply by supplying the scaled value of 1.0 to the function too:
Code:
int blend(const int x, const int one, const int y0, const int [I]y1[I])
{
    return (y0 + x * (y1 - y0)) / one;
}
Note, however, that if the intermediate results overflow (do not fit in an int), the result will be garbage. That is always an issue with fixed-point math.

Also note that all the variables above are either floats or (scaled) integers; I am not using any special fixed-point types at all. I am just using fixed-point arithmetic.

Did this help?

Last edited by Nominal Animal; 06-21-2012 at 06:06 PM.
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
Make removable USB hdd mount at fixed mount point ctkroeker Linux - General 13 08-11-2009 08:49 AM
us robotics Wireless Turbo Multi-Function Access Point software - where to get it??? leben1 Linux - Hardware 1 05-12-2006 01:17 PM
need a fixed point media player linux=future Linux - Software 1 03-05-2006 05:24 PM
write function cxel91a Programming 4 01-15-2004 11:09 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 11:17 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration