1
1
openmpi/opal/util/alfg.c
Joshua Ladd 9ea9bec4ad Addressing Jeff's comments:
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
2014-02-24 23:18:35 +00:00

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];
}