lroundf bug

Discussion to talk about software related topics only.
Post Reply
roland.ames

lroundf bug

Post by roland.ames »

I have found that lroundf() truncates instead of rounding

lroundf(0.1) = 0
lroundf(0.9) = 0


lround() works correctly
lround(0.1) = 0
lround(0.9) = 1


this seems to have been found before
see http://cygwin.com/ml/cygwin/2007-08/msg00656.html

Is anyone aware of any other floating point library problems?
User avatar
tod
Posts: 587
Joined: Sat Apr 26, 2008 8:27 am
Location: Southern California
Contact:

Re: lroundf bug

Post by tod »

lroundf takes a float and you're passing a double. I tested with
lroundf(0.9f) and it returns 1 as it should. In my experience relying on implicit conversions is a bad idea.
User avatar
tod
Posts: 587
Joined: Sat Apr 26, 2008 8:27 am
Location: Southern California
Contact:

Re: lroundf bug

Post by tod »

Just ran another test with explicit and implicit casts from double and they too worked.
Testing NNDK 2.6.4 (which uses gcc 4.2.1) on a MOD5272

Code: Select all

    cout << "\nround with implicit cast from 0.1 double " << lroundf(0.1);
    cout << "\nround with implicit cast from 0.9 double " << lroundf(0.9);
    cout << "\nround with explicit cast from double " << lroundf((float)0.9);
    cout << "\nround with float "<<lroundf(0.9f);
Post your actual test code.
roland.ames

Re: lroundf bug

Post by roland.ames »

Entire main.c

Code: Select all

#include "predef.h"
#include <stdio.h>
#include <ctype.h>
#include <startnet.h>
#include <autoupdate.h>
#include <dhcpclient.h>
#include <smarttrap.h>
#include <taskmon.h>
#include <NetworkDebug.h>

#include <math.h>

extern "C" {
void UserMain(void * pd);
}

const char * AppName="test_MOD5270B";


void tst_fplib(float tv)
{
	double dtv = (double)(tv);

	printf("\nf=%f\n", dtv);

	long int li = lroundf(tv);
	printf("lroundf(f) = %ld\n", li);
	li = lround(dtv);
	printf("lround(f) = %ld\n\n", li);

}
void test_float_point_libs(void)
{
	tst_fplib(0.9f);
	tst_fplib(0.5f);
	tst_fplib(0.1f);
	tst_fplib(-0.9f);
	tst_fplib(-0.5f);
	tst_fplib(-0.1f);

}




void UserMain(void * pd) {
    InitializeStack();
    if (EthernetIP == 0) GetDHCPAddress();
    OSChangePrio(MAIN_PRIO);
    EnableAutoUpdate();
    StartHTTP();
    EnableTaskMonitor();

    #ifndef _DEBUG
    EnableSmartTraps();
    #endif

    #ifdef _DEBUG
    InitializeNetworkGDB_and_Wait();
    #endif

    iprintf("Application started\n");

    test_float_point_libs();

    while (1) {
        OSTimeDly(20);
    }
}
output from stdio
Waiting 2sec to start 'A' to abort
Configured IP = 0.0.0.0
Configured Mask = 255.255.255.0
MAC Address= 00:03:f4:05:e1:3b
Application started

f=0.900000
lroundf(f) = 0
lround(f) = 1


f=0.500000
lroundf(f) = 0
lround(f) = 1


f=0.100000
lroundf(f) = 0
lround(f) = 0


f=-0.900000
lroundf(f) = 0
lround(f) = -1


f=-0.500000
lroundf(f) = 0
lround(f) = -1


f=-0.100000
lroundf(f) = 0
lround(f) = 0
this was done on a MOD5270B using standard system libraries, NNDK 2.6.4

same code with same result on a MOD5234
User avatar
tod
Posts: 587
Joined: Sat Apr 26, 2008 8:27 am
Location: Southern California
Contact:

Re: lroundf bug

Post by tod »

I recreated your code on a MOD5272 and I can replicate it. This is scary. The error seems to only happen when you pass the float (or double) as a parameter. This made me wonder if the value was getting changed or copied incorrectly when passed as a parameter. I wrote this function to pass the float as a reference

Code: Select all

void do_nothing (float& myfloat)
{
    cout << "No call to the rounding funcs "<< myfloat;
}
and then added this code down in main

Code: Select all

    float new_float = 0.9f;
    cout << "\nBEFORE  "<< new_float<< "result:" << lroundf(new_float) <<"\n";
    do_nothing(new_float);
    cout << "\nAFTER do_nothing() lroundf of "<< new_float<< "result:" << lroundf(new_float) <<"\n";
Before passing to do_nothing lroundf correctly returns 1. After the call to do nothing the call to lroundf incorrectly reports 0. Indicating to me that somehow new_float was changed by passing it to do_nothing(). At least it changed as far as lroundf was concerned.

The actual output was

BEFORE 0.9result:1
No call to the rounding funcs 0.9
AFTER do_nothing() lroundf of 0.9result:0
User avatar
dciliske
Posts: 623
Joined: Mon Feb 06, 2012 9:37 am
Location: San Diego, CA
Contact:

Re: lroundf bug

Post by dciliske »

Chiming in to say that we are now aware of the issue. We will try keep you apprised of the situation.
Dan Ciliske
Project Engineer
Netburner, Inc
User avatar
tod
Posts: 587
Joined: Sat Apr 26, 2008 8:27 am
Location: Southern California
Contact:

Re: lroundf bug

Post by tod »

Thanks Dan, it's always good to know you guys are listening. In case it helps I just created a simple desktop program using Eclipse and the Mingw toolchain (which is using gcc 4.7.2) and the problem does not occur so I suspect at some point a bug was found and fixed in the gcc libs. A good excuse to move to 4.7.2 or even 4.9.0? Of course as a side benefit that would get us C++11 compliance. Hidden motive? Who me?
roland.ames

Re: lroundf bug

Post by roland.ames »

Thanks for confirming the problem Tod. I would have been very concerned if your result was different to mine! Hopefully NB can sort this out, meanwhile I am doing all my floating point calcs using double instead of float.
Post Reply