From 85b62bfa0154f30a9359831663f45e8f6bbe3fe6 Mon Sep 17 00:00:00 2001 From: Mark Wooding Date: Mon, 25 Nov 2019 13:07:34 +0000 Subject: [PATCH] rand.c: Implement the `passes' property of the `DSARand' generator. This has always been present in the C library, but wasn't surfaced in Python, which seems like a poor show. --- rand.c | 35 ++++++++++++++++++++++++++++++++--- t/t-rand.py | 8 ++++++-- 2 files changed, 38 insertions(+), 5 deletions(-) diff --git a/rand.c b/rand.c index ada2baa..e72f450 100644 --- a/rand.c +++ b/rand.c @@ -1120,12 +1120,18 @@ static const PyTypeObject tlsprf_pytype_skel = { static PyObject *dsarand_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw) { struct bin in; + unsigned passes = 1; + grand *r; PyObject *rc = 0; - static const char *const kwlist[] = { "seed", 0 }; + static const char *const kwlist[] = { "seed", "passes", 0 }; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&:new", KWLIST, convbin, &in)) + if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&|O&:new", KWLIST, + convbin, &in, convuint, &passes)) goto end; - rc = grand_dopywrap(ty, dsarand_create(in.p, in.sz), f_freeme); + if (!passes) VALERR("must be positive"); + r = dsarand_create(in.p, in.sz); + if (passes != 1) r->ops->misc(r, DSARAND_PASSES, passes); + rc = grand_dopywrap(ty, r, f_freeme); end: return (rc); } @@ -1139,9 +1145,32 @@ static PyObject *drget_seed(PyObject *me, void *hunoz) return (rc); } +static PyObject *drget_passes(PyObject *me, void *hunoz) +{ + grand *r = GRAND_R(me); + return (PyInt_FromLong(r->ops->misc(r, DSARAND_PASSES, 0))); +} + +static int drset_passes(PyObject *me, PyObject *val, void *hunoz) +{ + grand *r = GRAND_R(me); + long n; + int rc = -1; + + if (!val) NIERR("__del__"); + n = PyInt_AsLong(val); if (n == -1 && PyErr_Occurred()) goto end; + if (n <= 0) VALERR("must be positive"); + if (n > ULONG_MAX) VALERR("out of range"); + r->ops->misc(r, DSARAND_PASSES, (unsigned)n); + rc = 0; +end: + return (rc); +} + static const PyGetSetDef dsarand_pygetset[] = { #define GETSETNAME(op, name) dr##op##_##name GET (seed, "R.seed -> current generator seed") + GETSET(passes, "R.passes -> number of passes to create output") #undef GETSETNAME { 0 } }; diff --git a/t/t-rand.py b/t/t-rand.py index 0ad92dc..9acf693 100644 --- a/t/t-rand.py +++ b/t/t-rand.py @@ -122,9 +122,13 @@ class TestRandomGenerator (U.TestCase): def test_dsarand(me): seed = T.span(16) n = C.MP.loadb(seed) - rng = C.DSARand(seed) + rng = C.DSARand(seed, passes = 2) me.check_rand(rng) - me.assertEqual(rng.seed, (n + 153 + 3).storeb(16)) + me.assertEqual(rng.seed, (n + 2*153).storeb(16)) + me.assertEqual(rng.passes, 2); + rng.passes = 1 + me.check_rand(rng) + me.assertEqual(rng.seed, (n + 3*153 + 1).storeb(16)) def test_bbs(me): ev = T.EventRecorder() -- 2.11.0