gmpy2_random.c
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 2 * gmpy_random.c * 3 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 4 * Python interface to the GMP or MPIR, MPFR, and MPC multiple precision * 5 * libraries. * 6 * * 7 * Copyright 2000 - 2009 Alex Martelli * 8 * * 9 * Copyright 2008 - 2021 Case Van Horsen * 10 * * 11 * This file is part of GMPY2. * 12 * * 13 * GMPY2 is free software: you can redistribute it and/or modify it under * 14 * the terms of the GNU Lesser General Public License as published by the * 15 * Free Software Foundation, either version 3 of the License, or (at your * 16 * option) any later version. * 17 * * 18 * GMPY2 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 Lesser General Public * 21 * License for more details. * 22 * * 23 * You should have received a copy of the GNU Lesser General Public * 24 * License along with GMPY2; if not, see <http://www.gnu.org/licenses/> * 25 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 26 27 static RandomState_Object * 28 GMPy_RandomState_New(void) 29 { 30 RandomState_Object *result; 31 32 if ((result = PyObject_New(RandomState_Object, &RandomState_Type))) { 33 gmp_randinit_default(result->state); 34 } 35 return result; 36 }; 37 38 static void 39 GMPy_RandomState_Dealloc(RandomState_Object *self) 40 { 41 gmp_randclear(self->state); 42 PyObject_Del(self); 43 }; 44 45 static PyObject * 46 GMPy_RandomState_Repr(RandomState_Object *self) 47 { 48 return Py_BuildValue("s", "<gmpy2.RandomState>"); 49 }; 50 51 PyDoc_STRVAR(GMPy_doc_random_state_factory, 52 "random_state([seed]) -> object\n\n" 53 "Return new object containing state information for the random number\n" 54 "generator. An optional integer can be specified as the seed value."); 55 56 static PyObject * 57 GMPy_RandomState_Factory(PyObject *self, PyObject *args) 58 { 59 RandomState_Object *result; 60 MPZ_Object *temp; 61 62 if (!(result = GMPy_RandomState_New())) { 63 return NULL; 64 } 65 66 if (PyTuple_GET_SIZE(args) == 0) { 67 gmp_randseed_ui(result->state, 0); 68 } 69 else if (PyTuple_GET_SIZE(args) == 1) { 70 if (!(temp = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args,0), NULL))) { 71 Py_DECREF((PyObject*)result); 72 TYPE_ERROR("seed must be an integer"); 73 return NULL; 74 } 75 gmp_randseed(result->state, temp->z); 76 Py_DECREF((PyObject*)temp); 77 } 78 else { 79 Py_DECREF((PyObject*)result); 80 TYPE_ERROR("random_state() requires 0 or 1 integer arguments"); 81 return NULL; 82 } 83 return (PyObject*)result; 84 } 85 86 PyDoc_STRVAR(GMPy_doc_mpz_urandomb_function, 87 "mpz_urandomb(random_state, bit_count) -> mpz\n\n" 88 "Return uniformly distributed random integer between 0 and\n" 89 "2**bit_count-1."); 90 91 static PyObject * 92 GMPy_MPZ_urandomb_Function(PyObject *self, PyObject *args) 93 { 94 MPZ_Object *result; 95 mp_bitcnt_t len; 96 97 if (PyTuple_GET_SIZE(args) != 2) { 98 TYPE_ERROR("mpz_urandomb() requires 2 arguments"); 99 return NULL; 100 } 101 102 if (!RandomState_Check(PyTuple_GET_ITEM(args, 0))) { 103 TYPE_ERROR("mpz_urandomb() requires 'random_state' and 'bit_count' arguments"); 104 return NULL; 105 } 106 107 len = mp_bitcnt_t_From_Integer(PyTuple_GET_ITEM(args, 1)); 108 if (len == (mp_bitcnt_t)(-1) && PyErr_Occurred()) { 109 TYPE_ERROR("mpz_urandomb() requires 'random_state' and 'bit_count' arguments"); 110 return NULL; 111 } 112 113 if ((result = GMPy_MPZ_New(NULL))) { 114 mpz_urandomb(result->z, RANDOM_STATE(PyTuple_GET_ITEM(args, 0)), len); 115 } 116 117 return (PyObject*)result; 118 } 119 120 PyDoc_STRVAR(GMPy_doc_mpz_rrandomb_function, 121 "mpz_rrandomb(random_state, bit_count) -> mpz\n\n" 122 "Return a random integer between 0 and 2**bit_count-1 with long\n" 123 "sequences of zeros and one in its binary representation."); 124 125 static PyObject * 126 GMPy_MPZ_rrandomb_Function(PyObject *self, PyObject *args) 127 { 128 MPZ_Object *result; 129 mp_bitcnt_t len; 130 131 if (PyTuple_GET_SIZE(args) != 2) { 132 TYPE_ERROR("mpz_rrandomb() requires 2 arguments"); 133 return NULL; 134 } 135 136 if (!RandomState_Check(PyTuple_GET_ITEM(args, 0))) { 137 TYPE_ERROR("mpz_rrandomb() requires 'random_state' and 'bit_count' arguments"); 138 return NULL; 139 } 140 141 len = mp_bitcnt_t_From_Integer(PyTuple_GET_ITEM(args, 1)); 142 if (len == (mp_bitcnt_t)(-1) && PyErr_Occurred()) { 143 TYPE_ERROR("mpz_rrandomb() requires 'random_state' and 'bit_count' arguments"); 144 return NULL; 145 } 146 147 if ((result = GMPy_MPZ_New(NULL))) { 148 mpz_rrandomb(result->z, RANDOM_STATE(PyTuple_GET_ITEM(args, 0)), len); 149 } 150 151 return (PyObject*)result; 152 } 153 154 PyDoc_STRVAR(GMPy_doc_mpz_random_function, 155 "mpz_random(random_state, int) -> mpz\n\n" 156 "Return uniformly distributed random integer between 0 and n-1."); 157 158 static PyObject * 159 GMPy_MPZ_random_Function(PyObject *self, PyObject *args) 160 { 161 MPZ_Object *result, *temp; 162 163 if (PyTuple_GET_SIZE(args) != 2) { 164 TYPE_ERROR("mpz_random() requires 2 arguments"); 165 return NULL; 166 } 167 168 if (!RandomState_Check(PyTuple_GET_ITEM(args, 0))) { 169 TYPE_ERROR("mpz_random() requires 'random_state' and 'int' arguments"); 170 return NULL; 171 } 172 173 if (!(temp = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 1), NULL))) { 174 TYPE_ERROR("mpz_random() requires 'random_state' and 'int' arguments"); 175 return NULL; 176 } 177 178 if ((result = GMPy_MPZ_New(NULL))) { 179 mpz_urandomm(result->z, RANDOM_STATE(PyTuple_GET_ITEM(args, 0)), temp->z); 180 } 181 182 Py_DECREF((PyObject*)temp); 183 return (PyObject*)result; 184 } 185 186 PyDoc_STRVAR(GMPy_doc_mpfr_random_function, 187 "mpfr_random(random_state) -> mpfr\n\n" 188 "Return uniformly distributed number between [0,1]."); 189 190 static PyObject * 191 GMPy_MPFR_random_Function(PyObject *self, PyObject *args) 192 { 193 MPFR_Object *result; 194 CTXT_Object *context = NULL; 195 196 CHECK_CONTEXT(context); 197 198 if (PyTuple_GET_SIZE(args) != 1) { 199 TYPE_ERROR("mpfr_random() requires 1 argument"); 200 return NULL; 201 } 202 203 if (!RandomState_Check(PyTuple_GET_ITEM(args, 0))) { 204 TYPE_ERROR("mpfr_random() requires 'random_state' argument"); 205 return NULL; 206 } 207 208 if ((result = GMPy_MPFR_New(0, context))) { 209 mpfr_urandom(result->f, RANDOM_STATE(PyTuple_GET_ITEM(args, 0)), GET_MPFR_ROUND(context)); 210 } 211 212 return (PyObject*)result; 213 } 214 215 #if MPFR_VERSION_MAJOR > 3 216 217 PyDoc_STRVAR(GMPy_doc_mpfr_nrandom_function, 218 "mpfr_nrandom(random_state) -> (mpfr)\n\n" 219 "Return a random number with gaussian distribution."); 220 221 static PyObject * 222 GMPy_MPFR_nrandom_Function(PyObject *self, PyObject *args) 223 { 224 MPFR_Object *result; 225 CTXT_Object *context = NULL; 226 227 CHECK_CONTEXT(context); 228 229 if (PyTuple_GET_SIZE(args) != 1) { 230 TYPE_ERROR("mpfr_nrandom() requires 1 argument"); 231 return NULL; 232 } 233 234 if (!RandomState_Check(PyTuple_GET_ITEM(args, 0))) { 235 TYPE_ERROR("mpfr_nrandom() requires 'random_state' argument"); 236 return NULL; 237 } 238 239 if ((result = GMPy_MPFR_New(0, context))) { 240 mpfr_nrandom(result->f, 241 RANDOM_STATE(PyTuple_GET_ITEM(args, 0)), 242 GET_MPFR_ROUND(context)); 243 } 244 return (PyObject*)result; 245 } 246 247 PyDoc_STRVAR(GMPy_doc_mpfr_grandom_function, 248 "mpfr_grandom(random_state) -> (mpfr, mpfr)\n\n" 249 "Return two random numbers with gaussian distribution."); 250 251 static PyObject * 252 GMPy_MPFR_grandom_Function(PyObject *self, PyObject *args) 253 { 254 MPFR_Object *result1, *result2; 255 PyObject *result; 256 CTXT_Object *context = NULL; 257 258 CHECK_CONTEXT(context); 259 260 if (PyTuple_GET_SIZE(args) != 1) { 261 TYPE_ERROR("mpfr_grandom() requires 1 argument"); 262 return NULL; 263 } 264 265 if (!RandomState_Check(PyTuple_GET_ITEM(args, 0))) { 266 TYPE_ERROR("mpfr_grandom() requires 'random_state' argument"); 267 return NULL; 268 } 269 270 result1 = GMPy_MPFR_New(0, context); 271 result2 = GMPy_MPFR_New(0, context); 272 if (!result1 || !result2) { 273 Py_XDECREF((PyObject*)result1); 274 Py_XDECREF((PyObject*)result2); 275 return NULL; 276 } 277 278 mpfr_nrandom(result1->f, 279 RANDOM_STATE(PyTuple_GET_ITEM(args, 0)), 280 GET_MPFR_ROUND(context)); 281 282 mpfr_nrandom(result2->f, 283 RANDOM_STATE(PyTuple_GET_ITEM(args, 0)), 284 GET_MPFR_ROUND(context)); 285 286 result = Py_BuildValue("(NN)", (PyObject*)result1, (PyObject*)result2); 287 if (!result) { 288 Py_DECREF((PyObject*)result1); 289 Py_DECREF((PyObject*)result2); 290 } 291 return result; 292 } 293 #else 294 PyDoc_STRVAR(GMPy_doc_mpfr_grandom_function, 295 "mpfr_grandom(random_state) -> (mpfr, mpfr)\n\n" 296 "Return two random numbers with gaussian distribution."); 297 298 static PyObject * 299 GMPy_MPFR_grandom_Function(PyObject *self, PyObject *args) 300 { 301 MPFR_Object *result1, *result2; 302 PyObject *result; 303 CTXT_Object *context = NULL; 304 305 CHECK_CONTEXT(context); 306 307 if (PyTuple_GET_SIZE(args) != 1) { 308 TYPE_ERROR("mpfr_grandom() requires 1 argument"); 309 return NULL; 310 } 311 312 if (!RandomState_Check(PyTuple_GET_ITEM(args, 0))) { 313 TYPE_ERROR("mpfr_grandom() requires 'random_state' argument"); 314 return NULL; 315 } 316 317 result1 = GMPy_MPFR_New(0, context); 318 result2 = GMPy_MPFR_New(0, context); 319 if (!result1 || !result2) { 320 Py_XDECREF((PyObject*)result1); 321 Py_XDECREF((PyObject*)result2); 322 return NULL; 323 } 324 325 mpfr_grandom(result1->f, result2->f, 326 RANDOM_STATE(PyTuple_GET_ITEM(args, 0)), 327 GET_MPFR_ROUND(context)); 328 329 result = Py_BuildValue("(NN)", (PyObject*)result1, (PyObject*)result2); 330 if (!result) { 331 Py_DECREF((PyObject*)result1); 332 Py_DECREF((PyObject*)result2); 333 } 334 return result; 335 } 336 #endif 337 338 339 PyDoc_STRVAR(GMPy_doc_mpc_random_function, 340 "mpc_random(random_state) -> mpc\n\n" 341 "Return uniformly distributed number in the unit square [0,1]x[0,1]."); 342 343 static PyObject * 344 GMPy_MPC_random_Function(PyObject *self, PyObject *args) 345 { 346 MPC_Object *result; 347 CTXT_Object *context = NULL; 348 349 CHECK_CONTEXT(context); 350 351 if (PyTuple_GET_SIZE(args) != 1) { 352 TYPE_ERROR("mpfc_random() requires 1 argument"); 353 return NULL; 354 } 355 356 if (!RandomState_Check(PyTuple_GET_ITEM(args, 0))) { 357 TYPE_ERROR("mpc_random() requires 'random_state' argument"); 358 return NULL; 359 } 360 361 if ((result = GMPy_MPC_New(0, 0, context))) { 362 mpc_urandom(result->c, RANDOM_STATE(PyTuple_GET_ITEM(args, 0))); 363 } 364 365 return (PyObject*)result; 366 } 367 368 static PyTypeObject RandomState_Type = 369 { 370 #ifdef PY3 371 PyVarObject_HEAD_INIT(0, 0) 372 #else 373 PyObject_HEAD_INIT(0) 374 0, /* ob_size */ 375 #endif 376 "gmpy2 random state", /* tp_name */ 377 sizeof(RandomState_Object), /* tp_basicsize */ 378 0, /* tp_itemsize */ 379 (destructor) GMPy_RandomState_Dealloc, /* tp_dealloc */ 380 0, /* tp_print */ 381 0, /* tp_getattr */ 382 0, /* tp_setattr */ 383 0, /* tp_reserved */ 384 (reprfunc) GMPy_RandomState_Repr, /* tp_repr */ 385 0, /* tp_as_number */ 386 0, /* tp_as_sequence */ 387 0, /* tp_as_mapping */ 388 0, /* tp_hash */ 389 0, /* tp_call */ 390 0, /* tp_str */ 391 0, /* tp_getattro */ 392 0, /* tp_setattro */ 393 0, /* tp_as_buffer */ 394 Py_TPFLAGS_DEFAULT, /* tp_flags */ 395 "GMPY2 Random number generator state", /* tp_doc */ 396 0, /* tp_traverse */ 397 0, /* tp_clear */ 398 0, /* tp_richcompare */ 399 0, /* tp_weaklistoffset*/ 400 0, /* tp_iter */ 401 0, /* tp_iternext */ 402 0, /* tp_methods */ 403 0, /* tp_members */ 404 0, /* tp_getset */ 405 };