鉴于标题 rand.h 包含:
#ifndef STANDARD
#include "standard.h"
#endif
#ifndef RAND
#define RAND
#define RANDSIZL (8)
#define RANDSIZ (1<<RANDSIZL)
/* context of random number generator */
struct randctx
{
ub4 randcnt;
ub4 randrsl[RANDSIZ];
ub4 randmem[RANDSIZ];
ub4 randa;
ub4 randb;
ub4 randc;
};
typedef struct randctx randctx;
/* If (flag==TRUE), then use the contents of randrsl[0..RANDSIZ-1] as the seed. */
void randinit(/*_ randctx *r, word flag _*/);
void isaac(/*_ randctx *r _*/);
/* Call rand(/o_ randctx *r _o/) to retrieve a single 32-bit random value */
#define rand(r) \
(!(r)->randcnt-- ? \
(isaac(r), (r)->randcnt=RANDSIZ-1, (r)->randrsl[(r)->randcnt]) : \
(r)->randrsl[(r)->randcnt])
#endif /* RAND */
您将需要对代码做一些工作,以便能够与来自<stdlib.h> 的rand() 一起使用它。 ISAAC rand() 的接口与<stdlib.h> 到rand() 的接口也不同。
为自己创建一个新标头"isaac.h",它定义了处理 ISAAC 系统特性的覆盖函数。
也许,如果您不打算在线程上下文中工作
#ifndef ISAAC_H_INCLUDED
#define ISAAC_H_INCLUDED
extern void isaac_init(unsigned long seed);
extern int isaac_rand(void);
#endif
然后您在isaac.c 中实现这些函数,以便它们调用rand.h 中定义的函数,并且isaac_rand() 包含来自rand.h 的rand() 宏的调用(从某处提供上下文,这是非螺纹部分的来源)。您可以决定如何处理seed,或者是否更改种子机制。
然后您可以在代码中使用isaac_init() 和isaac_rand() 函数,以及普通的rand() 和srand()。
我还将升级rand.h 中的代码,为包中的功能提供完整的原型。注释原型是 90 年代中期首次编写时遗留下来的,当时标准 C 编译器还没有被普遍使用。标题中最早的日期是 1996 年;这正处于标准 C 编译器几乎普遍可用的风口浪尖。
我注意到标题中的 cmets(上面已删除)表示代码在公共域中;这意味着进行您需要的任何修改都是 100% 合法的。
isaac.c
#include "isaac.h"
#include "rand.h"
static randctx control;
void isaac_init(unsigned long seed)
{
assert(seed != 0);
randinit(&control, FALSE);
}
int isaac_rand(void)
{
return rand(&control);
}
此实现忽略了您提供的种子,主要是因为该结构需要八个 32 位数字来为上下文结构的 randrsl 成员(我称为 control)提供种子。你可以做一些事情,比如连续使用种子值 8 次而不是完全忽略它,或者每次都添加一些数字,或者任何其他更复杂的播种技术。您应该认真考虑使用/dev/urandom 作为种子的来源:
#define DEV_URANDOM "/dev/urandom"
int ur = open(DEV_URANDOM, O_RDONLY);
if (ur >= 0)
{
read(ur, control.randrsl, sizeof(control.randrsl));
close(ur);
}
在调用randinit() 之前将此代码放入isaac_init(),并将FALSE 更改为TRUE。您可能还会丢失 seed 函数的 seed 参数。
这给您带来了跟踪随机种子以获得可重复性的问题(这在调试时可能很重要)。不过,这是由你来解决的——有多种方法可以做到这一点。您可能有两个初始化函数:void isaac_init(void) 和 void isaac_rsl(unsigned int *rsl),它们接受一个包含 8 个unsigned int(或ub4)值的数组并将其用作种子而不是/dev/urandom 的输出。或者您可以传递一个空指针来表示“使用来自/dev/urandom 的输出”,传递一个非空指针来表示“使用我提供的值”。等等。