C语言生成32位和64位随机数算法

/**
* randstd.h
*
*   Standard definitions and types, Bob Jenkins
*
* 2015-01-19: revised by cheungmine
*/
#ifndef _RANDSTD_H__
#define _RANDSTD_H__

#ifndef STDIO
#  include <stdio.h>
#  define STDIO
#endif

#ifndef STDDEF
#  include <stddef.h>
#  define STDDEF
#endif

typedef unsigned long long ub8;
#define UB8MAXVAL 0xffffffffffffffffLL
#define UB8BITS 64

typedef signed long long sb8;
#define SB8MAXVAL 0x7fffffffffffffffLL

typedef unsigned long int ub4;   /* unsigned 4-byte quantities */
#define UB4MAXVAL 0xffffffff

typedef signed long int sb4;
#define UB4BITS 32
#define SB4MAXVAL 0x7fffffff

typedef unsigned short int ub2;
#define UB2MAXVAL 0xffff
#define UB2BITS 16

typedef signed short int sb2;
#define SB2MAXVAL 0x7fff

/* unsigned 1-byte quantities */
typedef unsigned char ub1;
#define UB1MAXVAL 0xff
#define UB1BITS 8

/* signed 1-byte quantities */
typedef signed char sb1;
#define SB1MAXVAL 0x7f

/* fastest type available */
typedef int word;

#define bis(target,mask)  ((target) |=  (mask))
#define bic(target,mask)  ((target) &= ~(mask))
#define bit(target,mask)  ((target) &   (mask))

#ifndef min
#  define min(a,b) (((a)<(b)) ? (a) : (b))
#endif /* min */

#ifndef max
#  define max(a,b) (((a)<(b)) ? (b) : (a))
#endif /* max */

#ifndef abs
#  define abs(a)   (((a)>0) ? (a) : -(a))
#endif

#ifndef align
#  define align(a) (((ub4)a+(sizeof(void *)-1))&(~(sizeof(void *)-1)))
#endif /* align */

#define RAND_TRUE    1
#define RAND_FALSE   0

#define RAND_SUCCESS 0  /* 1 on VAX */

#endif /* _RANDSTD_H__ */

/**
* rand.h
*   definitions for a random number generator
* -----------------------------------------------------------------------------
* By Bob Jenkins, 1996, Public Domain
* MODIFIED:
*   960327: Creation (addition of randinit, really)
*   970719: use context, not global variables, for internal state
*   980324: renamed seed to flag
*   980605: recommend RANDSIZL=4 for noncryptography.
*   010626: note this is public domain
* -----------------------------------------------------------------------------
*
* 2015-01-19: revised by cheungmine
*/
#ifndef _RAND_H__
#define _RAND_H__

#ifdef    __cplusplus
extern "C" {
#endif

#include "randstd.h"

#define RANDSIZL   (8)
#define RANDSIZ    (1<<RANDSIZL)

/**
* context of random number generator
*/
struct randctx_ub4
{
    ub4 randcnt;
    ub4 seed[RANDSIZ];
    ub4 mm[RANDSIZ];
    ub4 aa;
    ub4 bb;
    ub4 cc;
};
typedef  struct randctx_ub4  randctx;

/**
* context of random number generator for 64-bits int
*/
struct randctx_ub8
{
    ub8 randcnt;
    ub8 seed[RANDSIZ];
    ub8 mm[RANDSIZ];
    ub8 aa;
    ub8 bb;
    ub8 cc;
};
typedef  struct randctx_ub8  randctx64;

/**
* randinit
*   init rand seed
*/
extern void rand_init(randctx *r, word time_as_seed);

extern void rand64_init(randctx64 *r, word time_as_seed);

/**
* rand
*   Call rand(randctx *) to retrieve a single 32-bit random value.
*/
extern ub4 rand(randctx *r);

extern ub4 randint(randctx *r, ub4 rmin, ub4 rmax);

extern ub8 rand64(randctx64 *r);

extern ub8 randint64(randctx64 *r, ub8 rmin, ub8 rmax);

#ifdef    __cplusplus
}
#endif

#endif  /* _RAND_H__ */

/**
* rand.c
*   By Bob Jenkins.  My random number generator, ISAAC.  Public Domain.
* -----------------------------------------------------------------------------
* MODIFIED:
*   960327: Creation (addition of randinit, really)
*   970719: use context, not global variables, for internal state
*   980324: added main (ifdef'ed out), also rearranged randinit()
*   010626: Note that this is public domain
* -----------------------------------------------------------------------------
*
* 2015-01-19: revised by cheungmine
*/
#include "rand.h"

#include <time.h>

/**
*==============================================================================
* 32-bits int random generator
*==============================================================================
*/
#define isaac_golden_ratio32  0x9e3779b9
#define ind32(mm,x)  (*(ub4 *)((ub1 *)(mm) + ((x) & ((RANDSIZ-1)<<2))))
#define rngstep32(mix,a,b,mm,m,m2,r,x) \
{ \
    x = *m;  \
    a = (a^(mix)) + *(m2++); \
    *(m++) = y = ind32(mm,x) + a + b; \
    *(r++) = b = ind32(mm,y>>RANDSIZL) + x; \
}

#define mix32(a,b,c,d,e,f,g,h) \
{ \
    a^=b<<11; d+=a; b+=c; \
    b^=c>>2;  e+=b; c+=d; \
    c^=d<<8;  f+=c; d+=e; \
    d^=e>>16; g+=d; e+=f; \
    e^=f<<10; h+=e; f+=g; \
    f^=g>>4;  a+=f; g+=h; \
    g^=h<<8;  b+=g; h+=a; \
    h^=a>>9;  c+=h; a+=b; \
}

static void isaac32(randctx *ctx)
{
    register ub4 a, b, x, y, *m, *mm, *m2, *r, *mend;
    mm = ctx->mm;
    r = ctx->seed;
    a = ctx->aa;
    b = ctx->bb + (++ctx->cc);

    for (m = mm, mend = m2 = m+(RANDSIZ/2); m<mend; ) {
        rngstep32( a<<13, a, b, mm, m, m2, r, x);
        rngstep32( a>>6 , a, b, mm, m, m2, r, x);
        rngstep32( a<<2 , a, b, mm, m, m2, r, x);
        rngstep32( a>>16, a, b, mm, m, m2, r, x);
    }

    for (m2 = mm; m2<mend; ) {
        rngstep32( a<<13, a, b, mm, m, m2, r, x);
        rngstep32( a>>6 , a, b, mm, m, m2, r, x);
        rngstep32( a<<2 , a, b, mm, m, m2, r, x);
        rngstep32( a>>16, a, b, mm, m, m2, r, x);
    }

    ctx->bb = b;
    ctx->aa = a;
}

#define gen_rand32(r) \
    (!(r)->randcnt-- ? \
        (isaac32(r), (r)->randcnt=RANDSIZ-1, (r)->seed[(r)->randcnt]) : \
        (r)->seed[(r)->randcnt])

void rand_init(randctx *ctx, word time_as_seed)
{
    word i;
    ub4 a, b, c, d, e, f, g, h;
    ub4 *m, *r;
    ctx->aa = ctx->bb = ctx->cc = 0;
    m = ctx->mm;
    r = ctx->seed;
    a = b = c = d = e = f = g = h = isaac_golden_ratio32; /* the golden ratio */

    /* init seed */
    for (i=0; i<256; ++i) {
        r[i] = (ub4) (time_as_seed? time(0) : 0);
    }

    for (i=0; i<4; ++i) {                                 /* scramble it */
        mix32(a,b,c,d,e,f,g,h);
    }

    if (1) {
        /* initialize using the contents of r[] as the seed */
        for (i=0; i<RANDSIZ; i+=8) {
            a+=r[i  ]; b+=r[i+1]; c+=r[i+2]; d+=r[i+3];
            e+=r[i+4]; f+=r[i+5]; g+=r[i+6]; h+=r[i+7];
            mix32(a,b,c,d,e,f,g,h);
            m[i  ]=a; m[i+1]=b; m[i+2]=c; m[i+3]=d;
            m[i+4]=e; m[i+5]=f; m[i+6]=g; m[i+7]=h;
        }

        /* do a second pass to make all of the seed affect all of m */
        for (i=0; i<RANDSIZ; i+=8) {
            a+=m[i  ]; b+=m[i+1]; c+=m[i+2]; d+=m[i+3];
            e+=m[i+4]; f+=m[i+5]; g+=m[i+6]; h+=m[i+7];
            mix32(a,b,c,d,e,f,g,h);
            m[i  ]=a; m[i+1]=b; m[i+2]=c; m[i+3]=d;
            m[i+4]=e; m[i+5]=f; m[i+6]=g; m[i+7]=h;
        }
    } else {
        /* Never run to this: fill in m[] with messy stuff */
        for (i=0; i<RANDSIZ; i+=8) {
            mix32(a,b,c,d,e,f,g,h);
            m[i  ]=a; m[i+1]=b; m[i+2]=c; m[i+3]=d;
            m[i+4]=e; m[i+5]=f; m[i+6]=g; m[i+7]=h;
        }
    }

    isaac32(ctx);              /* fill in the first set of results */
    ctx->randcnt = RANDSIZ;  /* prepare to use the first set of results */
}

/**
* randint
*   get 32-bits unsigned integer random
*/
ub4 rand(randctx *r)
{
    return gen_rand32(r);
}

/**
* randint
*   get integer random between rmin and rmax
*/
ub4 randint(randctx *r, ub4 rmin, ub4 rmax)
{
    if (! r->randcnt-- ) {
        isaac32(r);
        r->randcnt = RANDSIZ - 1;
    }

    ub4 ret = (ub4) r->seed[r->randcnt];

    return ret % (ub4) (rmax - rmin + 1) + rmin;
}

/**
*==============================================================================
* 64 bits int random generator
*==============================================================================
*/
#define isaac_golden_ratio64  0x9e3779b97f4a7c13LL
#define ind64(mm,x)  (*(ub8 *)((ub1 *)(mm) + ((x) & ((RANDSIZ-1)<<3))))
#define rngstep64(mix,a,b,mm,m,m2,r,x) \
{ \
    x = *m;  \
    a = (mix) + *(m2++); \
    *(m++) = y = ind64(mm,x) + a + b; \
    *(r++) = b = ind64(mm,y>>RANDSIZL) + x; \
}

#define mix64(a,b,c,d,e,f,g,h) \
{ \
    a-=e; f^=h>>9;  h+=a; \
    b-=f; g^=a<<9;  a+=b; \
    c-=g; h^=b>>23; b+=c; \
    d-=h; a^=c<<15; c+=d; \
    e-=a; b^=d>>14; d+=e; \
    f-=b; c^=e<<20; e+=f; \
    g-=c; d^=f>>17; f+=g; \
    h-=d; e^=g<<14; g+=h; \
}

static void isaac64(randctx64 *ctx)
{
    register ub8 a,b,x,y,*m,*mm,*m2,*r,*mend;
    mm = ctx->mm;
    r = ctx->seed;
    a = ctx->aa;
    b = ctx->bb + (++ctx->cc);

    for (m = mm, mend = m2 = m+(RANDSIZ/2); m<mend; ) {
        rngstep64(~(a^(a<<21)), a, b, mm, m, m2, r, x);
        rngstep64(  a^(a>>5)  , a, b, mm, m, m2, r, x);
        rngstep64(  a^(a<<12) , a, b, mm, m, m2, r, x);
        rngstep64(  a^(a>>33) , a, b, mm, m, m2, r, x);
    }

    for (m2 = mm; m2<mend; ) {
        rngstep64(~(a^(a<<21)), a, b, mm, m, m2, r, x);
        rngstep64(  a^(a>>5)  , a, b, mm, m, m2, r, x);
        rngstep64(  a^(a<<12) , a, b, mm, m, m2, r, x);
        rngstep64(  a^(a>>33) , a, b, mm, m, m2, r, x);
    }
    ctx->bb = b;
    ctx->aa = a;
}

#define gen_rand64(r) \
    (!(r)->randcnt-- ? (isaac64(r), (r)->randcnt=RANDSIZ-1, (r)->seed[(r)->randcnt]) : \
        (r)->seed[(r)->randcnt])

void rand64_init(randctx64 *ctx, word time_as_seed)
{
    word i;
    ub8 a,b,c,d,e,f,g,h;
    ub8 *mm, *r;
    ctx->aa = ctx->bb = ctx->cc = (ub8) 0;

    a=b=c=d=e=f=g=h= isaac_golden_ratio64;  /* the golden ratio */

    mm = ctx->mm;
    r = ctx->seed;

    /* init seed */
    for (i=0; i<256; ++i) {
        r[i] = (ub8) (time_as_seed? time(0) : 0);
    }

    for (i=0; i<4; ++i) {                   /* scramble it */
        mix64(a,b,c,d,e,f,g,h);
    }

    for (i=0; i<RANDSIZ; i+=8) {  /* fill in mm[] with messy stuff */
        if (1) {               /* use all the information in the seed */
            a+=r[i  ]; b+=r[i+1]; c+=r[i+2]; d+=r[i+3];
            e+=r[i+4]; f+=r[i+5]; g+=r[i+6]; h+=r[i+7];
        }
        mix64(a,b,c,d,e,f,g,h);
        mm[i  ]=a; mm[i+1]=b; mm[i+2]=c; mm[i+3]=d;
        mm[i+4]=e; mm[i+5]=f; mm[i+6]=g; mm[i+7]=h;
    }

    if (1) {
        /* do a second pass to make all of the seed affect all of mm */
        for (i=0; i<RANDSIZ; i+=8) {
            a+=mm[i  ]; b+=mm[i+1]; c+=mm[i+2]; d+=mm[i+3];
            e+=mm[i+4]; f+=mm[i+5]; g+=mm[i+6]; h+=mm[i+7];
            mix64(a,b,c,d,e,f,g,h);
            mm[i  ]=a; mm[i+1]=b; mm[i+2]=c; mm[i+3]=d;
            mm[i+4]=e; mm[i+5]=f; mm[i+6]=g; mm[i+7]=h;
        }
    }

    isaac64(ctx);             /* fill in the first set of results */
    ctx->randcnt = RANDSIZ;   /* prepare to use the first set of results */
}

/**
* rand64
*   get 64-bits unsigned integer random
*/
ub8 rand64(randctx64 *r)
{
    return (ub8) (gen_rand64(r));
}

/**
* randint64
*   get 64-bits unsigned integer random
*/
ub8 randint64(randctx64 *r, ub8 rmin, ub8 rmax)
{
    if (! r->randcnt-- ) {
        isaac64(r);
        r->randcnt = RANDSIZ - 1;
    }

    ub8 ret = (ub8) r->seed[r->randcnt];

    return ret % (ub8) (rmax - rmin + 1) + rmin;
}

#ifdef NEVER
static void inner_test32()
{
    ub4 i,j;
    randctx ctx;
    rand_init(&ctx, RAND_FALSE);

    for (i=0; i<2; ++i) {
        isaac32(&ctx);

        for (j=0; j<256; ++j) {
            printf("%.8lx",ctx.seed[j]);
            if ((j&7)==7) {
                printf("\n");
            }
        }
    }
}

static void inner_test64()
{
    ub8 i,j;
    randctx64 ctx;
    rand64_init(&ctx, RAND_FALSE);

    for (i=0; i<2; ++i) {
        isaac64(&ctx);

        for (j=0; j<RANDSIZ; ++j) {
            printf("%.8lx%.8lx",(ub4)(ctx.seed[j]>>32),(ub4)ctx.seed[j]);

            if ((j&3)==3) {
                printf("\n");
            }
        }
    }
}

static void usage()
{
    int i;

    randctx ctx;
    randctx64 ctx64;

    rand_init(&ctx, RAND_TRUE);

    rand64_init(&ctx64, RAND_TRUE);

    for (i=0; i<100; ++i) {
        printf("%03d: %d\n", i, (sb4)randint(&ctx, -100, 100));
        printf("%03d: %lld\n", i, (sb8)randint64(&ctx64, -100, 100));
    }
}

int main()
{
    inner_test32();
    inner_test64();

    usage();
}

#endif

