Using Premake and GCC then avoid FloatFast

We are porting our MSVC/Win32 applications to Clang/GCC/Linux and have just spent the morning tracing why our unit tests fail.

void BadExampleCode()
{
    double a = NAN;
    ASSERT(!isnan(a));
}

Under MSVC and Clang all good, GCC asserts. We added printf’s and looked at the assembly and the code was hard coded to 0.

Some googling found 2006 posts stating GCC -ffast-math did odd things with isnan, and it’s still a presently reported issue

This came about because we are using Premake, and had the FloatFast flag set, because that’s how our MSVC projects were set, and we don’t want to change those builds, so for now we have tweaked the Premake code for this flag under GCC, as it doesn’t make sense that you would ever want isnan to be hard coded to zero, that’s really not fast maths at all.

We also put a #ifdef for ffast-math to break if this flag is present in the future.

And by we I mean Dave, and I just sat and talking it though with him.

-1.#IND00

Debugging a recent issue, where our _matherr handler was logging a call to sqrt with -1.#IND00 as input, and in this same scenario the system was crashing (the actual problem needing to be solved).

So to findout what input was going into the sqrt, as I suspected there was rubish being passed in, I wanted to know what -1.#IND00 was in binnary.

I knew that passing -1.0 to sqrt would result in -1.#IND00 in the result, so I altered the code:

int main ()
{
	double d = sqrt(-1.0);
}

int __cdecl _matherr(struct _exception *e)
{
	informf( "\nMath Error: %s, Parameters: %lf %lf, Return: %lf\n",
		e->name, e->arg1, e->arg2, e->retval ) ;

	union ccc
	{
		double d;
		struct {
			long a;
			long b;
		} ll;
	};

	ccc aa;

	aa.d = e->retval;

<break point here, and inspect aa in debugger>
	if( _isnan( e->retval ) ) {
		e->retval = 0 ;
	}
	return 1 ;
}

results in the values:

aa.ll.a = 0;
aa.ll.b = 0xFFF80000;

And I posted this because Googling for -1.#IND00 got me no results.

We are looking for C++ Developers

Well I didn’t say anything last time we posted C++ developer job roles, but we currently have two openings for C++ developers asĀ permanent Caterpillar employees, so if you have 4+ year experince in C++ and you want to live in the greater Peoria, IL area.

go to http://www.caterpillar.com/careers/job-opportunities/job-search

then click on ‘Agree‘ at the bottom

click on the ‘Search for Jobs Now‘ button on the left

scroll down to ‘Job Opening ID:‘ and enterĀ 89466

Job posting closes on the 11:59 pm (CST) on Monday, November 14, 2011.

Learn more about Team Caterpillar

TrackPopupMenu in WinCE 5.0

After banging my head against the MSDN documentation* for a few days, it turns out that TrackPopupMenu and TrackPopupMenuEx (in CE 5.0 the former maps to the latter) are not in Menu.lib as per the documentation but in Coredll.lib.

Also causing problems was the macro redefining TrackPopupMenu to TrackPopupMenuEx was not working due to I believe Afx.h, so I just manually swapped to using the Ex function.

*MSDN url: ms-help://MS.WINCE.v50.en/wceshellui5/html/wce50lrfTrackPopupMenu.htm

Programming Challenges: 110208 Yahtzee

I completed the Yahtzee problem today, after a couple of days effort.

I first double checked my previous 2004 solution’s scoring function, there were a few gems in there that I had to reprove, like how the full house was worked out.

        // a - e are the five dice rolls
	int array[7] = { 0,0,0,0,0,0,0 };

	array[a]++;
	array[b]++;
	array++;
	array[d]++;
	array[e]++;

	// full house
	if ( ( array[a] + array[b] + array + array[d] + array[e] ) == 13 )
	{
		scores[count][12] = 40;
	}

I then rewrote the recursive function to remove my fancy std::list<int> stuff and used simple arrays of ints, and wrote a completely naive checker. But at 6 billions checks per score set, it was never going to fit the time limit.

I then thought about it for a day, and this morning, wrote a version the skipped the skippable stuff, but it got the wrong answer, then I noticed a case I’d skipped that I shouldn’t have. I added that back in, and all of a sudden my code started giving really bad (low) score results.

I noticed the my best score function was entering (new_score > best_score) when they were the same values.

Much muttering, explaining to my wife and children later…

I noticed a compiler warning:

warning C4390: ';' : empty controlled statement found; is this the intent?
	if( new_value > best_value );
	{
		//cout << "b: " << best_value << " n: " << new_value << endl;
		memcpy(best_set, current_set, sizeof(int)*13);
		best_value = new_value;
	}

after removing the stupid semicolon and debugging text, my solution solved the puzzle!