Open In App

Well Equidistributed Long-period Linear

Last Updated : 19 Jul, 2019
Improve
Improve
Like Article
Like
Save
Share
Report

Well Equidistributed Long-period Linear (WELL) is a pseudorandom number generator algorithm based on the technique of Linear Feedback Shift Register to create Pseudo-Random Numbers. It belongs to the family of Linear Congruential Generators. It is similar to a Mersenne twister in terms of functioning since both of them work using XOR, shifts and an LFSR mechanism. Both require a seed value to start off the process of generation.

Pseudorandom Number Generators refers to a class of algorithms that utilize an initial set of seed values and apply a variety of logical operations or shift operations to produce a seemingly random number. A generator can be defined recursively as follows:

Xn+1 = (a*(Xn) + c) modulo-m

where X is a sequence of pseudorandom values, 
m is the modulus (m>0), 
a is the multiplier (0<a<m), 
c is the increment ( 0<c<m), 
and X0 is the seed ( 0<X0<m)

The algorithm is as follows:

0.  Initialize the necessary seed values
1.  Utilize a state array of a defined length (here it is 32)
2.  Apply the necessary xor, shift and logical and operations to arrive at
    the required parameters
3a. Update the current location value and output that value from an array 
    location multiplied with a scaling constant
3b. newV0 and newV1 are additional pseudorandom numbers that can be supplied
    as per requirement

WELL algorithm can produce many numbers in a short time and is advantageous for applications that need many numbers. One of the major weakness that WELL suffers from is having a smaller state space. This can be changed by utilizing a larger size of state space with auxiliary space being traded off.

Python code implementation –

# W stands for size of the digest, R is the size of the state
W = 32;R = 32 
# Variables used for jumping to a particular state
M1 = 3;M2 = 24;M3 = 10 

# can be changed to scale accordingly
FACT = 1.718 

# value based right shift with xor operation
def mat0pos(t, v):
    return(v^(v>>t))

# value based negative left shift with xor operation
def mat0neg(t, v):
    return(v^(v<<(~t)))

# returns the value itself (identity function)
def identity(v):
    return v

state = [None]*R

state_i = 0; z0 = None;z1 = None;z2 = None; newV1 = None; newV0 = None

# used to initialize the state of our digest based on argument provided
def InitWellRNG(arg):
    global state
    for j in range(0, len(arg)):
        state[j]= arg[j]

# function that utilizes seed values and logical operations to 
# output random numbers
def WELLRNG():
    global state_i
    global z0; global z1; global z2; global newV1; global newV0
    
    z0 = state[(state_i + M1) & 0x001f]
    z1 = identity(state[state_i]) ^ mat0pos(8, state[(state_i + M1) & 0x001f])
    z2 = mat0neg(-19, state[(state_i + M2) & 0x001f]) ^ mat0neg(-14,
                state[(state_i + M3) & 0x001f])

    # newV1 and newV0 are additional random values that are produced
    # and can be returned as per requirement
    newV1 = z1 ^ z2;
    newV0 = mat0neg(-11, z0) ^ mat0neg(-7, z1) ^ mat0neg(-13, z2)

    state_i = (state_i + (W-1)) & 0x001f
    return (state[state_i] *FACT)

# executed if this is the main file
if (__name__ == "__main__"):
    print("WELL created\n")
    # replace seed array with your own array to create different output
    # sequence of random numbers
    seed = [27, 10, 14, 27, 24, 4, 11, 25, 14, 13, 2, 20, 0, 22, 9, 24, 14, 9,
            20, 14, 17, 6, 21, 10, 27, 8, 16, 5, 26, 21, 18, 29]
    InitWellRNG(seed)
    for i in range(0,5):    
        print("random number generated is {}".format(WELLRNG()))

Output :

WELL created

random number generated is 49.822
random number generated is 30.924
random number generated is 36.078
random number generated is 44.668
random number generated is 8.59

Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads