11176bdada62cabc6ec4b0308a930e83b679d5d36John Reck/*
21176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * Copyright © 2012 Siarhei Siamashka <siarhei.siamashka@gmail.com>
31176bdada62cabc6ec4b0308a930e83b679d5d36John Reck *
41176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * Based on the public domain implementation of small noncryptographic PRNG
51176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * authored by Bob Jenkins: http://burtleburtle.net/bob/rand/smallprng.html
61176bdada62cabc6ec4b0308a930e83b679d5d36John Reck *
71176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * Permission is hereby granted, free of charge, to any person obtaining a
81176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * copy of this software and associated documentation files (the "Software"),
91176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * to deal in the Software without restriction, including without limitation
101176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * the rights to use, copy, modify, merge, publish, distribute, sublicense,
111176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * and/or sell copies of the Software, and to permit persons to whom the
121176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * Software is furnished to do so, subject to the following conditions:
131176bdada62cabc6ec4b0308a930e83b679d5d36John Reck *
141176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * The above copyright notice and this permission notice (including the next
151176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * paragraph) shall be included in all copies or substantial portions of the
161176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * Software.
171176bdada62cabc6ec4b0308a930e83b679d5d36John Reck *
181176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
191176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
201176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
211176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
221176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
231176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
241176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * DEALINGS IN THE SOFTWARE.
251176bdada62cabc6ec4b0308a930e83b679d5d36John Reck */
261176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
271176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#include "utils.h"
281176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#include "utils-prng.h"
291176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
301176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#if defined(GCC_VECTOR_EXTENSIONS_SUPPORTED) && defined(__SSE2__)
311176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#include <xmmintrin.h>
321176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#endif
331176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
341176bdada62cabc6ec4b0308a930e83b679d5d36John Reckvoid smallprng_srand_r (smallprng_t *x, uint32_t seed)
351176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{
361176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    uint32_t i;
371176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    x->a = 0xf1ea5eed, x->b = x->c = x->d = seed;
381176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    for (i = 0; i < 20; ++i)
391176bdada62cabc6ec4b0308a930e83b679d5d36John Reck        smallprng_rand_r (x);
401176bdada62cabc6ec4b0308a930e83b679d5d36John Reck}
411176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
421176bdada62cabc6ec4b0308a930e83b679d5d36John Reck/*
431176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * Set a 32-bit seed for PRNG
441176bdada62cabc6ec4b0308a930e83b679d5d36John Reck *
451176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * LCG is used here for generating independent seeds for different
461176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * smallprng instances (in the case if smallprng is also used for
471176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * generating these seeds, "Big Crush" test from TestU01 detects
481176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * some problems in the glued 'prng_rand_128_r' output data).
491176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * Actually we might be even better using some cryptographic
501176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * hash for this purpose, but LCG seems to be also enough for
511176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * passing "Big Crush".
521176bdada62cabc6ec4b0308a930e83b679d5d36John Reck */
531176bdada62cabc6ec4b0308a930e83b679d5d36John Reckvoid prng_srand_r (prng_t *x, uint32_t seed)
541176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{
551176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#ifdef GCC_VECTOR_EXTENSIONS_SUPPORTED
561176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int i;
571176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    prng_rand_128_data_t dummy;
581176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    smallprng_srand_r (&x->p0, seed);
591176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    x->a[0] = x->a[1] = x->a[2] = x->a[3] = 0xf1ea5eed;
601176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    x->b[0] = x->c[0] = x->d[0] = (seed = seed * 1103515245 + 12345);
611176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    x->b[1] = x->c[1] = x->d[1] = (seed = seed * 1103515245 + 12345);
621176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    x->b[2] = x->c[2] = x->d[2] = (seed = seed * 1103515245 + 12345);
631176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    x->b[3] = x->c[3] = x->d[3] = (seed = seed * 1103515245 + 12345);
641176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    for (i = 0; i < 20; ++i)
651176bdada62cabc6ec4b0308a930e83b679d5d36John Reck        prng_rand_128_r (x, &dummy);
661176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#else
671176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    smallprng_srand_r (&x->p0, seed);
681176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    smallprng_srand_r (&x->p1, (seed = seed * 1103515245 + 12345));
691176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    smallprng_srand_r (&x->p2, (seed = seed * 1103515245 + 12345));
701176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    smallprng_srand_r (&x->p3, (seed = seed * 1103515245 + 12345));
711176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    smallprng_srand_r (&x->p4, (seed = seed * 1103515245 + 12345));
721176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#endif
731176bdada62cabc6ec4b0308a930e83b679d5d36John Reck}
741176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
751176bdada62cabc6ec4b0308a930e83b679d5d36John Reckstatic force_inline void
761176bdada62cabc6ec4b0308a930e83b679d5d36John Reckstore_rand_128_data (void *addr, prng_rand_128_data_t *d, int aligned)
771176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{
781176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#ifdef GCC_VECTOR_EXTENSIONS_SUPPORTED
791176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    if (aligned)
801176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {
811176bdada62cabc6ec4b0308a930e83b679d5d36John Reck        *(uint8x16 *)addr = d->vb;
821176bdada62cabc6ec4b0308a930e83b679d5d36John Reck        return;
831176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }
841176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    else
851176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {
861176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#ifdef __SSE2__
871176bdada62cabc6ec4b0308a930e83b679d5d36John Reck        /* workaround for http://gcc.gnu.org/PR55614 */
881176bdada62cabc6ec4b0308a930e83b679d5d36John Reck        _mm_storeu_si128 (addr, _mm_loadu_si128 ((__m128i *)d));
891176bdada62cabc6ec4b0308a930e83b679d5d36John Reck        return;
901176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#endif
911176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }
921176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#endif
931176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    /* we could try something better for unaligned writes (packed attribute),
941176bdada62cabc6ec4b0308a930e83b679d5d36John Reck     * but GCC is not very reliable: http://gcc.gnu.org/PR55454 */
951176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    memcpy (addr, d, 16);
961176bdada62cabc6ec4b0308a930e83b679d5d36John Reck}
971176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
981176bdada62cabc6ec4b0308a930e83b679d5d36John Reck/*
991176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * Helper function and the actual code for "prng_randmemset_r" function
1001176bdada62cabc6ec4b0308a930e83b679d5d36John Reck */
1011176bdada62cabc6ec4b0308a930e83b679d5d36John Reckstatic force_inline void
1021176bdada62cabc6ec4b0308a930e83b679d5d36John Reckrandmemset_internal (prng_t                  *prng,
1031176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                     uint8_t                 *buf,
1041176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                     size_t                   size,
1051176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                     prng_randmemset_flags_t  flags,
1061176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                     int                      aligned)
1071176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{
1081176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    prng_t local_prng = *prng;
1091176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    prng_rand_128_data_t randdata;
1101176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    size_t i;
1111176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
1121176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    while (size >= 16)
1131176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {
1141176bdada62cabc6ec4b0308a930e83b679d5d36John Reck        prng_rand_128_data_t t;
1151176bdada62cabc6ec4b0308a930e83b679d5d36John Reck        if (flags == 0)
1161176bdada62cabc6ec4b0308a930e83b679d5d36John Reck        {
1171176bdada62cabc6ec4b0308a930e83b679d5d36John Reck            prng_rand_128_r (&local_prng, &randdata);
1181176bdada62cabc6ec4b0308a930e83b679d5d36John Reck        }
1191176bdada62cabc6ec4b0308a930e83b679d5d36John Reck        else
1201176bdada62cabc6ec4b0308a930e83b679d5d36John Reck        {
1211176bdada62cabc6ec4b0308a930e83b679d5d36John Reck            prng_rand_128_r (&local_prng, &t);
1221176bdada62cabc6ec4b0308a930e83b679d5d36John Reck            prng_rand_128_r (&local_prng, &randdata);
1231176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#ifdef GCC_VECTOR_EXTENSIONS_SUPPORTED
1241176bdada62cabc6ec4b0308a930e83b679d5d36John Reck            if (flags & RANDMEMSET_MORE_FF)
1251176bdada62cabc6ec4b0308a930e83b679d5d36John Reck            {
1261176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                const uint8x16 const_C0 =
1271176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                {
1281176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                    0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0,
1291176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                    0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0
1301176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                };
1311176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                randdata.vb |= (t.vb >= const_C0);
1321176bdada62cabc6ec4b0308a930e83b679d5d36John Reck            }
1331176bdada62cabc6ec4b0308a930e83b679d5d36John Reck            if (flags & RANDMEMSET_MORE_00)
1341176bdada62cabc6ec4b0308a930e83b679d5d36John Reck            {
1351176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                const uint8x16 const_40 =
1361176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                {
1371176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                    0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
1381176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                    0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40
1391176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                };
1401176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                randdata.vb &= (t.vb >= const_40);
1411176bdada62cabc6ec4b0308a930e83b679d5d36John Reck            }
1421176bdada62cabc6ec4b0308a930e83b679d5d36John Reck            if (flags & RANDMEMSET_MORE_FFFFFFFF)
1431176bdada62cabc6ec4b0308a930e83b679d5d36John Reck            {
1441176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                const uint32x4 const_C0000000 =
1451176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                {
1461176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                    0xC0000000, 0xC0000000, 0xC0000000, 0xC0000000
1471176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                };
1481176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                randdata.vw |= ((t.vw << 30) >= const_C0000000);
1491176bdada62cabc6ec4b0308a930e83b679d5d36John Reck            }
1501176bdada62cabc6ec4b0308a930e83b679d5d36John Reck            if (flags & RANDMEMSET_MORE_00000000)
1511176bdada62cabc6ec4b0308a930e83b679d5d36John Reck            {
1521176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                const uint32x4 const_40000000 =
1531176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                {
1541176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                    0x40000000, 0x40000000, 0x40000000, 0x40000000
1551176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                };
1561176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                randdata.vw &= ((t.vw << 30) >= const_40000000);
1571176bdada62cabc6ec4b0308a930e83b679d5d36John Reck            }
1581176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#else
1591176bdada62cabc6ec4b0308a930e83b679d5d36John Reck            #define PROCESS_ONE_LANE(i)                                       \
1601176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                if (flags & RANDMEMSET_MORE_FF)                               \
1611176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                {                                                             \
1621176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                    uint32_t mask_ff = (t.w[i] & (t.w[i] << 1)) & 0x80808080; \
1631176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                    mask_ff |= mask_ff >> 1;                                  \
1641176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                    mask_ff |= mask_ff >> 2;                                  \
1651176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                    mask_ff |= mask_ff >> 4;                                  \
1661176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                    randdata.w[i] |= mask_ff;                                 \
1671176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                }                                                             \
1681176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                if (flags & RANDMEMSET_MORE_00)                               \
1691176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                {                                                             \
1701176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                    uint32_t mask_00 = (t.w[i] | (t.w[i] << 1)) & 0x80808080; \
1711176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                    mask_00 |= mask_00 >> 1;                                  \
1721176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                    mask_00 |= mask_00 >> 2;                                  \
1731176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                    mask_00 |= mask_00 >> 4;                                  \
1741176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                    randdata.w[i] &= mask_00;                                 \
1751176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                }                                                             \
1761176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                if (flags & RANDMEMSET_MORE_FFFFFFFF)                         \
1771176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                {                                                             \
1781176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                    int32_t mask_ff = ((t.w[i] << 30) & (t.w[i] << 31)) &     \
1791176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                                       0x80000000;                            \
1801176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                    randdata.w[i] |= mask_ff >> 31;                           \
1811176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                }                                                             \
1821176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                if (flags & RANDMEMSET_MORE_00000000)                         \
1831176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                {                                                             \
1841176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                    int32_t mask_00 = ((t.w[i] << 30) | (t.w[i] << 31)) &     \
1851176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                                       0x80000000;                            \
1861176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                    randdata.w[i] &= mask_00 >> 31;                           \
1871176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                }
1881176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
1891176bdada62cabc6ec4b0308a930e83b679d5d36John Reck            PROCESS_ONE_LANE (0)
1901176bdada62cabc6ec4b0308a930e83b679d5d36John Reck            PROCESS_ONE_LANE (1)
1911176bdada62cabc6ec4b0308a930e83b679d5d36John Reck            PROCESS_ONE_LANE (2)
1921176bdada62cabc6ec4b0308a930e83b679d5d36John Reck            PROCESS_ONE_LANE (3)
1931176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#endif
1941176bdada62cabc6ec4b0308a930e83b679d5d36John Reck        }
1951176bdada62cabc6ec4b0308a930e83b679d5d36John Reck        if (is_little_endian ())
1961176bdada62cabc6ec4b0308a930e83b679d5d36John Reck        {
1971176bdada62cabc6ec4b0308a930e83b679d5d36John Reck            store_rand_128_data (buf, &randdata, aligned);
1981176bdada62cabc6ec4b0308a930e83b679d5d36John Reck            buf += 16;
1991176bdada62cabc6ec4b0308a930e83b679d5d36John Reck        }
2001176bdada62cabc6ec4b0308a930e83b679d5d36John Reck        else
2011176bdada62cabc6ec4b0308a930e83b679d5d36John Reck        {
2021176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#ifdef GCC_VECTOR_EXTENSIONS_SUPPORTED
2031176bdada62cabc6ec4b0308a930e83b679d5d36John Reck            const uint8x16 bswap_shufflemask =
2041176bdada62cabc6ec4b0308a930e83b679d5d36John Reck            {
2051176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12
2061176bdada62cabc6ec4b0308a930e83b679d5d36John Reck            };
2071176bdada62cabc6ec4b0308a930e83b679d5d36John Reck            randdata.vb = __builtin_shuffle (randdata.vb, bswap_shufflemask);
2081176bdada62cabc6ec4b0308a930e83b679d5d36John Reck            store_rand_128_data (buf, &randdata, aligned);
2091176bdada62cabc6ec4b0308a930e83b679d5d36John Reck            buf += 16;
2101176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#else
2111176bdada62cabc6ec4b0308a930e83b679d5d36John Reck            uint8_t t1, t2, t3, t4;
2121176bdada62cabc6ec4b0308a930e83b679d5d36John Reck            #define STORE_ONE_LANE(i)                                         \
2131176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                t1 = randdata.b[i * 4 + 3];                                   \
2141176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                t2 = randdata.b[i * 4 + 2];                                   \
2151176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                t3 = randdata.b[i * 4 + 1];                                   \
2161176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                t4 = randdata.b[i * 4 + 0];                                   \
2171176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                *buf++ = t1;                                                  \
2181176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                *buf++ = t2;                                                  \
2191176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                *buf++ = t3;                                                  \
2201176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                *buf++ = t4;
2211176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
2221176bdada62cabc6ec4b0308a930e83b679d5d36John Reck            STORE_ONE_LANE (0)
2231176bdada62cabc6ec4b0308a930e83b679d5d36John Reck            STORE_ONE_LANE (1)
2241176bdada62cabc6ec4b0308a930e83b679d5d36John Reck            STORE_ONE_LANE (2)
2251176bdada62cabc6ec4b0308a930e83b679d5d36John Reck            STORE_ONE_LANE (3)
2261176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#endif
2271176bdada62cabc6ec4b0308a930e83b679d5d36John Reck        }
2281176bdada62cabc6ec4b0308a930e83b679d5d36John Reck        size -= 16;
2291176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }
2301176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    i = 0;
2311176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    while (i < size)
2321176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {
2331176bdada62cabc6ec4b0308a930e83b679d5d36John Reck        uint8_t randbyte = prng_rand_r (&local_prng) & 0xFF;
2341176bdada62cabc6ec4b0308a930e83b679d5d36John Reck        if (flags != 0)
2351176bdada62cabc6ec4b0308a930e83b679d5d36John Reck        {
2361176bdada62cabc6ec4b0308a930e83b679d5d36John Reck            uint8_t t = prng_rand_r (&local_prng) & 0xFF;
2371176bdada62cabc6ec4b0308a930e83b679d5d36John Reck            if ((flags & RANDMEMSET_MORE_FF) && (t >= 0xC0))
2381176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                randbyte = 0xFF;
2391176bdada62cabc6ec4b0308a930e83b679d5d36John Reck            if ((flags & RANDMEMSET_MORE_00) && (t < 0x40))
2401176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                randbyte = 0x00;
2411176bdada62cabc6ec4b0308a930e83b679d5d36John Reck            if (i % 4 == 0 && i + 4 <= size)
2421176bdada62cabc6ec4b0308a930e83b679d5d36John Reck            {
2431176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                t = prng_rand_r (&local_prng) & 0xFF;
2441176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                if ((flags & RANDMEMSET_MORE_FFFFFFFF) && (t >= 0xC0))
2451176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                {
2461176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                    memset(&buf[i], 0xFF, 4);
2471176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                    i += 4;
2481176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                    continue;
2491176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                }
2501176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                if ((flags & RANDMEMSET_MORE_00000000) && (t < 0x40))
2511176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                {
2521176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                    memset(&buf[i], 0x00, 4);
2531176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                    i += 4;
2541176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                    continue;
2551176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                }
2561176bdada62cabc6ec4b0308a930e83b679d5d36John Reck            }
2571176bdada62cabc6ec4b0308a930e83b679d5d36John Reck        }
2581176bdada62cabc6ec4b0308a930e83b679d5d36John Reck        buf[i] = randbyte;
2591176bdada62cabc6ec4b0308a930e83b679d5d36John Reck        i++;
2601176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }
2611176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    *prng = local_prng;
2621176bdada62cabc6ec4b0308a930e83b679d5d36John Reck}
2631176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
2641176bdada62cabc6ec4b0308a930e83b679d5d36John Reck/*
2651176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * Fill memory buffer with random data. Flags argument may be used
2661176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * to tweak some statistics properties:
2671176bdada62cabc6ec4b0308a930e83b679d5d36John Reck *    RANDMEMSET_MORE_00        - set ~25% of bytes to 0x00
2681176bdada62cabc6ec4b0308a930e83b679d5d36John Reck *    RANDMEMSET_MORE_FF        - set ~25% of bytes to 0xFF
2691176bdada62cabc6ec4b0308a930e83b679d5d36John Reck *    RANDMEMSET_MORE_00000000  - ~25% chance for 00000000 4-byte clusters
2701176bdada62cabc6ec4b0308a930e83b679d5d36John Reck *    RANDMEMSET_MORE_FFFFFFFF  - ~25% chance for FFFFFFFF 4-byte clusters
2711176bdada62cabc6ec4b0308a930e83b679d5d36John Reck */
2721176bdada62cabc6ec4b0308a930e83b679d5d36John Reckvoid prng_randmemset_r (prng_t                  *prng,
2731176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                        void                    *voidbuf,
2741176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                        size_t                   size,
2751176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                        prng_randmemset_flags_t  flags)
2761176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{
2771176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    uint8_t *buf = (uint8_t *)voidbuf;
2781176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    if ((uintptr_t)buf & 15)
2791176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {
2801176bdada62cabc6ec4b0308a930e83b679d5d36John Reck        /* unaligned buffer */
2811176bdada62cabc6ec4b0308a930e83b679d5d36John Reck        if (flags == 0)
2821176bdada62cabc6ec4b0308a930e83b679d5d36John Reck            randmemset_internal (prng, buf, size, 0, 0);
2831176bdada62cabc6ec4b0308a930e83b679d5d36John Reck        else if (flags == RANDMEMSET_MORE_00_AND_FF)
2841176bdada62cabc6ec4b0308a930e83b679d5d36John Reck            randmemset_internal (prng, buf, size, RANDMEMSET_MORE_00_AND_FF, 0);
2851176bdada62cabc6ec4b0308a930e83b679d5d36John Reck        else
2861176bdada62cabc6ec4b0308a930e83b679d5d36John Reck            randmemset_internal (prng, buf, size, flags, 0);
2871176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }
2881176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    else
2891176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {
2901176bdada62cabc6ec4b0308a930e83b679d5d36John Reck        /* aligned buffer */
2911176bdada62cabc6ec4b0308a930e83b679d5d36John Reck        if (flags == 0)
2921176bdada62cabc6ec4b0308a930e83b679d5d36John Reck            randmemset_internal (prng, buf, size, 0, 1);
2931176bdada62cabc6ec4b0308a930e83b679d5d36John Reck        else if (flags == RANDMEMSET_MORE_00_AND_FF)
2941176bdada62cabc6ec4b0308a930e83b679d5d36John Reck            randmemset_internal (prng, buf, size, RANDMEMSET_MORE_00_AND_FF, 1);
2951176bdada62cabc6ec4b0308a930e83b679d5d36John Reck        else
2961176bdada62cabc6ec4b0308a930e83b679d5d36John Reck            randmemset_internal (prng, buf, size, flags, 1);
2971176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }
2981176bdada62cabc6ec4b0308a930e83b679d5d36John Reck}
299