Read the REDIS study C programming One: How to implement Rand

Source: Internet
Author: User
Tags mul

before starting this series, let's start by talking about Redis. REdis is a high-performance Key-value memory database written in ANSI C and is now one of the representatives of NoSQL databases. By counting the number of lines in the redis2.8.17 code, including a total of about 50,000 lines in the open source family, it is very short and concise, and the project starts from 2009, the distance is very close, the code style is very suitable for us 80, the programmer's knowledge structure. When you have a certain coding experience, good source code is our best teacher, especially has been verified by the practice codes. Especially because of the recent study of Apue and UNP, read a lot of things still confused, and this doubt I feel more should be in the actual code to find the answer.

On-line various Redis source Code Analysis blog has been a huge amount, but as a learning purpose in Unix/linux C in the rookie, I prefer to first from the code module itself from low-up analysis of Redis, especially focus on learning its excellent code snippets. Well, gossip less, start with Rand, a small module that you see today. For programmers with a certain C language programming experience, Rand is an intrinsic feature, and ANSI C provides information about Rand and Srand implementations. Then why does Redis have to do the repetitive wheel-building activities?

/* Pseudo random number generation functions derived from the drand48 () * function obtained from Pysam source code. * * This functions is used in order to replace the default math.random () * Lua implementation with something have exact Ly the same behavior * across different systems (by default Lua uses LIBC's rand () that's not * required to implement a s Pecific PRNG generating the same sequence * in different systems if seeded with the same integer). * * The original code appears to is under the public domain. * I modified it removing the non needed functions and all the * 1960-style C coding stuff ... * *------------------------- ---------------------------------------------------
This is the note in front of RAND.C, where we can see two of the content. First, the author thinks that different systems implement math.random differently, so the author uses this module instead of the implementation of RAND in the system, and secondly, it is not a native module of Redis, but comes from a Pysam project. For us, though, it doesn't matter what it is or where it comes from, it's easier to see how it's done. Rand uses the algorithm called DRAND48, why is drand48, because it uses a 48bit space a linear congruence algorithm. What is the linear congruence algorithm? Let's take a look at Wikipedia's explanation.

The linear congruence method (LCG) is a method for generating pseudo-random numbers.

It is based on the recursive formula:

Which is the constant set by the generator.

The cycle of LCG is the most significant, but most of it will be less than M. For the LCG to reach its maximum cycle, the following conditions should be met:

    1. Coprime
    2. All the qualitative factors can be divided evenly;
    3. If the multiples of 4, too;
    4. Are smaller than the small;
    5. is a positive integer.
is actually an iterative redundancy algorithm that obeys uniformly distributed pseudo-random numbers. In Drand48 this a selected 0x5deece66d,b selected 0xb,m Choose 2^48,m Choice can understand, because the maximum setting is 2^48, as for the choice of A and B then first is in line with the previous five settings, and as to why in the number of matching set selected them, There are also more rigorous mathematical proofs, in this case the author of the level of limited also unable to delve into. So the next interesting thing to come, for us, if you get such a formula, straight A word does not solve it? n = (a*n+b)%m? Let's see what the author does.
#include <stdint.h> #define N16#define MASK ((1 << (N-1)) + (1 << (N-1))-1) #define LOW (x) ((unsigned) (x) & MASK) #define HIGH (x) Low ((x) >> N) #define MUL (x, Y, z) {int32_t L = (long) (x) * (long) (y); (z) [0] = low (L); (z) [1] = high (L); } #define CARRY (x, y) ((int32_t) (x) + (long) (y) > MASK) #define ADDEQU (x, Y, z) (z = CARRY (x, (y)), x = Low (x + (y)) #defin E x00x330e#define x10xabcd#define x20x1234#define a00xe66d#define a10xdeec#define A20x5#define C0xB#define SET3 (x, x0, x1, x2) ((x) [0] = (x0), (x) [1] = (x1), (x) [2] = (x2)) #define Setlow (x, y, N) SET3 (x, Low ((y) [n]), low ((y) [(n) +1]), Low ((y) [ (n) +2]) #define SEED (x0, x1, x2) (SET3 (x, x0, x1, x2), SET3 (A, A0, A1, A2), C = c) #define REST (v) for (i = 0; i < 3; i++ {Xsubi[i] = X[i]; X[i] = Temp[i];} return (v); #define Hi_bit (1L << (2 * N-1)) static uint32_t x[3] = {X0, X1,    X2}, A[3] = {A0, A1, A2}, C = c;static void next (void); int32_t redisLrand48 () {next (); Return ((int32_t) x[2 << (N-1)) + (X[1] >> 1));} void RedisSrand48 (int32_t seedval) {SEED (X0, Low (Seedval), High (Seedval));}    static void Next (void) {uint32_t p[2], q[2], r[2], carry0, carry1;    MUL (A[0], x[0], p);    Addequ (P[0], C, carry0);    Addequ (P[1], carry0, carry1);    MUL (A[0], x[1], q);    Addequ (P[1], q[0], carry0);    MUL (A[1], x[0], R);    X[2] = Low (carry0 + Carry1 + CARRY (p[1], r[0]) + q[1] + r[1] + a[0] * x[2] + a[1] * x[1] + a[2] * x[0]);    X[1] = Low (p[1] + r[0]); X[0] = Low (p[0]);}
First, we find it seems more complicated than we think. Each number is divided into an array of length three according to 16 bits, and its arithmetic also changed, by defining mul to represent multiplication, addequ to represent addition, low for 16 bits, high for 16 bits, and CArray to determine if a carry occurred. This enables the same functionality as an expression. At this point we have a question why, we try to interpret the boundary conditions, due to the use of 48bit results, and the actual results are more than 48bit, such as A is 36bit, if n is 48bit then the total public may be produced by 84bit, or even beyond a long long range. This is not the case when implementing arithmetic using arrays. In the code, macro functions and bit operations are used extensively, and in this implementation we can see that these techniques are a sharp weapon in C programming for dealing with numerical problems and are worth learning from.

Read the REDIS study C programming One: How to implement Rand

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.