blob: a7cc9201b8f110caa1d3eae4fffad74b49644a99 [file] [log] [blame]
/*
* Copyright (c) 2022 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* PCG Random Number Generation for C.
*
* Copyright 2014-2019 Melissa O'Neill <oneill@pcg-random.org>,
* and the PCG Project contributors.
*
* SPDX-License-Identifier: (Apache-2.0 OR MIT)
*
* Licensed under the Apache License, Version 2.0 (provided in
* LICENSE-APACHE.txt and at http://www.apache.org/licenses/LICENSE-2.0)
* or under the MIT license (provided in LICENSE-MIT.txt and at
* http://opensource.org/licenses/MIT), at your option. This file may not
* be copied, modified, or distributed except according to those terms.
*
* Distributed on an "AS IS" BASIS, WITHOUT WARRANTY OF ANY KIND, either
* express or implied. See your chosen license for details.
*
* For additional information about the PCG random number generation scheme,
* visit http://www.pcg-random.org/.
*/
/* This implements the pcg64i_random_t PCG specialized generator:
* https://www.pcg-random.org/using-pcg-c.html#specialized-generators
* This generator produces each 64-bits output exactly once, which is
* perfectly suited to generated non-repeating IVs. However, because of this
* property the entire internal state is revealed with each output.
* It has a 2^64 period and supports 2^63 non-overlaping streams */
#define clib_pcg64i_random_r clib_pcg_setseq_64_rxs_m_xs_64_random_r
#define clib_pcg64i_srandom_r clib_pcg_setseq_64_srandom_r
typedef struct
{
u64 state;
u64 inc;
} clib_pcg_state_setseq_64_t;
typedef clib_pcg_state_setseq_64_t clib_pcg64i_random_t;
static_always_inline void
clib_pcg_setseq_64_step_r (clib_pcg_state_setseq_64_t *rng)
{
rng->state = rng->state * 6364136223846793005ULL + rng->inc;
}
static_always_inline u64
clib_pcg_output_rxs_m_xs_64_64 (u64 state)
{
u64 word =
((state >> ((state >> 59u) + 5u)) ^ state) * 12605985483714917081ull;
return (word >> 43u) ^ word;
}
static_always_inline u64
clib_pcg_setseq_64_rxs_m_xs_64_random_r (clib_pcg_state_setseq_64_t *rng)
{
u64 oldstate = rng->state;
clib_pcg_setseq_64_step_r (rng);
return clib_pcg_output_rxs_m_xs_64_64 (oldstate);
}
static_always_inline void
clib_pcg_setseq_64_srandom_r (clib_pcg_state_setseq_64_t *rng, u64 initstate,
u64 initseq)
{
rng->state = 0U;
rng->inc = (initseq << 1u) | 1u;
clib_pcg_setseq_64_step_r (rng);
rng->state += initstate;
clib_pcg_setseq_64_step_r (rng);
}