root/opal/util/alfg.c

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

DEFINITIONS

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

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