OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [language/] [c/] [libc/] [stdlib/] [current/] [src/] [rand.cxx] - Blame information for rev 786

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 786 skrzyp
//===========================================================================
2
//
3
//      rand.cxx
4
//
5
//      ISO and POSIX 1003.1 standard random number generation functions
6
//
7
//===========================================================================
8
// ####ECOSGPLCOPYRIGHTBEGIN####                                            
9
// -------------------------------------------                              
10
// This file is part of eCos, the Embedded Configurable Operating System.   
11
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
12
//
13
// eCos is free software; you can redistribute it and/or modify it under    
14
// the terms of the GNU General Public License as published by the Free     
15
// Software Foundation; either version 2 or (at your option) any later      
16
// version.                                                                 
17
//
18
// eCos is distributed in the hope that it will be useful, but WITHOUT      
19
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or    
20
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License    
21
// for more details.                                                        
22
//
23
// You should have received a copy of the GNU General Public License        
24
// along with eCos; if not, write to the Free Software Foundation, Inc.,    
25
// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.            
26
//
27
// As a special exception, if other files instantiate templates or use      
28
// macros or inline functions from this file, or you compile this file      
29
// and link it with other works to produce a work based on this file,       
30
// this file does not by itself cause the resulting work to be covered by   
31
// the GNU General Public License. However the source code for this file    
32
// must still be made available in accordance with section (3) of the GNU   
33
// General Public License v2.                                               
34
//
35
// This exception does not invalidate any other reasons why a work based    
36
// on this file might be covered by the GNU General Public License.         
37
// -------------------------------------------                              
38
// ####ECOSGPLCOPYRIGHTEND####                                              
39
//===========================================================================
40
//#####DESCRIPTIONBEGIN####
41
//
42
// Author(s):     jlarmour
43
// Contributors:  
44
// Date:          2000-04-30
45
// Purpose:       Provides ISO C rand() and srand() functions, along with
46
//                POSIX 1003.1 rand_r() function
47
// Description:   This implements rand() and srand() of section 7.10.2.1 of
48
//                the ISO C standard. Also rand_r() defined in section 8.3.8
49
//                of the POSIX 1003.1 standard
50
// Usage:       
51
//
52
//####DESCRIPTIONEND####
53
//
54
//===========================================================================
55
 
56
// CONFIGURATION
57
 
58
#include <pkgconf/libc_stdlib.h>   // Configuration header
59
 
60
// INCLUDES
61
 
62
#include <cyg/infra/cyg_type.h>    // Common type definitions and support
63
#include <cyg/infra/cyg_trac.h>    // Tracing support
64
#include <cyg/infra/cyg_ass.h>     // Assertion support
65
#include <stdlib.h>                // Header for all stdlib functions
66
                                   // (like this one)
67
 
68
#ifdef CYGSEM_LIBC_PER_THREAD_RAND
69
# include <pkgconf/kernel.h>       // kernel configuration
70
# include <cyg/kernel/thread.hxx>  // per-thread data
71
# include <cyg/kernel/thread.inl>  // per-thread data
72
# include <cyg/kernel/mutex.hxx>   // mutexes
73
#endif
74
 
75
// TRACE
76
 
77
#if defined(CYGDBG_USE_TRACING) && defined(CYGNUM_LIBC_RAND_TRACE_LEVEL)
78
static int rand_trace = CYGNUM_LIBC_RAND_TRACE_LEVEL;
79
# define TL1 (0 < rand_trace)
80
#else
81
# define TL1 (0)
82
#endif
83
 
84
 
85
// STATICS
86
 
87
#ifdef CYGSEM_LIBC_PER_THREAD_RAND
88
static Cyg_Thread::cyg_data_index
89
rand_data_index=CYGNUM_KERNEL_THREADS_DATA_MAX;
90
 
91
static Cyg_Mutex rand_data_mutex CYGBLD_ATTRIB_INIT_PRI(CYG_INIT_LIBC);
92
#else
93
static unsigned int cyg_libc_rand_seed = CYGNUM_LIBC_RAND_SEED;
94
#endif
95
 
96
// FUNCTIONS
97
 
