I was curious about the fuss over Fruit...

Discussion of anything and everything relating to chess playing software and machines.

Moderators: hgm, Rebel, chrisw

User avatar
hgm
Posts: 27790
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Re: I was curious about the fuss over Fruit...

Post by hgm »

Well, to build WinBoard we actually do not use MINGW, but gcc under Cygwin, with the option -mno-cygwin. But to my understandig this would be equivalent.

The point is that gcc does not complain about %lld, if it matches a 64-bit parameter of printf, as this is standard ANSI. But when at run time you do pass it to the library function for printf, it does not understand it properly, and prints a 32-bit integer. As this is the low word of the int64, you normally would not notice the difference, unless the number was > 2G. Or unless you printed something after it in the same printf call.

What happens when you do

Code: Select all

printf("%lld %d %d\n", (long long)3e9, 1, 2);
and run the program?

We have to use "%I64d %d %d" to make that work. But than it draws a compilaton warning that the parameter does not match the format.
Harald
Posts: 318
Joined: Thu Mar 09, 2006 1:07 am

Re: I was curious about the fuss over Fruit...

Post by Harald »

hgm wrote:Well, to build WinBoard we actually do not use MINGW, but gcc under Cygwin, with the option -mno-cygwin. But to my understandig this would be equivalent.

The point is that gcc does not complain about %lld, if it matches a 64-bit parameter of printf, as this is standard ANSI. But when at run time you do pass it to the library function for printf, it does not understand it properly, and prints a 32-bit integer. As this is the low word of the int64, you normally would not notice the difference, unless the number was > 2G. Or unless you printed something after it in the same printf call.

What happens when you do

Code: Select all

printf("%lld %d %d\n", (long long)3e9, 1, 2);
and run the program?

We have to use "%I64d %d %d" to make that work. But than it draws a compilaton warning that the parameter does not match the format.
One possibility to get rid of some compiler warnings and OS or compiler dependencies is the use of macros.

Code: Select all

#ifdef ... test the system or compiler here ...

// define some types here
typedef unsigned __int64 U64;

#define C(n)  (n##ull)

// define some formats here
#define U64_F "I64u"
#define X64_F "016I64x"

#endif

// use it like this
U64 bb = C(0x0123456789abcdef);
printf("bb value is %"U64_F" or %"X64_F"\n", bb, bb);
Harald
User avatar
hgm
Posts: 27790
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Re: I was curious about the fuss over Fruit...

Post by hgm »

I don't think that would work. The pre-processor, which expands the macros, runs before the 1st gcc pass, which generates the warnings. So the 1st compiler pass sees exactly the same input.

I guess you could thwart the compilers error detection by using a variable to pass the format. Like

Code: Select all

char *f = "%I64d %d %s";
long long int nodeCount;
printf(f, nodeCount, time, PV);
However, you would not receive any warnings for other possible errors in that case, e.g. fewer parameters than specified in the format. So it remains a nuisance, and I decided to live with the warnings. (three in backend.c, one in engineoutput.c).
pawnslinger
Posts: 42
Joined: Thu Jan 06, 2011 9:10 pm
Location: Mesa, AZ USA

Re: I was curious about the fuss over Fruit...

Post by pawnslinger »

Xann wrote:
pawnslinger wrote:There were about 4 places that I had to fix. This is an example. It is from the file util.h...

#ifdef _MSC_VER
# define S64_FORMAT "%I64d"
# define U64_FORMAT "%016I64X"
#else
// # define S64_FORMAT "%lld"
# define S64_FORMAT "%I64d"
# define U64_FORMAT "%016llX"
#endif

You can see the part that I commented out and below that added a new line. The MinGW compiler did not like the "%lld", but it was happy as a clam with the I64 specifier.
Do you know why your compiler accepts %016llX but not %lld?
This looks inconsistent to me.

Fabien.
It seems strange to me also. I do not know why it accepts one, but complains about the other. Since it is using Microsoft library calls from some of this stuff, perhaps what some have done is the right way... I have seen others simply define the _MSC_VER preprocessor variable. Since I am new to this particular compiler, I could not reall say more.
User avatar
Evert
Posts: 2929
Joined: Sat Jan 22, 2011 12:42 am
Location: NL

Re: I was curious about the fuss over Fruit...

Post by Evert »

The point is that gcc does not complain about %lld, if it matches a 64-bit parameter of printf, as this is standard ANSI. But when at run time you do pass it to the library function for printf, it does not understand it properly, and prints a 32-bit integer. As this is the low word of the int64, you normally would not notice the difference, unless the number was > 2G. Or unless you printed something after it in the same printf call.

What happens when you do

Code:
printf("%lld %d %d\n", (long long)3e9, 1, 2);


and run the program?
I don't have access to Windows at the moment, so I can't check it now. However, Sjaak's output line uses "% 4lld" when printing the search time, which is then followed by the node count in the same output string. As far as I'm aware, this works correctly, but you've probably run it more under Windows than I have.
It could be different with different MinGW versions as well, and it's possible that it's actually using the GNU runtime rather than the MSVC runtime, if that sort of thing makes sense (I dont know much about Windows or how different compilers are set up or interact there).
User avatar
michiguel
Posts: 6401
Joined: Thu Mar 09, 2006 8:30 pm
Location: Chicago, Illinois, USA

