Project Ne10
An Open Optimized Software Library Project for the ARM Architecture
Loading...
Searching...
No Matches
NE10_random.c
1/*
2 * Copyright 2012-15 ARM Limited and Contributors.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of ARM Limited nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY ARM LIMITED AND CONTRIBUTORS "AS IS" AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL ARM LIMITED AND CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28/*
29 * NE10 Library : test/src/NE10_random.c
30 */
31
32#include "NE10_random.h"
33
34// Please look at http://en.wikipedia.org/wiki/Linear_congruential_generator
35// According to this page, these values are the ones used in "glibc"
36
37//uint32_t _M = 4294967296L; // 2^32 // modulus, must be 0 < _M
38const uint32_t _A = 1103515245L; // a, must be 0 < _A < _M
39const uint32_t _C = 12345L; // c, must be 0 < _C < _M
40// uint32_t m_X_NM1 = 0; // X(n-1), at first this value is the seed or the start value
41
42// generic functions
43void NE10_rng_init_g (NE10_rng_t *rng, uint32_t seed)
44{
45 assert (rng != NULL);
46 rng->_private_m_A = _A;
47 rng->_private_m_C = _C;
48 rng->_private_m_X_NM1 = seed;
49}
50
51uint32_t NE10_rng_next_g (NE10_rng_t *rng)
52{
53 assert (rng != NULL);
54 // Linear Congruential Generator
55 rng->_private_m_X_NM1 = (rng->_private_m_A * rng->_private_m_X_NM1 + rng->_private_m_C); // % _M; // excluded by the nature of using a 32-bit data type
56 return rng->_private_m_X_NM1;
57}
58
59const uint32_t NE10_rng_max_g (NE10_rng_t *rng)
60{
61 return 0xffffffff; // this is 2^32 - 1
62}
63
64
65
66// the same functions using a rng which is shared across the library
67static NE10_rng_t __NE10_rng; // used as the global random number generator shared across the library
68
69void NE10_rng_init (uint32_t seed)
70{
71 NE10_rng_init_g (&__NE10_rng, seed);
72}
73
74uint32_t NE10_rng_next()
75{
76 return NE10_rng_next_g (&__NE10_rng);
77}
78
79const uint32_t NE10_rng_max()
80{
81 return NE10_rng_max_g (NULL);
82}
83
84void NE10_float_rng_init_g (NE10_float_rng_t* float_rng, uint32_t seed)
85{
86 // we can use [0] for the fraction, [1] for the exponent, and [2] for the sign bit
87
88 NE10_rng_t seed_generator;
89 NE10_rng_init_g (&seed_generator, seed);
90
91 NE10_rng_init_g (&float_rng->_private_m_rngs[0], NE10_rng_next_g (&seed_generator));
92 NE10_rng_init_g (&float_rng->_private_m_rngs[1], NE10_rng_next_g (&seed_generator));
93 NE10_rng_init_g (&float_rng->_private_m_rngs[2], NE10_rng_next_g (&seed_generator));
94}
95
96float NE10_float_rng_next_g (NE10_float_rng_t* float_rng)
97{
98 uint32_t frc, exp, sgn, ret;
99
100 do
101 {
102 // generate three random numbers
103 frc = NE10_rng_next_g (&float_rng->_private_m_rngs[0]);
104 exp = NE10_rng_next_g (&float_rng->_private_m_rngs[1]);
105 sgn = NE10_rng_next_g (&float_rng->_private_m_rngs[2]);
106
107 // take the top bits ( the sign uses the 17th bit)
108 frc = (frc >> 9) & 0x7FFFFF ; // (1)b^23
109 exp = ( (exp >> 24) & 0x0000FF) << 23; // (1)b^ 8
110 sgn = ( (sgn >> 16) & 0x000001) << 31;
111
112 // generate the final float value
113 ret = frc | exp | sgn;
114
115 }
116 while (IS_NAN_OR_INF (ret) || IS_SUBNORMAL (ret));
117
118 //memcpy( &__ret, &ret, 1*sizeof(float) );
119 return * ( (float*) &ret);
120}
121
122float NE10_float_rng_max_g (NE10_float_rng_t* float_rng)
123{
124 return FLT_MAX;
125}
126
127
128// the same functions using a float_rng which is shared across the library
129
130static NE10_float_rng_t __NE10_float_rng; // local array for internal use only
131
132void NE10_float_rng_init (uint32_t seed)
133{
134 NE10_float_rng_init_g (&__NE10_float_rng , seed);
135}
136
137float NE10_float_rng_next()
138{
139 return NE10_float_rng_next_g (&__NE10_float_rng);
140}
141
142float NE10_float_rng_max()
143{
144 return NE10_float_rng_max_g (NULL);
145}
146
147// the same as above functions except the range of values are limited
148
149#define IS_TOO_SMALL(f) ((fabs(f)<1.0e-3)?1:0)
150#define IS_TOO_BIG(f) ((fabs(f)>1.0e3)?1:0)
151
152static NE10_float_rng_t __NE10_float_rng_limit; // local array for internal use only
153
154void NE10_float_rng_limit_init (uint32_t seed)
155{
156 NE10_float_rng_init_g (&__NE10_float_rng_limit , seed);
157}
158
159float NE10_float_rng_limit_next()
160{
161 float ret = 0.0f;
162
163 do
164 {
165 ret = NE10_float_rng_next_g (&__NE10_float_rng_limit);
166 }
167 while (IS_TOO_SMALL (ret) || IS_TOO_BIG (ret));
168
169 return ret;
170}
171
172float NE10_float_rng_limit_max()
173{
174 return NE10_float_rng_max_g (NULL);
175}
176
177// the same as above functions except the range of values are limited and all the values are greater than 1.0e-6
178
179#define IS_TOO_SMALL_GT1(f) ((fabs(f)<1.0e-6)?1:0)
180#define IS_TOO_BIG_GT1(f) ((fabs(f)>1.0e+3)?1:0)
181
182void NE10_float_rng_limit_gt1_init (uint32_t seed)
183{
184 NE10_float_rng_init_g (&__NE10_float_rng_limit , seed);
185}
186
187float NE10_float_rng_limit_gt1_next()
188{
189 float ret = 0.0f;
190
191 do
192 {
193 ret = NE10_float_rng_next_g (&__NE10_float_rng_limit);
194 }
195 while (IS_TOO_SMALL_GT1 (ret) || IS_TOO_BIG_GT1 (ret));
196
197 return ret;
198}
199
200float NE10_float_rng_limit_gt1_max()
201{
202 return NE10_float_rng_max_g (NULL);
203}