1d722e3fbSopenharmony_ci/* xf86drmRandom.c -- "Minimal Standard" PRNG Implementation 2d722e3fbSopenharmony_ci * Created: Mon Apr 19 08:28:13 1999 by faith@precisioninsight.com 3d722e3fbSopenharmony_ci * 4d722e3fbSopenharmony_ci * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. 5d722e3fbSopenharmony_ci * All Rights Reserved. 6d722e3fbSopenharmony_ci * 7d722e3fbSopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 8d722e3fbSopenharmony_ci * copy of this software and associated documentation files (the "Software"), 9d722e3fbSopenharmony_ci * to deal in the Software without restriction, including without limitation 10d722e3fbSopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11d722e3fbSopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 12d722e3fbSopenharmony_ci * Software is furnished to do so, subject to the following conditions: 13d722e3fbSopenharmony_ci * 14d722e3fbSopenharmony_ci * The above copyright notice and this permission notice (including the next 15d722e3fbSopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 16d722e3fbSopenharmony_ci * Software. 17d722e3fbSopenharmony_ci * 18d722e3fbSopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19d722e3fbSopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20d722e3fbSopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 21d722e3fbSopenharmony_ci * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 22d722e3fbSopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 23d722e3fbSopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 24d722e3fbSopenharmony_ci * DEALINGS IN THE SOFTWARE. 25d722e3fbSopenharmony_ci * 26d722e3fbSopenharmony_ci * Authors: Rickard E. (Rik) Faith <faith@valinux.com> 27d722e3fbSopenharmony_ci * 28d722e3fbSopenharmony_ci * DESCRIPTION 29d722e3fbSopenharmony_ci * 30d722e3fbSopenharmony_ci * This file contains a simple, straightforward implementation of the Park 31d722e3fbSopenharmony_ci * & Miller "Minimal Standard" PRNG [PM88, PMS93], which is a Lehmer 32d722e3fbSopenharmony_ci * multiplicative linear congruential generator (MLCG) with a period of 33d722e3fbSopenharmony_ci * 2^31-1. 34d722e3fbSopenharmony_ci * 35d722e3fbSopenharmony_ci * This implementation is intended to provide a reliable, portable PRNG 36d722e3fbSopenharmony_ci * that is suitable for testing a hash table implementation and for 37d722e3fbSopenharmony_ci * implementing skip lists. 38d722e3fbSopenharmony_ci * 39d722e3fbSopenharmony_ci * FUTURE ENHANCEMENTS 40d722e3fbSopenharmony_ci * 41d722e3fbSopenharmony_ci * If initial seeds are not selected randomly, two instances of the PRNG 42d722e3fbSopenharmony_ci * can be correlated. [Knuth81, pp. 32-33] describes a shuffling technique 43d722e3fbSopenharmony_ci * that can eliminate this problem. 44d722e3fbSopenharmony_ci * 45d722e3fbSopenharmony_ci * If PRNGs are used for simulation, the period of the current 46d722e3fbSopenharmony_ci * implementation may be too short. [LE88] discusses methods of combining 47d722e3fbSopenharmony_ci * MLCGs to produce much longer periods, and suggests some alternative 48d722e3fbSopenharmony_ci * values for A and M. [LE90 and Sch92] also provide information on 49d722e3fbSopenharmony_ci * long-period PRNGs. 50d722e3fbSopenharmony_ci * 51d722e3fbSopenharmony_ci * REFERENCES 52d722e3fbSopenharmony_ci * 53d722e3fbSopenharmony_ci * [Knuth81] Donald E. Knuth. The Art of Computer Programming. Volume 2: 54d722e3fbSopenharmony_ci * Seminumerical Algorithms. Reading, Massachusetts: Addison-Wesley, 1981. 55d722e3fbSopenharmony_ci * 56d722e3fbSopenharmony_ci * [LE88] Pierre L'Ecuyer. "Efficient and Portable Combined Random Number 57d722e3fbSopenharmony_ci * Generators". CACM 31(6), June 1988, pp. 742-774. 58d722e3fbSopenharmony_ci * 59d722e3fbSopenharmony_ci * [LE90] Pierre L'Ecuyer. "Random Numbers for Simulation". CACM 33(10, 60d722e3fbSopenharmony_ci * October 1990, pp. 85-97. 61d722e3fbSopenharmony_ci * 62d722e3fbSopenharmony_ci * [PM88] Stephen K. Park and Keith W. Miller. "Random Number Generators: 63d722e3fbSopenharmony_ci * Good Ones are Hard to Find". CACM 31(10), October 1988, pp. 1192-1201. 64d722e3fbSopenharmony_ci * 65d722e3fbSopenharmony_ci * [Sch92] Bruce Schneier. "Pseudo-Ransom Sequence Generator for 32-Bit 66d722e3fbSopenharmony_ci * CPUs". Dr. Dobb's Journal 17(2), February 1992, pp. 34, 37-38, 40. 67d722e3fbSopenharmony_ci * 68d722e3fbSopenharmony_ci * [PMS93] Stephen K. Park, Keith W. Miller, and Paul K. Stockmeyer. In 69d722e3fbSopenharmony_ci * "Technical Correspondence: Remarks on Choosing and Implementing Random 70d722e3fbSopenharmony_ci * Number Generators". CACM 36(7), July 1993, pp. 105-110. 71d722e3fbSopenharmony_ci * 72d722e3fbSopenharmony_ci */ 73d722e3fbSopenharmony_ci 74d722e3fbSopenharmony_ci#include <stdio.h> 75d722e3fbSopenharmony_ci#include <stdlib.h> 76d722e3fbSopenharmony_ci 77d722e3fbSopenharmony_ci#include "libdrm_macros.h" 78d722e3fbSopenharmony_ci#include "xf86drm.h" 79d722e3fbSopenharmony_ci#include "xf86drmRandom.h" 80d722e3fbSopenharmony_ci 81d722e3fbSopenharmony_ci#define RANDOM_MAGIC 0xfeedbeef 82d722e3fbSopenharmony_ci 83d722e3fbSopenharmony_cidrm_public void *drmRandomCreate(unsigned long seed) 84d722e3fbSopenharmony_ci{ 85d722e3fbSopenharmony_ci RandomState *state; 86d722e3fbSopenharmony_ci 87d722e3fbSopenharmony_ci state = drmMalloc(sizeof(*state)); 88d722e3fbSopenharmony_ci if (!state) return NULL; 89d722e3fbSopenharmony_ci state->magic = RANDOM_MAGIC; 90d722e3fbSopenharmony_ci#if 0 91d722e3fbSopenharmony_ci /* Park & Miller, October 1988 */ 92d722e3fbSopenharmony_ci state->a = 16807; 93d722e3fbSopenharmony_ci state->m = 2147483647; 94d722e3fbSopenharmony_ci state->check = 1043618065; /* After 10000 iterations */ 95d722e3fbSopenharmony_ci#else 96d722e3fbSopenharmony_ci /* Park, Miller, and Stockmeyer, July 1993 */ 97d722e3fbSopenharmony_ci state->a = 48271; 98d722e3fbSopenharmony_ci state->m = 2147483647; 99d722e3fbSopenharmony_ci state->check = 399268537; /* After 10000 iterations */ 100d722e3fbSopenharmony_ci#endif 101d722e3fbSopenharmony_ci state->q = state->m / state->a; 102d722e3fbSopenharmony_ci state->r = state->m % state->a; 103d722e3fbSopenharmony_ci 104d722e3fbSopenharmony_ci state->seed = seed; 105d722e3fbSopenharmony_ci /* Check for illegal boundary conditions, 106d722e3fbSopenharmony_ci and choose closest legal value. */ 107d722e3fbSopenharmony_ci if (state->seed <= 0) state->seed = 1; 108d722e3fbSopenharmony_ci if (state->seed >= state->m) state->seed = state->m - 1; 109d722e3fbSopenharmony_ci 110d722e3fbSopenharmony_ci return state; 111d722e3fbSopenharmony_ci} 112d722e3fbSopenharmony_ci 113d722e3fbSopenharmony_cidrm_public int drmRandomDestroy(void *state) 114d722e3fbSopenharmony_ci{ 115d722e3fbSopenharmony_ci drmFree(state); 116d722e3fbSopenharmony_ci return 0; 117d722e3fbSopenharmony_ci} 118d722e3fbSopenharmony_ci 119d722e3fbSopenharmony_cidrm_public unsigned long drmRandom(void *state) 120d722e3fbSopenharmony_ci{ 121d722e3fbSopenharmony_ci RandomState *s = (RandomState *)state; 122d722e3fbSopenharmony_ci unsigned long hi; 123d722e3fbSopenharmony_ci unsigned long lo; 124d722e3fbSopenharmony_ci 125d722e3fbSopenharmony_ci hi = s->seed / s->q; 126d722e3fbSopenharmony_ci lo = s->seed % s->q; 127d722e3fbSopenharmony_ci s->seed = s->a * lo - s->r * hi; 128d722e3fbSopenharmony_ci if ((s->a * lo) <= (s->r * hi)) s->seed += s->m; 129d722e3fbSopenharmony_ci 130d722e3fbSopenharmony_ci return s->seed; 131d722e3fbSopenharmony_ci} 132d722e3fbSopenharmony_ci 133d722e3fbSopenharmony_cidrm_public double drmRandomDouble(void *state) 134d722e3fbSopenharmony_ci{ 135d722e3fbSopenharmony_ci RandomState *s = (RandomState *)state; 136d722e3fbSopenharmony_ci 137d722e3fbSopenharmony_ci return (double)drmRandom(state)/(double)s->m; 138d722e3fbSopenharmony_ci} 139