Problem in making mtrand work

I am quite a beginner in c++. I want to use C++ Mersenne Twister Pseudo-Random Number Generator provided by http://www.bedaux.net/mtrand/. I put mtrand.h, mtrand.cpp in the same folder as mutest.cpp. Then, tried to run the test function mttest.cpp in the following by using terminal command

$ g++ mttest.cpp


I got the following error

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Undefined symbols for architecture x86_64:
  "MTRand_int32::p", referenced from:
      MTRand_int32::rand_int32()       in ccyQdzrD.o
  "MTRand_int32::init", referenced from:
      MTRand_int32::MTRand_int32(unsigned long const*, int)in ccyQdzrD.o
      MTRand_int32::MTRand_int32()in ccyQdzrD.o
  "MTRand_int32::seed(unsigned long const*, int)", referenced from:
      MTRand_int32::MTRand_int32(unsigned long const*, int)in ccyQdzrD.o
  "MTRand_int32::seed(unsigned long)", referenced from:
      MTRand_int32::MTRand_int32()in ccyQdzrD.o
  "MTRand_int32::state", referenced from:
      MTRand_int32::rand_int32()       in ccyQdzrD.o
  "MTRand_int32::gen_state()", referenced from:
      MTRand_int32::rand_int32()       in ccyQdzrD.o
ld: symbol(s) not found for architecture x86_64
collect2: ld returned 1 exit status


The mttest.cpp is:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
// mtrand.cpp, see include file mtrand.h for information

#include "mtrand.h"
// non-inline function definitions and static member definitions cannot
// reside in header file because of the risk of multiple declarations

// initialization of static private members
unsigned long MTRand_int32::state[n] = {0x0UL};
int MTRand_int32::p = 0;
bool MTRand_int32::init = false;

void MTRand_int32::gen_state() { // generate new state vector
    for (int i = 0; i < (n - m); ++i)
        state[i] = state[i + m] ^ twiddle(state[i], state[i + 1]);
    for (int i = n - m; i < (n - 1); ++i)
        state[i] = state[i + m - n] ^ twiddle(state[i], state[i + 1]);
    state[n - 1] = state[m - 1] ^ twiddle(state[n - 1], state[0]);
    p = 0; // reset position
}

void MTRand_int32::seed(unsigned long s) {  // init by 32 bit seed
    state[0] = s & 0xFFFFFFFFUL; // for > 32 bit machines
    for (int i = 1; i < n; ++i) {
        state[i] = 1812433253UL * (state[i - 1] ^ (state[i - 1] >> 30)) + i;
        // see Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier
        // in the previous versions, MSBs of the seed affect only MSBs of the array state
        // 2002/01/09 modified by Makoto Matsumoto
        state[i] &= 0xFFFFFFFFUL; // for > 32 bit machines
    }
    p = n; // force gen_state() to be called for next random number
}

void MTRand_int32::seed(const unsigned long* array, int size) { // init by array
    seed(19650218UL);
    int i = 1, j = 0;
    for (int k = ((n > size) ? n : size); k; --k) {
        state[i] = (state[i] ^ ((state[i - 1] ^ (state[i - 1] >> 30)) * 1664525UL))
        + array[j] + j; // non linear
        state[i] &= 0xFFFFFFFFUL; // for > 32 bit machines
        ++j; j %= size;
        if ((++i) == n) { state[0] = state[n - 1]; i = 1; }
    }
    for (int k = n - 1; k; --k) {
        state[i] = (state[i] ^ ((state[i - 1] ^ (state[i - 1] >> 30)) * 1566083941UL)) - i;
        state[i] &= 0xFFFFFFFFUL; // for > 32 bit machines
        if ((++i) == n) { state[0] = state[n - 1]; i = 1; }
    }
    state[0] = 0x80000000UL; // MSB is 1; assuring non-zero initial array
    p = n; // force gen_state() to be called for next random number
}



Can anyone give me a hint on what I did wrong and how I should fix it?
Last edited on
$ g++ mttest.cpp mtrand.cpp
Thank you. If you have time, please explain a bit more may I learn something.
You have to compile all source files; the compiler won't just guess for you which files need to be included as part of your program.
Does that mean I can merge them into one file like:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
// test program mttest.cpp, see mtreadme.txt for information
#include "mtrand.h"
#include <cstdio>
unsigned long MTRand_int32::state[n] = {0x0UL};
int MTRand_int32::p = 0;
bool MTRand_int32::init = false;

void MTRand_int32::gen_state() { // generate new state vector
    for (int i = 0; i < (n - m); ++i)
        state[i] = state[i + m] ^ twiddle(state[i], state[i + 1]);
    for (int i = n - m; i < (n - 1); ++i)
        state[i] = state[i + m - n] ^ twiddle(state[i], state[i + 1]);
    state[n - 1] = state[m - 1] ^ twiddle(state[n - 1], state[0]);
    p = 0; // reset position
}

void MTRand_int32::seed(unsigned long s) {  // init by 32 bit seed
    state[0] = s & 0xFFFFFFFFUL; // for > 32 bit machines
    for (int i = 1; i < n; ++i) {
        state[i] = 1812433253UL * (state[i - 1] ^ (state[i - 1] >> 30)) + i;
        // see Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier
        // in the previous versions, MSBs of the seed affect only MSBs of the array state
        // 2002/01/09 modified by Makoto Matsumoto
        state[i] &= 0xFFFFFFFFUL; // for > 32 bit machines
    }
    p = n; // force gen_state() to be called for next random number
}

void MTRand_int32::seed(const unsigned long* array, int size) { // init by array
    seed(19650218UL);
    int i = 1, j = 0;
    for (int k = ((n > size) ? n : size); k; --k) {
        state[i] = (state[i] ^ ((state[i - 1] ^ (state[i - 1] >> 30)) * 1664525UL))
        + array[j] + j; // non linear
        state[i] &= 0xFFFFFFFFUL; // for > 32 bit machines
        ++j; j %= size;
        if ((++i) == n) { state[0] = state[n - 1]; i = 1; }
    }
    for (int k = n - 1; k; --k) {
        state[i] = (state[i] ^ ((state[i - 1] ^ (state[i - 1] >> 30)) * 1566083941UL)) - i;
        state[i] &= 0xFFFFFFFFUL; // for > 32 bit machines
        if ((++i) == n) { state[0] = state[n - 1]; i = 1; }
    }
    state[0] = 0x80000000UL; // MSB is 1; assuring non-zero initial array
    p = n; // force gen_state() to be called for next random number
}
int main() {
    unsigned long init[4] = {0x123, 0x234, 0x345, 0x456}, length = 4;
    MTRand_int32 irand(init, length); // 32-bit int generator
    // this is an example of initializing by an array
    // you may use MTRand(seed) with any 32bit integer
    // as a seed for a simpler initialization
    MTRand drand; // double in [0, 1) generator, already init
    
    // generate the same numbers as in the original C test program
    std::printf("1000 32-bit integer random numbers:\n");
    for (int i = 0; i < 1000; ++i) {
        std::printf("%10lu ", irand());
        if ((i % 5) == 4) std::printf("\n");
    }
    std::printf("\n1000 random numbers in [0, 1):\n");
    for (int i = 0; i < 1000; ++i) {
        std::printf("%10.8f ", drand());
        if ((i % 5) == 4) std::printf("\n");
    }
}


or put strand.cpp in a header file?
Last edited on
They are separate for a reason, do not try to merge them.
Is that gonna change the the compilation time?
Topic archived. No new replies allowed.