gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

C/C++ > having trouble including files [solved]

#172047 - zelbo - Mon Jan 11, 2010 9:31 pm

When i try to put the mtrandom stuff into mtrandom.h and mtrandom.c, i get the following error:
Code:
c:/devkitPro/projects/Quest_yarlds0.0.0c/source/mtrandom.c:23: error: conflicting types for 'init_by_array'
c:/devkitPro/projects/Quest_yarlds0.0.0c/include/mtrandom.h:62: note: previous declaration of 'init_by_array' was here

What the crap? how do i fix this? what else am i doing wrong here?
Is it superfluous to include mtrandom.h in mtrandom.c, or required?
including in my main.cpp with
Code:
#include "mtrandom.h"

include folder: mtrandom.h
Code:
/*
   A C-program for MT19937, with initialization improved 2002/1/26.
   Coded by Takuji Nishimura and Makoto Matsumoto.

   Before using, initialize the state by using init_genrand(seed) 
   or init_by_array(init_key, key_length).

   Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
   All rights reserved.                         

   Redistribution and use in source and binary forms, with or without
   modification, are permitted provided that the following conditions
   are met:

     1. Redistributions of source code must retain the above copyright
        notice, this list of conditions and the following disclaimer.

     2. Redistributions in binary form must reproduce the above copyright
        notice, this list of conditions and the following disclaimer in the
        documentation and/or other materials provided with the distribution.

     3. The names of its contributors may not be used to endorse or promote
        products derived from this software without specific prior written
        permission.

   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
   A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


   Any feedback is very welcome.
   http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html
   email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space)
*/

/* Period parameters */ 
#define N 624
#define M 397
#define MATRIX_A 0x9908b0dfUL   /* constant vector a */
#define UPPER_MASK 0x80000000UL /* most significant w-r bits */
#define LOWER_MASK 0x7fffffffUL /* least significant r bits */

static unsigned long mt[N]; /* the array for the state vector  */
static int mti=N+1; /* mti==N+1 means mt[N] is not initialized */


/* initializes mt[N] with a seed */
void init_genrand(unsigned long);

/* initialize by an array with array-length */
/* init_key is the array for initializing keys */
/* key_length is its length */
/* slight change for C++, 2004/2/26 */
void init_by_array(unsigned long, int);

/* generates a random number on [0,0xffffffff]-interval */
unsigned long genrand_int32(void);


/* generates a random number on [0,0x7fffffff]-interval */
long genrand_int31(void);

/* generates a random number on [0,1]-real-interval */
double genrand_real1(void);

/* generates a random number on [0,1)-real-interval */
double genrand_real2(void);

/* generates a random number on (0,1)-real-interval */
double genrand_real3(void);

/* generates a random number on [0,1) with 53-bit resolution*/
double genrand_res53(void);
/* These real versions are due to Isaku Wada, 2002/01/09 added */

source folder: mtrandom.c
Code:
#include "mtrandom.h"

/* initializes mt[N] with a seed */
void init_genrand(unsigned long s)
{
    mt[0]= s & 0xffffffffUL;
    for (mti=1; mti<N; mti++) {
        mt[mti] =
       (1812433253UL * (mt[mti-1] ^ (mt[mti-1] >> 30)) + mti);
        /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */
        /* In the previous versions, MSBs of the seed affect   */
        /* only MSBs of the array mt[].                        */
        /* 2002/01/09 modified by Makoto Matsumoto             */
        mt[mti] &= 0xffffffffUL;
        /* for >32 bit machines */
    }
}

/* initialize by an array with array-length */
/* init_key is the array for initializing keys */
/* key_length is its length */
/* slight change for C++, 2004/2/26 */
void init_by_array(unsigned long init_key[], int key_length)
{
    int i, j, k;
    init_genrand(19650218UL);
    i=1; j=0;
    k = (N>key_length ? N : key_length);
    for (; k; k--) {
        mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1664525UL))
          + init_key[j] + j; /* non linear */
        mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */
        i++; j++;
        if (i>=N) { mt[0] = mt[N-1]; i=1; }
        if (j>=key_length) j=0;
    }
    for (k=N-1; k; k--) {
        mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1566083941UL))
          - i; /* non linear */
        mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */
        i++;
        if (i>=N) { mt[0] = mt[N-1]; i=1; }
    }

    mt[0] = 0x80000000UL; /* MSB is 1; assuring non-zero initial array */
}

