17c2fbfb3SApril Chin /***********************************************************************
27c2fbfb3SApril Chin *                                                                      *
37c2fbfb3SApril Chin *               This software is part of the ast package               *
4*b30d1939SAndy Fiddaman *          Copyright (c) 1996-2011 AT&T Intellectual Property          *
57c2fbfb3SApril Chin *                      and is licensed under the                       *
6*b30d1939SAndy Fiddaman *                 Eclipse Public License, Version 1.0                  *
77c2fbfb3SApril Chin *                    by AT&T Intellectual Property                     *
87c2fbfb3SApril Chin *                                                                      *
97c2fbfb3SApril Chin *                A copy of the License is available at                 *
10*b30d1939SAndy Fiddaman *          http://www.eclipse.org/org/documents/epl-v10.html           *
11*b30d1939SAndy Fiddaman *         (with md5 checksum b35adb5213ca9657e911e9befb180842)         *
127c2fbfb3SApril Chin *                                                                      *
137c2fbfb3SApril Chin *              Information and Software Systems Research               *
147c2fbfb3SApril Chin *                            AT&T Research                             *
157c2fbfb3SApril Chin *                           Florham Park NJ                            *
167c2fbfb3SApril Chin *                                                                      *
177c2fbfb3SApril Chin *                 Glenn Fowler <gsf@research.att.com>                  *
187c2fbfb3SApril Chin *                                                                      *
197c2fbfb3SApril Chin ***********************************************************************/
207c2fbfb3SApril Chin #pragma prototyped
217c2fbfb3SApril Chin 
227c2fbfb3SApril Chin /*
237c2fbfb3SApril Chin  * prng
247c2fbfb3SApril Chin  */
257c2fbfb3SApril Chin 
267c2fbfb3SApril Chin #include <fnv.h>
277c2fbfb3SApril Chin 
287c2fbfb3SApril Chin #define prng_description \
297c2fbfb3SApril Chin 	"32 bit PRNG (pseudo random number generator) hash."
307c2fbfb3SApril Chin #define prng_options	"\
317c2fbfb3SApril Chin [+mpy?The 32 bit PRNG multiplier.]:[number:=0x01000193]\
327c2fbfb3SApril Chin [+add?The 32 bit PRNG addend.]:[number:=0]\
337c2fbfb3SApril Chin [+init?The PRNG initial value. 0xffffffff is used if \anumber\a is omitted.]:?[number:=0x811c9dc5]\
347c2fbfb3SApril Chin "
357c2fbfb3SApril Chin #define prng_match	"prng"
367c2fbfb3SApril Chin #define prng_done	long_done
377c2fbfb3SApril Chin #define prng_print	long_print
387c2fbfb3SApril Chin #define prng_data	long_data
397c2fbfb3SApril Chin #define prng_scale	0
407c2fbfb3SApril Chin 
417c2fbfb3SApril Chin typedef uint32_t Prngnum_t;
427c2fbfb3SApril Chin 
437c2fbfb3SApril Chin typedef struct Prng_s
447c2fbfb3SApril Chin {
457c2fbfb3SApril Chin 	_SUM_PUBLIC_
467c2fbfb3SApril Chin 	_SUM_PRIVATE_
477c2fbfb3SApril Chin 	_INTEGRAL_PRIVATE_
487c2fbfb3SApril Chin 	Prngnum_t		init;
497c2fbfb3SApril Chin 	Prngnum_t		mpy;
507c2fbfb3SApril Chin 	Prngnum_t		add;
517c2fbfb3SApril Chin } Prng_t;
527c2fbfb3SApril Chin 
537c2fbfb3SApril Chin static Sum_t*
prng_open(const Method_t * method,const char * name)547c2fbfb3SApril Chin prng_open(const Method_t* method, const char* name)
557c2fbfb3SApril Chin {
567c2fbfb3SApril Chin 	register Prng_t*	sum;
577c2fbfb3SApril Chin 	register const char*	s;
587c2fbfb3SApril Chin 	register const char*	t;
597c2fbfb3SApril Chin 	register const char*	v;
607c2fbfb3SApril Chin 	register int		i;
617c2fbfb3SApril Chin 
627c2fbfb3SApril Chin 	if (sum = newof(0, Prng_t, 1, 0))
637c2fbfb3SApril Chin 	{
647c2fbfb3SApril Chin 		sum->method = (Method_t*)method;
657c2fbfb3SApril Chin 		sum->name = name;
667c2fbfb3SApril Chin 	}
677c2fbfb3SApril Chin 	s = name;
687c2fbfb3SApril Chin 	while (*(t = s))
697c2fbfb3SApril Chin 	{
707c2fbfb3SApril Chin 		for (t = s, v = 0; *s && *s != '-'; s++)
717c2fbfb3SApril Chin 			if (*s == '=' && !v)
727c2fbfb3SApril Chin 				v = s;
737c2fbfb3SApril Chin 		i = (v ? v : s) - t;
747c2fbfb3SApril Chin 		if (isdigit(*t) || v && strneq(t, "mpy", i) && (t = v + 1))
757c2fbfb3SApril Chin 			sum->mpy = strtoul(t, NiL, 0);
767c2fbfb3SApril Chin 		else if (strneq(t, "add", i))
777c2fbfb3SApril Chin 			sum->add = v ? strtoul(v + 1, NiL, 0) : ~sum->add;
787c2fbfb3SApril Chin 		else if (strneq(t, "init", i))
797c2fbfb3SApril Chin 			sum->init = v ? strtoul(v + 1, NiL, 0) : ~sum->init;
807c2fbfb3SApril Chin 		if (*s == '-')
817c2fbfb3SApril Chin 			s++;
827c2fbfb3SApril Chin 	}
837c2fbfb3SApril Chin 	if (!sum->mpy)
847c2fbfb3SApril Chin 	{
857c2fbfb3SApril Chin 		sum->mpy = FNV_MULT;
867c2fbfb3SApril Chin 		if (!sum->init)
877c2fbfb3SApril Chin 			sum->init = FNV_INIT;
887c2fbfb3SApril Chin 	}
897c2fbfb3SApril Chin 	return (Sum_t*)sum;
907c2fbfb3SApril Chin }
917c2fbfb3SApril Chin 
927c2fbfb3SApril Chin static int
prng_init(Sum_t * p)937c2fbfb3SApril Chin prng_init(Sum_t* p)
947c2fbfb3SApril Chin {
957c2fbfb3SApril Chin 	Prng_t*		sum = (Prng_t*)p;
967c2fbfb3SApril Chin 
977c2fbfb3SApril Chin 	sum->sum = sum->init;
987c2fbfb3SApril Chin 	return 0;
997c2fbfb3SApril Chin }
1007c2fbfb3SApril Chin 
1017c2fbfb3SApril Chin static int
prng_block(Sum_t * p,const void * s,size_t n)1027c2fbfb3SApril Chin prng_block(Sum_t* p, const void* s, size_t n)
1037c2fbfb3SApril Chin {
1047c2fbfb3SApril Chin 	Prng_t*			sum = (Prng_t*)p;
1057c2fbfb3SApril Chin 	register Prngnum_t	c = sum->sum;
1067c2fbfb3SApril Chin 	register unsigned char*	b = (unsigned char*)s;
1077c2fbfb3SApril Chin 	register unsigned char*	e = b + n;
1087c2fbfb3SApril Chin 
1097c2fbfb3SApril Chin 	while (b < e)
1107c2fbfb3SApril Chin 		c = c * sum->mpy + sum->add + *b++;
1117c2fbfb3SApril Chin 	sum->sum = c;
1127c2fbfb3SApril Chin 	return 0;
1137c2fbfb3SApril Chin }
114