9ea9bec4ad
1. Changed rng_buff_t --> opal_rng_buff_t 2. All global variables obey the prefix rule 3. Old code has been removed 4. Found a couple of unnecessary includes Refs trac:4298 This commit was SVN r30807. The following Trac tickets were found above: Ticket 4298 --> https://svn.open-mpi.org/trac/ompi/ticket/4298
118 строки
2.7 KiB
C
118 строки
2.7 KiB
C
/*
|
|
* Copyright (c) 2014 Mellanox Technologies, Inc.
|
|
* All rights reserved.
|
|
* $COPYRIGHT$
|
|
*
|
|
* Additional copyrights may follow
|
|
*
|
|
* $HEADER$
|
|
*/
|
|
|
|
#include "opal_config.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;
|
|
}
|
|
|
|
/**
|
|
* @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);
|
|
}
|
|
}
|
|
|
|
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];
|
|
|
|
}
|
|
|
|
|