98
int
99
rand( void )
100
{
101
    unsigned int *seed_p;
102
    int retval;
103
 
104
    CYG_REPORT_FUNCNAMETYPE( "rand", "returning %d" );
105
 
106
    // get seed for this thread (if relevant )
107
#ifdef CYGSEM_LIBC_PER_THREAD_RAND
108
    Cyg_Thread *self = Cyg_Thread::self();
109
 
110
    // Get a per-thread data slot if we haven't got one already
111
    // Do a simple test before locking and retrying test, as this is a
112
    // rare situation
113
    if (CYGNUM_KERNEL_THREADS_DATA_MAX==rand_data_index) {
114
        rand_data_mutex.lock();
115
        if (CYGNUM_KERNEL_THREADS_DATA_MAX==rand_data_index) {
116
 
117
            // FIXME: Should use real CDL to pre-allocate a slot at compile
118
            // time to ensure there are enough slots
119
            rand_data_index = self->new_data_index();
120
            CYG_ASSERT(rand_data_index >= 0, "failed to allocate data index" );
121
 
122
            // Initialize seed
123
            self->set_data(rand_data_index, CYGNUM_LIBC_RAND_SEED);
124
        }
125
        rand_data_mutex.unlock();
126
    } // if
127
 
128
    // we have a valid index now
129
 
130
    seed_p = (unsigned int *)self->get_data_ptr(rand_data_index);
131
#else
132
    seed_p = &cyg_libc_rand_seed;
133
#endif
134
 
135
    CYG_TRACE2( TL1, "Retrieved seed address %08x containing %d",
136
                seed_p, *seed_p );
137
    CYG_CHECK_DATA_PTR( seed_p, "Help! Returned address of seed is invalid!" );
138
 
139
    retval = rand_r( seed_p );
140
 
141
    CYG_REPORT_RETVAL( retval );
142
 
143
    return retval;
144
 
145
} // rand()
146
 
147
 
148
int
149
rand_r( unsigned int *seed )
150
{
151
    int retval;
152
 
153
    CYG_REPORT_FUNCNAMETYPE( "rand_r", "returning %d" );
154
 
155
    CYG_CHECK_DATA_PTR( seed, "pointer to seed invalid!" );
156
 
157
#if defined(CYGIMP_LIBC_RAND_SIMPLEST)
158
 
159
    // This algorithm sucks in the lower bits
160
 
161
    *seed = (*seed * 1103515245) + 12345; // permutate seed
162
 
163
    retval = (int)( *seed & RAND_MAX );
164
 
165
#elif defined(CYGIMP_LIBC_RAND_SIMPLE1)
166
 
167
    // The above algorithm sucks in the lower bits, so we shave them off
168
    // and repeat a couple of times to make it up
169
 
170
    unsigned int s=*seed;
171
    unsigned int uret;
172
 
173
    s = (s * 1103515245) + 12345; // permutate seed
174
    // Only use top 11 bits
175
    uret = s & 0xffe00000;
176
 
177
    s = (s * 1103515245) + 12345; // permutate seed
178
    // Only use top 14 bits
179
    uret += (s & 0xfffc0000) >> 11;
180
 
181
    s = (s * 1103515245) + 12345; // permutate seed
182
    // Only use top 7 bits
183
    uret += (s & 0xfe000000) >> (11+14);
184
 
185
    retval = (int)(uret & RAND_MAX);
186
    *seed = s;
187
 
188
#elif defined(CYGIMP_LIBC_RAND_KNUTH1)
189
 
190
// This is the code supplied in Knuth Vol 2 section 3.6 p.185 bottom
191
 
192
#define MM 2147483647    // a Mersenne prime
193
#define AA 48271         // this does well in the spectral test
194
#define QQ 44488         // (long)(MM/AA)
195
#define RR 3399          // MM % AA; it is important that RR<QQ
196
 
197
    *seed = AA*(*seed % QQ) - RR*(unsigned int)(*seed/QQ);
198
    if (*seed < 0)
199
        *seed += MM;
200
 
201
    retval = (int)( *seed & RAND_MAX );
202
 
203
#else
204
# error No valid implementation for rand()!
205
#endif
206
 
207
    CYG_REPORT_RETVAL( retval );
208
 
209
    return retval;
210
 
211
} // rand_r()
212
 
213
 
214
void
215
srand( unsigned int seed )
216
{
217
    CYG_REPORT_FUNCNAME( "srand" );
218
 
219
    CYG_REPORT_FUNCARG1DV( (int)seed );
220
 
221
    // get seed for this thread ( if relevant )
222
#ifdef CYGSEM_LIBC_PER_THREAD_RAND
223
    Cyg_Thread *self = Cyg_Thread::self();
224
 
225
    // Get a per-thread data slot if we haven't got one already
226
    // Do a simple test before locking and retrying test, as this is a
227
    // rare situation
228
    if (CYGNUM_KERNEL_THREADS_DATA_MAX==rand_data_index) {
229
        rand_data_mutex.lock();
230
        if (CYGNUM_KERNEL_THREADS_DATA_MAX==rand_data_index) {
231
 
232
            // FIXME: Should use real CDL to pre-allocate a slot at compile
233
            // time to ensure there are enough slots
234
            rand_data_index = self->new_data_index();
235
            CYG_ASSERT(rand_data_index >= 0, "failed to allocate data index" );
236
        }
237
        rand_data_mutex.unlock();
238
    } // if
239
 
240
    // we have a valid index now
241
 
242
    self->set_data(rand_data_index, (CYG_ADDRWORD) seed);
243
#else
244
    cyg_libc_rand_seed = seed;
245
#endif
246
 
247
    CYG_REPORT_RETURN();
248
 
249
} // srand()
250
 
251
// EOF rand.cxx

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.