File: alfg.c

package info (click to toggle)
openmpi 5.0.8-4
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 201,684 kB
  • sloc: ansic: 613,078; makefile: 42,353; sh: 11,194; javascript: 9,244; f90: 7,052; java: 6,404; perl: 5,179; python: 1,859; lex: 740; fortran: 61; cpp: 20; tcl: 12
file content (136 lines) | stat: -rw-r--r-- 3,295 bytes parent folder | download | duplicates (5)
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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
/*
 * Copyright (c) 2014      Mellanox Technologies, Inc.
 *                         All rights reserved.
 * Copyright (c) 2016      Research Organization for Information Science
 *                         and Technology (RIST). All rights reserved.
 * $COPYRIGHT$
 *
 * Additional copyrights may follow
 *
 * $HEADER$
 */

#include "opal_config.h"

#include <string.h>

#include "alfg.h"

/* Mask corresponding to the primitive polynomial
 *---------------------------------------------------
 *
 * p(x) = 1 + x^25 + x^27 + x^29 + x^30 + x^31 + x^32
 *
 *---------------------------------------------------
 */
#define MASK 0x80000057U

/* Additive lagged Fibonacci parameters:
 *---------------------------------------------------
 *
 * x_n = (x_(n - TAP1) + x_(n - TAP2) ) mod M
 *
 *---------------------------------------------------
 */
#define TAP1 127
#define TAP2 97
#define CBIT 21 /* Canonical bit */

/**
 * @brief      Galois shift register: Used to seed the ALFG's
 *             canonical rectangle
 *
 * @param[in]  unsigned int *seed: used to seed the Galois register
 * @param[out] uint32_t lsb: least significant bit of the Galois
 *             register after shift
 */
static uint32_t galois(unsigned int *seed)
{

    uint32_t lsb;
    lsb = (*seed & 1) ? 1 : 0;
    *seed >>= 1;
    /* tap it with the mask */
    *seed = *seed ^ (lsb * MASK);

    return lsb;
}

/* OPAL global rng buffer */
static opal_rng_buff_t alfg_buffer;

/**
 * @brief   Routine to seed the ALFG register
 *
 * @param[in]   uint32_t seed
 * @param[out]  opal_rng_buff_t *buff: handle to ALFG buffer state
 */
int opal_srand(opal_rng_buff_t *buff, uint32_t seed)
{

    int i, j;
    uint32_t seed_cpy = seed;
    buff->tap1 = TAP1 - 1;
    buff->tap2 = TAP2 - 1;

    /* zero out the register */
    for (i = 0; i < TAP1; i++) {
        buff->alfg[i] = 0;
    }
    /* set the canonical bit */
    buff->alfg[CBIT] = 1;

    /* seed the ALFG register by blasting
     * the canonical rectangle with bits
     */
    for (j = 1; j < TAP1; j++) {
        for (i = 1; i < 32; i++) {
            buff->alfg[j] = buff->alfg[j] ^ ((galois(&seed_cpy)) << i);
        }
    }
    /* copy the ALFG to the global buffer */
    memcpy(&alfg_buffer, buff, sizeof(alfg_buffer));

    return 1;
}

/**
 * @brief       The additive lagged Fibonnaci PRNG
 *
 * @param[in]   opal_rng_buff_t *buff: handle to ALFG buffer state
 * @param[out]  32-bit unsigned random integer
 */

uint32_t opal_rand(opal_rng_buff_t *buff)
{

    int *tap1 = &(buff->tap1);
    int *tap2 = &(buff->tap2);
    uint64_t overflow;
    uint32_t temp;

    /* prevent overflow */
    overflow = (uint64_t) buff->alfg[*tap1] + (uint64_t) buff->alfg[*tap2];
    /* circular buffer arithmetic */
    temp = (*tap1 + 1) == TAP1 ? 0 : (*tap1 + 1);
    /* Division modulo 2^32 */
    buff->alfg[temp] = (uint32_t)(overflow & ((1ULL << 32) - 1));

    /* increment tap points */
    *tap1 = (*tap1 + 1) % TAP1;
    *tap2 = (*tap2 + 1) % TAP1;

    return buff->alfg[temp];
}

/**
 * @brief      A wrapper for opal_rand() with our global ALFG buffer;
 *
 * @param[in]  none
 * @param[out] int, the same as normal rand(3)
 */
int opal_random(void)
{
    /* always return a positive int */
    return (int) (opal_rand(&alfg_buffer) & 0x7FFFFFFF);
}