Computer Chess Club Archives


Search

Terms

Messages

Subject: Re: Stupid compiler question...

Author: Dieter Buerssner

Date: 22:24:20 12/14/01

Go up one level in this thread


On December 15, 2001 at 00:10:00, Paul Byrne wrote:

>Not sure if it is the compiler that is stupid or the question... :)
>
>When I started using the MS compiler recently I discovered that rand()
>is only 16 bits & just hacked this together to get things running...
>[yes, I know rand() is evil, but ignore that for a moment  :)]
>
>unsigned rand32()
>{
>  return (unsigned) (rand() ^ (rand()<<7) ^ (rand()>>7) ^
>           (rand()<<17) ^ (rand()>>17) ^ (rand()<<23) ^ (rand()>>23));
>}
>
>Problem is, this returns different things in debug and release mode,
>which stops my opening books from functioning in debug mode.
>rand() is returning the same sequence of integers, so I'm assuming
>the optimizer is messing with the order of the calls (I'm just using
>the default maximize speed settings).
>
>Shouldn't the ^ operator always be left to right?
>
>Am I missing something here, or is the compiler breaking the rules?  :)

You code is unspecified behaviour.

From the C Standard:

6.5 Expressions
[...]

3 The grouping of operators and operands is indicated by the syntax.61) Except
as specified later (for the function-call (), &&, ||, ?:, and comma operators),
the order of evaluation of subexpressions and the order in which side effects
take place are both unspecified.

From my rather old version of the comp.lang.c FAQ:

4.5:    Can I use explicit parentheses to force the order of evaluation
        I want?  Even if I don't, doesn't precedence dictate it?

A:      Operator precedence and explicit parentheses impose only a
        partial ordering on the evaluation of an expression.  Consider
        the expression

                f() + g() * h()

        -- although we know that the multiplication will happen before
        the addition, there is no telling which of the three functions
        will be called first.


I can add: You can force the order of evaluation by using several expressions.
So in

 unsigned long k, l, m;
 k = rand();
 l = rand();
 m = (k + l) - rand();

the order of evaluation is specified, while in

 m = (rand() + rand()) - rand();

it is not.

You could try the following PRNG. It is small and fast and shows reasonable
results in test for randomness. I think, it is also much less hazzle and error
prone,
than using rand().

static unsigned long zs = 0x12345678UL;
static unsigned long ws = 0x87654321UL;

/* Multiply with carry RNG. Pastes together 2 16 bit MWC generators.
Suitable multipliers (list from Fortran source of Marsaglia):
 :: 18000 18030 18273 18513 18879 19074 19098 19164 19215 19584 ::
 :: 19599 19950 20088 20508 20544 20664 20814 20970 21153 21243 ::
 :: 21423 21723 21954 22125 22188 22293 22860 22938 22965 22974 ::
 :: 23109 23124 23163 23208 23508 23520 23553 23658 23865 24114 ::
 :: 24219 24660 24699 24864 24948 25023 25308 25443 26004 26088 ::
 :: 26154 26550 26679 26838 27183 27258 27753 27795 27810 27834 ::
 :: 27960 28320 28380 28689 28710 28794 28854 28959 28980 29013 ::
 :: 29379 29889 30135 30345 30459 30714 30903 30963 31059 31083 ::
 my [Marsaglia] favorites are 18000, 30963
 */


unsigned long mwc1616(void)
{
  unsigned long t = zs;
  zs = 30903*(t&0xffff)+(t>>16);
  t = ws;
  ws=18000*(t&0xffff)+(t>>16);
  return ((ws&0xffff)<<16) + (zs&0xffff);
}

BTW. Many systems don't have 16 bit rand(), but rather 15 bit rand().

Regards,
Dieter




This page took 0 seconds to execute

Last modified: Thu, 15 Apr 21 08:11:13 -0700

Current Computer Chess Club Forums at Talkchess. This site by Sean Mintz.