root/opal/mca/pmix/pmix4x/pmix/src/util/alfg.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. galois
  2. pmix_srand
  3. pmix_rand
  4. pmix_random

   1 /*
   2  * Copyright (c) 2014      Mellanox Technologies, Inc.
   3  *                         All rights reserved.
   4  * Copyright (c) 2016      Research Organization for Information Science
   5  *                         and Technology (RIST). All rights reserved.
   6  * Copyright (c) 2016      Intel, Inc.  All rights reserved.
   7  * $COPYRIGHT$
   8  *
   9  * Additional copyrights may follow
  10  *
  11  * $HEADER$
  12  */
  13 
  14 #include <src/include/pmix_config.h>
  15 
  16 #include <string.h>
  17 
  18 #include "alfg.h"
  19 
  20 /* Mask corresponding to the primitive polynomial
  21  *---------------------------------------------------
  22  *
  23  * p(x) = 1 + x^25 + x^27 + x^29 + x^30 + x^31 + x^32
  24  *
  25  *---------------------------------------------------
  26  */
  27 #define MASK 0x80000057U
  28 
  29 /* Additive lagged Fibonacci parameters:
  30  *---------------------------------------------------
  31  *
  32  * x_n = (x_(n - TAP1) + x_(n - TAP2) ) mod M
  33  *
  34  *---------------------------------------------------
  35  */
  36 #define TAP1 127
  37 #define TAP2 97
  38 #define CBIT 21  /* Canonical bit */
  39 
  40 
  41 /**
  42  * @brief      Galois shift register: Used to seed the ALFG's
  43  *             canonical rectangle
  44  *
  45  * @param[in]  unsigned int *seed: used to seed the Galois register
  46  * @param[out] uint32_t lsb: least significant bit of the Galois
  47  *             register after shift
  48  */
  49 static uint32_t galois(unsigned int *seed){
  50 
  51     uint32_t lsb;
  52     lsb = (*seed & 1) ? 1 : 0;
  53     *seed >>= 1;
  54     /* tap it with the mask */
  55     *seed = *seed ^ (lsb*MASK);
  56 
  57     return lsb;
  58 }
  59 
  60 /* PMIX global rng buffer */
  61 static pmix_rng_buff_t alfg_buffer;
  62 
  63 /**
  64  * @brief   Routine to seed the ALFG register
  65  *
  66  * @param[in]   uint32_t seed
  67  * @param[out]  pmix_rng_buff_t *buff: handle to ALFG buffer state
  68  */
  69 int pmix_srand(pmix_rng_buff_t *buff, uint32_t seed) {
  70 
  71     int i, j;
  72     uint32_t seed_cpy = seed;
  73     buff->tap1 = TAP1 - 1;
  74     buff->tap2 = TAP2 - 1;
  75 
  76     /* zero out the register */
  77     for( i = 0; i < TAP1; i++){
  78         buff->alfg[i] = 0;
  79     }
  80     /* set the canonical bit */
  81     buff->alfg[CBIT] = 1;
  82 
  83     /* seed the ALFG register by blasting
  84      * the canonical rectangle with bits
  85     */
  86     for ( j = 1; j < TAP1; j++){
  87         for( i = 1; i < 32; i++){
  88             buff->alfg[j] = buff->alfg[j] ^ ((galois(&seed_cpy))<<i);
  89         }
  90     }
  91     /* copy the ALFG to the global buffer */
  92     memcpy(&alfg_buffer, buff, sizeof(alfg_buffer));
  93 
  94     return 1;
  95 
  96 }
  97 
  98 /**
  99  * @brief       The additive lagged Fibonnaci PRNG
 100  *
 101  * @param[in]   pmix_rng_buff_t *buff: handle to ALFG buffer state
 102  * @param[out]  32-bit unsigned random integer
 103  */
 104 
 105 uint32_t pmix_rand(pmix_rng_buff_t *buff){
 106 
 107     int *tap1 = &(buff->tap1);
 108     int *tap2 = &(buff->tap2);
 109     uint64_t overflow;
 110     uint32_t temp;
 111 
 112     /* prevent overflow */
 113     overflow = (uint64_t) buff->alfg[*tap1] + (uint64_t) buff->alfg[*tap2];
 114     /* circular buffer arithmetic */
 115     temp = (*tap1 + 1) == TAP1 ?  0 :  (*tap1 + 1);
 116     /* Division modulo 2^32 */
 117     buff->alfg[temp] = (uint32_t) ( overflow & ((1ULL<<32) -1));
 118 
 119     /* increment tap points */
 120     *tap1 = (*tap1 + 1)%TAP1;
 121     *tap2 = (*tap2 + 1)%TAP1;
 122 
 123     return buff->alfg[temp];
 124 
 125 }
 126 
 127 /**
 128  * @brief      A wrapper for pmix_rand() with our global ALFG buffer;
 129  *
 130  * @param[in]  none
 131  * @param[out] int, the same as normal rand(3)
 132  */
 133 int pmix_random(void){
 134     /* always return a positive int */
 135     return (int)(pmix_rand(&alfg_buffer) & 0x7FFFFFFF);
 136 }

/* [<][>][^][v][top][bottom][index][help] */