@@ -53,6 +53,24 @@ STATIC uint32_t yasmarang(void)
53
53
54
54
// End of Yasmarang
55
55
56
+ #if MICROPY_PY_URANDOM_EXTRA_FUNCS
57
+
58
+ // returns an unsigned integer below the given argument
59
+ // n must not be zero
60
+ STATIC uint32_t yasmarang_randbelow (uint32_t n ) {
61
+ uint32_t mask = 1 ;
62
+ while ((n & mask ) < n ) {
63
+ mask = (mask << 1 ) | 1 ;
64
+ }
65
+ uint32_t r ;
66
+ do {
67
+ r = yasmarang () & mask ;
68
+ } while (r >= n );
69
+ return r ;
70
+ }
71
+
72
+ #endif
73
+
56
74
STATIC mp_obj_t mod_urandom_getrandbits (mp_obj_t num_in ) {
57
75
int n = mp_obj_get_int (num_in );
58
76
if (n > 32 || n == 0 ) {
@@ -75,10 +93,122 @@ STATIC mp_obj_t mod_urandom_seed(mp_obj_t seed_in) {
75
93
}
76
94
STATIC MP_DEFINE_CONST_FUN_OBJ_1 (mod_urandom_seed_obj , mod_urandom_seed );
77
95
96
+ #if MICROPY_PY_URANDOM_EXTRA_FUNCS
97
+
98
+ STATIC mp_obj_t mod_urandom_randrange (size_t n_args , const mp_obj_t * args ) {
99
+ mp_int_t start = mp_obj_get_int (args [0 ]);
100
+ if (n_args == 1 ) {
101
+ // range(stop)
102
+ if (start > 0 ) {
103
+ return mp_obj_new_int (yasmarang_randbelow (start ));
104
+ } else {
105
+ nlr_raise (mp_obj_new_exception (& mp_type_ValueError ));
106
+ }
107
+ } else {
108
+ mp_int_t stop = mp_obj_get_int (args [1 ]);
109
+ if (n_args == 2 ) {
110
+ // range(start, stop)
111
+ if (start < stop ) {
112
+ return mp_obj_new_int (start + yasmarang_randbelow (stop - start ));
113
+ } else {
114
+ nlr_raise (mp_obj_new_exception (& mp_type_ValueError ));
115
+ }
116
+ } else {
117
+ // range(start, stop, step)
118
+ mp_int_t step = mp_obj_get_int (args [2 ]);
119
+ mp_int_t n ;
120
+ if (step > 0 ) {
121
+ n = (stop - start + step - 1 ) / step ;
122
+ } else if (step < 0 ) {
123
+ n = (stop - start + step + 1 ) / step ;
124
+ } else {
125
+ nlr_raise (mp_obj_new_exception (& mp_type_ValueError ));
126
+ }
127
+ if (n > 0 ) {
128
+ return mp_obj_new_int (start + step * yasmarang_randbelow (n ));
129
+ } else {
130
+ nlr_raise (mp_obj_new_exception (& mp_type_ValueError ));
131
+ }
132
+ }
133
+ }
134
+ }
135
+ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN (mod_urandom_randrange_obj , 1 , 3 , mod_urandom_randrange );
136
+
137
+ STATIC mp_obj_t mod_urandom_randint (mp_obj_t a_in , mp_obj_t b_in ) {
138
+ mp_int_t a = mp_obj_get_int (a_in );
139
+ mp_int_t b = mp_obj_get_int (b_in );
140
+ if (a <= b ) {
141
+ return mp_obj_new_int (a + yasmarang_randbelow (b - a + 1 ));
142
+ } else {
143
+ nlr_raise (mp_obj_new_exception (& mp_type_ValueError ));
144
+ }
145
+ }
146
+ STATIC MP_DEFINE_CONST_FUN_OBJ_2 (mod_urandom_randint_obj , mod_urandom_randint );
147
+
148
+ STATIC mp_obj_t mod_urandom_choice (mp_obj_t seq ) {
149
+ mp_int_t len = mp_obj_get_int (mp_obj_len (seq ));
150
+ if (len > 0 ) {
151
+ return mp_obj_subscr (seq , mp_obj_new_int (yasmarang_randbelow (len )), MP_OBJ_SENTINEL );
152
+ } else {
153
+ nlr_raise (mp_obj_new_exception (& mp_type_IndexError ));
154
+ }
155
+ }
156
+ STATIC MP_DEFINE_CONST_FUN_OBJ_1 (mod_urandom_choice_obj , mod_urandom_choice );
157
+
158
+ #if MICROPY_PY_BUILTINS_FLOAT
159
+
160
+ // returns a number in the range [0..1) using Yasmarang to fill in the fraction bits
161
+ STATIC mp_float_t yasmarang_float (void ) {
162
+ #if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE
163
+ typedef uint64_t mp_float_int_t ;
164
+ #elif MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT
165
+ typedef uint32_t mp_float_int_t ;
166
+ #endif
167
+ union {
168
+ mp_float_t f ;
169
+ #if MP_ENDIANNESS_LITTLE
170
+ struct { mp_float_int_t frc :MP_FLOAT_FRAC_BITS , exp :MP_FLOAT_EXP_BITS , sgn :1 ; } p ;
171
+ #else
172
+ struct { mp_float_int_t sgn :1 , exp :MP_FLOAT_EXP_BITS , frc :MP_FLOAT_FRAC_BITS ; } p ;
173
+ #endif
174
+ } u ;
175
+ u .p .sgn = 0 ;
176
+ u .p .exp = (1 << (MP_FLOAT_EXP_BITS - 1 )) - 1 ;
177
+ if (MP_FLOAT_FRAC_BITS <= 32 ) {
178
+ u .p .frc = yasmarang ();
179
+ } else {
180
+ u .p .frc = ((uint64_t )yasmarang () << 32 ) | (uint64_t )yasmarang ();
181
+ }
182
+ return u .f - 1 ;
183
+ }
184
+
185
+ STATIC mp_obj_t mod_urandom_random (void ) {
186
+ return mp_obj_new_float (yasmarang_float ());
187
+ }
188
+ STATIC MP_DEFINE_CONST_FUN_OBJ_0 (mod_urandom_random_obj , mod_urandom_random );
189
+
190
+ STATIC mp_obj_t mod_urandom_uniform (mp_obj_t a_in , mp_obj_t b_in ) {
191
+ mp_float_t a = mp_obj_get_float (a_in );
192
+ mp_float_t b = mp_obj_get_float (b_in );
193
+ return mp_obj_new_float (a + (b - a ) * yasmarang_float ());
194
+ }
195
+ STATIC MP_DEFINE_CONST_FUN_OBJ_2 (mod_urandom_uniform_obj , mod_urandom_uniform );
196
+
197
+ #endif
198
+
199
+ #endif // MICROPY_PY_URANDOM_EXTRA_FUNCS
200
+
78
201
STATIC const mp_rom_map_elem_t mp_module_urandom_globals_table [] = {
79
202
{ MP_ROM_QSTR (MP_QSTR___name__ ), MP_ROM_QSTR (MP_QSTR_urandom ) },
80
203
{ MP_ROM_QSTR (MP_QSTR_getrandbits ), MP_ROM_PTR (& mod_urandom_getrandbits_obj ) },
81
204
{ MP_ROM_QSTR (MP_QSTR_seed ), MP_ROM_PTR (& mod_urandom_seed_obj ) },
205
+ #if MICROPY_PY_URANDOM_EXTRA_FUNCS
206
+ { MP_ROM_QSTR (MP_QSTR_randrange ), MP_ROM_PTR (& mod_urandom_randrange_obj ) },
207
+ { MP_ROM_QSTR (MP_QSTR_randint ), MP_ROM_PTR (& mod_urandom_randint_obj ) },
208
+ { MP_ROM_QSTR (MP_QSTR_choice ), MP_ROM_PTR (& mod_urandom_choice_obj ) },
209
+ { MP_ROM_QSTR (MP_QSTR_random ), MP_ROM_PTR (& mod_urandom_random_obj ) },
210
+ { MP_ROM_QSTR (MP_QSTR_uniform ), MP_ROM_PTR (& mod_urandom_uniform_obj ) },
211
+ #endif
82
212
};
83
213
84
214
STATIC MP_DEFINE_CONST_DICT (mp_module_urandom_globals , mp_module_urandom_globals_table );
0 commit comments