blob: 4d0ed13d1d9d9e3b834552cdfef5fa07c1e2d3e8 [file] [log] [blame]
/***************************************************************************
*
* random.cpp - random number generator
*
* $Id$
*
***************************************************************************
*
* Copyright (c) 1994
* Hewlett-Packard Company
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation. Hewlett-Packard Company makes no
* representations about the suitability of this software for any
* purpose. It is provided "as is" without express or implied warranty.
*
***************************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the License); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*
* Copyright 1994-2006 Rogue Wave Software, Inc.
*
**************************************************************************/
#define _RWSTD_LIB_SRC
#include <rw/_defs.h>
#ifdef _RWSTD_REENTRANT
# include <rw/_mutex.h>
#endif // _RWSTD_REENTRANT
#include <stddef.h> // for size_t
_RWSTD_NAMESPACE (__rw) {
#ifndef _RWSTD_NO_EXT_PORTABLE_RANDOM_SEQUENCE
// generator produces the same sequence of random numbers
// irrespective of the architecture and width of integers
typedef _RWSTD_UINT32_T __rw_random_t;
#else // if defined (_RWSTD_NO_EXT_PORTABLE_RANDOM_SEQUENCE)
// generator may produces a different sequence of random numbers
// on different architectures (depending on the width of size_t)
typedef size_t __rw_random_t;
#endif // _RWSTD_NO_EXT_PORTABLE_RANDOM_SEQUENCE
static _RWSTD_THREAD __rw_random_t
__rw_table [55];
static _RWSTD_THREAD __rw_random_t
__rw_inx [2];
static const __rw_random_t
__rw_table_size = __rw_random_t (sizeof __rw_table / sizeof *__rw_table);
static void
__rw_seed ( __rw_random_t seed)
{
__rw_table [__rw_table_size - 1] = seed;
size_t i;
__rw_random_t k = 1;
for (i = 0; i != __rw_table_size - 1; ++i) {
const size_t ii = 21U * i % __rw_table_size;
__rw_table [ii] = k;
k = seed - k;
seed = __rw_table [ii];
}
for (i = 0; i != 4U; ++i) {
for (size_t ii = 0; ii != __rw_table_size; ++ii)
__rw_table [i] =
__rw_table [i] - __rw_table [(i + 31U) % __rw_table_size];
}
__rw_inx [0] = 0U;
__rw_inx [1] = __rw_table_size * 2U / 3U - 1U;
}
struct _RandGuardT;
_RWSTD_EXPORT size_t
__rw_rand (size_t limit)
{
_RWSTD_ASSERT (0 != limit);
#ifdef _RWSTD_NO_TLS
_RWSTD_MT_STATIC_GUARD (_RandGuardT);
#endif // _RWSTD_NO_TLS
if (0 == __rw_inx [0] && 0 == __rw_inx [1])
__rw_seed (161803398U);
__rw_table [++__rw_inx [0] %= __rw_table_size] -=
__rw_table [++__rw_inx [1] %= __rw_table_size];
return __rw_table [__rw_inx [0]] % limit;
}
} // namespace __rw