Re: I was curious about the fuss over Fruit...

Post by michiguel »

Evert wrote:
The point is that gcc does not complain about %lld, if it matches a 64-bit parameter of printf, as this is standard ANSI. But when at run time you do pass it to the library function for printf, it does not understand it properly, and prints a 32-bit integer. As this is the low word of the int64, you normally would not notice the difference, unless the number was > 2G. Or unless you printed something after it in the same printf call.

What happens when you do

Code:
printf("%lld %d %d\n", (long long)3e9, 1, 2);


and run the program?
I don't have access to Windows at the moment, so I can't check it now. However, Sjaak's output line uses "% 4lld" when printing the search time, which is then followed by the node count in the same output string. As far as I'm aware, this works correctly, but you've probably run it more under Windows than I have.
It could be different with different MinGW versions as well, and it's possible that it's actually using the GNU runtime rather than the MSVC runtime, if that sort of thing makes sense (I dont know much about Windows or how different compilers are set up or interact there).
Probably what I do is an overkill, but I got tired of this problem with 64 bit numbers and lack of output compatibility.
Since 64 bit output is not scattered everywhere

I use

Code: Select all

char *buffer[32];
printf("counter: %s\n", llu2str(x,buffer));
where llu2str is defined

Code: Select all

extern char *
llu2str (uint64_t x, char *s)
{
	char buf[32];
	char digitch[10] = {'0','1','2','3','4','5','6','7','8','9'};
	uint64_t m = 0;
	char *p;
	int i;

	buf[0] = '\0'; /* start with terminated string to silence splint */
	p = s;
	i = 0;
	while (x > 0) {
		m = x % 10;
		buf[i++] = digitch[(int)m];
		x -= m;		
		x /= 10;
	}
	if (i == 0) {
		*s++ = digitch[0];
	} else {
		while (i-- > 0) {
			*s++ = buf[i];
		}
	}
	*s = '\0';
	return p;
}
This compiles everywhere without warnings.

Miguel
pawnslinger
Posts: 42
Joined: Thu Jan 06, 2011 9:10 pm
Location: Mesa, AZ USA

Re: I was curious about the fuss over Fruit...

Post by pawnslinger »

I found another little fly. In the source code that I have, UseModulo is defined as false in trans.cpp. But the mask is a little wrong, unless using modulo...

At least I think so. So I made this change to trans.cpp in the trans_alloc() function.
// The order of the following 2 lines were reversed EPM
Trans.mask = size - 1;
Trans.size = size + (ClusterSize - 1); // HACK to avoid testing for end of table
Since size is a power of 2 before the ClusterSize hack, the subtraction gives the perfect mask when done before the ClusterSize is added. A small bit, I know, but I worried over that all last night, before I finally decided to make the change. The order of the 2 lines seemed correct without the ClusterSize hack, but with it... only correct if UseModulo is true. Perhaps a preprocessor thing can fix this.

Of course, I could be completely misunderstanding the code, but I think I have it right (this is not the first hash table I have worked on... grin).

Sincerely,
Ed

PS: As you might guess, I am going thru trans.cpp with a microscope. My wife says I am "anal retentive" about this kind of stuff. :)
User avatar
hgm
Posts: 27790
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Re: I was curious about the fuss over Fruit...

Post by hgm »

Trans.size is not the same as size. The latter is never assigned to, so the order does not matter. (Other than for dodging the GPL. :wink: )
pawnslinger
Posts: 42
Joined: Thu Jan 06, 2011 9:10 pm
Location: Mesa, AZ USA

Re: I was curious about the fuss over Fruit...

Post by pawnslinger »

hgm wrote:Trans.size is not the same as size. The latter is never assigned to, so the order does not matter. (Other than for dodging the GPL. :wink: )
Ahhhh, hmmmm, :oops:

The actual code as it appears now in my version is a little different than what I put in my previous message. I tried to show the intermediate step to my final version, but bloxed it. Sorry. Here is how the code now appears in this area:

// The order of the following 2 lines were reversed EPM
Trans.mask = size - 1;
Trans.size = Trans.mask + ClusterSize; // HACK to avoid testing for end of table
It is perhaps a trivial thing, and maybe makes no difference, but I prefer this way, because it seems more logical to me. The original way and this way do the same (very nearly) thing, but I believe this way to be a little more efficient. As I said not a big deal. But to get it to look like this, I had to reverse the lines. You can see that Trans.mask is calculated, then used as the basis for the Trans.sisze, saving, I think, a subtraction.

Or am I dreaming? I have been known to "see" what I want to see in code. Not necessarily what is actually there.

As for the GPL, I am not planning on violating it. If I ever release this code, it will definitely be: free and open-source. I am just doing this for grins.
pawnslinger
Posts: 42
Joined: Thu Jan 06, 2011 9:10 pm
Location: Mesa, AZ USA

Re: I was curious about the fuss over Fruit...

Post by pawnslinger »

Also, in all the files I am working on, I am adding this notice at the very top of the file:

/********************************************************************************************************************
Fruit 2.1 UCI by Fabien Letouzey (c) 2005, licensed under the GPL v.2 of the Free Software Foundation
MyFruit 1.0 by Edwin Meiners (c) 2010, licensed under the GPL v.2 of the Free Software Foundation
********************************************************************************************************************/
I think this will clearly spell the status of the code.