C语言生成32位和64位随机数算法的更多相关文章

  1. 64位主机64位oracle下装32位客户端ODAC(NFPACS版)

    64位主机64位oracle下装32位客户端ODAC(NFPACS版) by dd 1.下载Oracle Data Access Components(ODAC) Xcopy的两个版本: x86:(我 ...

  2. Linux系统查看系统是32位还是64位方法总结

    这篇博客是总结.归纳查看Linux系统是32位还是64位的一些方法,很多内容来自网上网友的博客.本篇只是整理.梳理这方面的知识,方便自己忘记的时候随时查看. 方法1:getconf LONG_BIT ...

  3. oracle 32位导64位

    oracle 32位导64位 SHUTDOWN IMMEDIATE; STARTUP MOUNT; ALTER SYSTEM ENABLE RESTRICTED SESSION; ; ; ALTER ...

  4. Shell脚本中,如何判断Linux系统是32位还是64位?

    一行就能搞定,输出32或者64 可以用“和. 参考代码如下: ldconfig if [ $(getconf WORD_BIT) = '32' ] && [ $(getconf LON ...

  5. 【转】Tomcat版本是32位、64位问题

    转载地址:http://www.cnblogs.com/greensleeves/p/3168541.html 最近遇到一个Tomcat windows安装版本是32位还是64位问题.由于一系列原因, ...

  6. 查看Linux是32位还是64位

    最直接简洁的办法: 在linux终端输入getconf LONG_BIT命令 如果是32位机器,则结果为32 [root@localhost ~]# getconf LONG_BIT 32 如果是64 ...

  7. Windows2003 IIS6.0支持32位和64位两种模式的设置方法

    IIS 6.0 可支持 32 位和 64 位两种模式.但是,IIS 6.0 不支持在 64 位版本的 Windows 上同时运行这两种模式.ASP.NET 1.1 只在 32 位模式下运行.而 ASP ...

  8. linux-查看系统是32位还是64位

    可以用命令“getconf LONG_BIT”查看, 如果返回的结果是32则说明是32位,返回的结果是64则说明是64位. 此外还可以使用命令“uname -a”查看, 输出的结果中,如果有x86_6 ...

  9. 查看linux机器是32位还是64位的方法

    file /sbin/init 或者 file /bin/ls/sbin/init: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dyna ...

随机推荐

  1. Latex 文本编辑技巧

    临时取消首行缩进 \noindent 生成随机文本 \usepackage{lipsum} \begin{document} \lipsum \end{document} 多栏模式 \usepacka ...

  2. Dynamics CRM 删除字段时检测到有组件类型为查看的依赖组件而无法删除问题

    今天在删除一个字段的时候报如下截图错误,点开详细信息会看到是一个快速查找视图,但却在视图列中没有找到我要删的那个字段,然后回过头来又看到组件类型是查看,这是啥类型?有点摸不着头脑了. 最后想到是不是查 ...

  3. java项目管理工具maven使用初级

    一.前言        早就知道maven 在java 项目的管理方面名声显赫,于是就想着学习掌握之,于是查阅了大量文档.发现这些文档的作者都是java 的大腕,大多都是站在掌握了一定maven 基础 ...

  4. [ExtJS5学习笔记]第二十五节 利用window.open()函数实现ExtJS5的登陆页面跳转

    本文地址:http://blog.csdn.net/sushengmiyan/article/details/40427543 mvvm方式实现登陆的博客:http://blog.csdn.net/s ...

  5. Linux2.6 --系统调用处理程序

          用户空间的程序无法直接执行内核代码.它们不能直接调用内核空间中的函数,因为内核驻留在受保护的地址空间上.如果进程可以直接在内核的地址空间上读写的话,系统的安全性和稳定性将不复存在.     ...

  6. Android的RadioButton和checkBox的用法-android学习之旅(十九)

    RadioButton和checkBox简介 单选按钮(RadioButton)和复选框(CheckBox)都继承了Button,因此属性的设置和Button差不多,只是加了一个android:che ...

  7. Transform介绍(Unity3D开发之二)

    猴子原创,欢迎转载.转载请注明: 转载自Cocos2D开发网–Cocos2Dev.com,谢谢! 原文地址: http://www.cocos2dev.com/?p=491 可能unity中接触较早的 ...

  8. android 使用Vysor投影到电脑

    有没有好的投影软件可以将android屏幕投影到电脑,当然这种很多,比如360就自带了投影功能,小米盒子也可以(不过貌似只能支持到4.4版本),今天要说的是Vysor,google的一款投影软件. V ...

  9. (一一七)基本文件操作 -SDWebImage清除缓存 -文件夹的大小计算

    在iOS的App沙盒中,Documents和Library/Preferences都会被备份到iCloud,因此只适合放置一些记录文件,例如plist.数据库文件.缓存一般放置到Library/Cac ...

  10. Postgre: How to import UUID function into Postgre 9.3

    1. Open a command console and go to the directory where you installed Postgre server. e.g. D:\Progra ...