Thread: How to use a float/double without using float/double keyword?

  1. #1
    Registered User
    Join Date
    Jan 2012
    Posts
    37

    How to use a float/double without using float/double keyword?

    I know this is weird to ask, but how do you set a variable as a decimal without using the keywords float/double?


    I ask this because when I am compiling the Kernel I get an error when I use float/double in the tcp_vegas.c file.


    These are the errors I am getting, if anyone knows how to go around this please let me know. Though like I said it is because I was using the float/double keywords; I used u32 (unsigned 32) to replace the float/double which got rid of the errors.


    Code:
    ERROR: "__addsf3" [net/ipv4/tcp_vegas.ko] undefined
    ERROR: "__fixunssfsi" [net/ipv4/tcp_vegas.ko] undefined
    ERROR: "__mulsf3" [net/ipv4/tcp_vegas.ko] undefined
    ERROR: "__muldf3" [net/ipv4/tcp_vegas.ko] undefined
    ERROR: "__floatsisf" [net/ipv4/tcp_vegas.ko] undefined
    ERROR: "__adddf3" [net/ipv4/tcp_vegas.ko] undefined
    ERROR: "__fixunsdfsi" [net/ipv4/tcp_vegas.ko] undefined
    ERROR: "__floatsidf" [net/ipv4/tcp_vegas.ko] undefined
    ERROR: "__subsf3" [net/ipv4/tcp_vegas.ko] undefined

    So is there an algorithm, function, or a way to do a float/double without using those keywords?
    An example


    float a = 3.145678; //I do not want this
    (some algorithm/function)-> a = 3.145678654; //This is somewhat I want


    I hope this makes sense, if it doesn't I will try to explain it better.


    Thanks

  2. #2
    - - - - - - - - oogabooga's Avatar
    Join Date
    Jan 2008
    Posts
    2,808
    Your description is very strange and I suspect that you are misinterpreting things. The errors look like linker errors, though, so could you be missing a library?
    The cost of software maintenance increases with the square of the programmer's creativity. - Robert D. Bliss

  3. #3
    Registered User
    Join Date
    May 2012
    Location
    Arizona, USA
    Posts
    945
    This is in the Linux kernel, right? As far as I know, you cannot use floating point at all inside the kernel. Those errors about undefined references are because GCC uses helper routines to work with floating values, and the kernel does not include the standard libraries or other GCC-specific libraries like libgcc (which contains the helper routines).

    Instead of floating point, you may be able to use fixed-point numbers, if the range and precision of values are relatively limited and known ahead of time. You can easily create a fixed-point number by treating a u32 as a 16-bit integer and 16-bit fraction. This will give you a range of 0..65535 and a precision of 0.000015259 (1/65536). See Fixed-point arithmetic - Wikipedia, the free encyclopedia for more information about working with fixed-point numbers. Actually I'm pretty sure Linux already uses fixed-point arithmetic in some places, such as for calculating load averages, so you could probably see how it's used there.

  4. #4
    Registered User
    Join Date
    Mar 2011
    Posts
    546
    christop is correct. no floating point allowed in kernel code.

  5. #5
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Not precisely true. It is not a particularly good idea though.

    For an explanation of why it is generally not done, but even how to do it if you really must, have a look at this link.

    This, incidentally, was the first link I found by googling "linux kernel floating point"
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  6. #6
    Registered User
    Join Date
    Jan 2012
    Posts
    37
    Thank you guys for your help.

    christop:
    Yes this is for the Linux Kernel. I am really interested using the fixed point you suggested. My research partner and I have talked about this filter function; however, we are not sure how to implement this function. Though, the code below shows some idea. I also like your example about treating a u32 as a 16-bit integer and 16-bit fraction. Though how would you create this, because my knowledge is u32 is an unsigned 32 bits of integer, but still interesting.

    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;
    }
    
    /*----------------------------*/

    grumpy:
    Thank you for posting that link. In that blog it says something about using two functions, kernel_fpu_begin() and kernel_fpu_end(), to use the floating point in the kernel. This is amazing and I don't have to make a fixed point function (no offense christop lol). In the blog it said that to use these functions just put the floating point codes between those functions. I have posted a code just to make sure I am doing this correctly, am I?

    Code:
    static void tcp_vegas_cong_avoid(struct sock *sk, u32 ack, u32 in_flight){
        kernel_fpu_begin();
    
    
        struct tcp_sock *tp = tcp_sk(sk);
        struct vegas *vegas = inet_csk_ca(sk);
        int target_queue_size;
        float rho, step_size;
        double avgRTT_Mult, rtt_Mult; 
        
        rho = 0.5;
        step_size = 0.1;
        target_queue_size = 100;
        avgRTT_Mult = 0.99609375; //(255/256)
        rtt_Mult    = 0.00390625; //(1/256)
        .
        .
        .
        avgRTT = (avgRTT_Mult*avgRtt) + (rtt_Mult*rtt);
        .                
        .
        .
        .
        kernel_fpu_end();    
    }

  7. #7
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    You'll have to read deeper to answer that question. The only time I ever considered doing something involving floating point in a kernel, deeper analysis determined it was a really bad idea (I wound up using fixed point instead).

    Most importantly, you will need to analyse your requirement quite deeply. Just because you CAN do something doesn't mean it is a good idea.

    Looking at your notional code (names of variables, etc) it seems you are trying to do some sort of simulation. My initial thought is that modifying code in a kernel is an extremely bad way of doing or supporting a simulation.

    Dividing by 256 is a basic operation for integral types, and there is no guarantee that a floating point type will correctly represent certain values. One fundamental property of floating point types is that they cannot represent values like 0.1 (decimal) precisely. I would strongly suggest considering whether that is better for coding as an application, rather than needing modification of a kernel.
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  8. #8
    Registered User
    Join Date
    Jan 2012
    Posts
    37
    grumpy:

    May I ask how did you used fixed point in your problem because those two functions, kernel_fpu_begin() and kernel_fpu_end(), did 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 or if your fixed point code is publicly publish so I could look at them. 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

    Also the 0.1 comment you made I changed it to 0.2 Thanks
    The other numbers that I have posted previously is still the same.

  9. #9
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    The code I wrote is part of something that cannot be published.

    Wikipedia has a link on fixed point arithmetic, here. That will hopefully be enough to get you started.
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. I need this (float != double)
    By m.sudhakar in forum C Programming
    Replies: 4
    Last Post: 08-19-2006, 06:27 AM
  2. float vs Double
    By sughandh in forum C Programming
    Replies: 3
    Last Post: 07-16-2006, 04:26 AM
  3. double to float
    By jsbeckton in forum C Programming
    Replies: 2
    Last Post: 11-07-2005, 11:29 PM
  4. float; double; int
    By Lyanette in forum C++ Programming
    Replies: 4
    Last Post: 01-29-2003, 12:04 PM
  5. Float,double,int
    By Bill 101 in forum C Programming
    Replies: 1
    Last Post: 11-06-2002, 02:09 PM