/* generates a random number on [0,0xffffffff]-interval */
unsigned long genrand_int32(void)
{
    unsigned long y;
    static unsigned long mag01[2]={0x0UL, MATRIX_A};
    /* mag01[x] = x * MATRIX_A  for x=0,1 */

    if (mti >= N) { /* generate N words at one time */
        int kk;

        if (mti == N+1)   /* if init_genrand() has not been called, */
            init_genrand(5489UL); /* a default initial seed is used */

        for (kk=0;kk<N-M;kk++) {
            y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
            mt[kk] = mt[kk+M] ^ (y >> 1) ^ mag01[y & 0x1UL];
        }
        for (;kk<N-1;kk++) {
            y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
            mt[kk] = mt[kk+(M-N)] ^ (y >> 1) ^ mag01[y & 0x1UL];
        }
        y = (mt[N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK);
        mt[N-1] = mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1UL];

        mti = 0;
    }
 
    y = mt[mti++];

    /* Tempering */
    y ^= (y >> 11);
    y ^= (y << 7) & 0x9d2c5680UL;
    y ^= (y << 15) & 0xefc60000UL;
    y ^= (y >> 18);

    return y;
}

/* generates a random number on [0,0x7fffffff]-interval */
long genrand_int31(void)
{
    return (long)(genrand_int32()>>1);
}

/* generates a random number on [0,1]-real-interval */
double genrand_real1(void)
{
    return genrand_int32()*(1.0/4294967295.0);
    /* divided by 2^32-1 */
}

/* generates a random number on [0,1)-real-interval */
double genrand_real2(void)
{
    return genrand_int32()*(1.0/4294967296.0);
    /* divided by 2^32 */
}

/* generates a random number on (0,1)-real-interval */
double genrand_real3(void)
{
    return (((double)genrand_int32()) + 0.5)*(1.0/4294967296.0);
    /* divided by 2^32 */
}

/* generates a random number on [0,1) with 53-bit resolution*/
double genrand_res53(void)
{
    unsigned long a=genrand_int32()>>5, b=genrand_int32()>>6;
    return(a*67108864.0+b)*(1.0/9007199254740992.0);
}
/* These real versions are due to Isaku Wada, 2002/01/09 added */


Last edited by zelbo on Tue Jan 12, 2010 2:57 am; edited 1 time in total

#172049 - gauauu - Mon Jan 11, 2010 9:44 pm

The signatures for init_by_array are different...in the header file, you specify the first parameter as an unsigned long, but the c source file, you specify it as an array of unsigned longs.

#172050 - zelbo - Mon Jan 11, 2010 9:48 pm

any suggestions on how to fix it? It's not my code, i'm just stealing it. I wrote the header prototypes though, so i guess i need to change that. How should i write it so it knows it's an array?

#172053 - gauauu - Mon Jan 11, 2010 10:47 pm

Just make the header prototype match the one in the c source, and you should be fine. (It won't hurt anything to put the parameter names in the headers, and might actually make it easier to use the header for your reference)

Code:

void init_by_array(unsigned long init_key[], int key_length);



Myself, I tend to avoid using the [] notation when passing parameters (not because you necessarily shouldn't, but I always end up confusing myself)

If it were me, I'd do:

Code:

void init_by_array(unsigned long * init_key, int key_length)


int both places.

In C, a pointer and an array can often be used interchangeably (for your purposes, they are almost the same thing, although saying they are truly the same would get me into trouble for telling lies)

#172058 - zelbo - Tue Jan 12, 2010 2:57 am

Spectacular! Thank you!

#172061 - Ruben - Tue Jan 12, 2010 11:25 am

Oh and one small thing.
I noticed this code...
Code:
mt[i-1] ^ (mt[i-1] >> 30

Unless I'm incredibly mistaken, x^x = 0, in C/C++ as ^ is in fact XOR, not pow(x, y)

EDIT: Nevermind, didn't see the ()
_________________
I'm 18 and have Asperger's, so if I don't get something at first, just bear with me. *nod*

#172069 - zelbo - Tue Jan 12, 2010 9:34 pm

Yeah, so i got it to compile and all. Except now i realized something. Most of this 'pseudo random number generator' stuff is going to be using floating point math at some point, right?
I don't know for sure, but it just seems like it would. So, if that's the case, is it the sort of thing i would be able to use a LUT for?
I guess it's not a big deal yet, since i'm nowhere near using it yet, but i would like it to work. And unlike most of the rest of it, this is one i'm willing to say "i don't need to understand it, i just need it to work". Because the math for this sort of thing is way over my head.

#172070 - gauauu - Tue Jan 12, 2010 10:38 pm

It shouldn't do any floating point as long as you only ask it for random ints instead of calling the genrand_real functions.

If you are asking for random floating point values, then it doesn't look much like a LUT will help, unless you are planning on always using the same seed each time (at which point you could just precalculate all your random numbers instead). (disclaimer: I'm bad at the math behind this stuff, so I could be wrong).

Assuming you are just going to use it for random ints (which is probably what you should do, depending on your requirements), you could just ignore (or even remove) the genrand_real functions and you'll be fine.