Kaido Kert | b108943 | 2024-03-18 19:46:49 -0700 | [diff] [blame] | 1 | // Copyright 2017 The Abseil Authors. |
| 2 | // |
| 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // you may not use this file except in compliance with the License. |
| 5 | // You may obtain a copy of the License at |
| 6 | // |
| 7 | // https://www.apache.org/licenses/LICENSE-2.0 |
| 8 | // |
| 9 | // Unless required by applicable law or agreed to in writing, software |
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, |
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 | // See the License for the specific language governing permissions and |
| 13 | // limitations under the License. |
| 14 | // |
| 15 | // ----------------------------------------------------------------------------- |
| 16 | // File: seed_sequences.h |
| 17 | // ----------------------------------------------------------------------------- |
| 18 | // |
| 19 | // This header contains utilities for creating and working with seed sequences |
| 20 | // conforming to [rand.req.seedseq]. In general, direct construction of seed |
| 21 | // sequences is discouraged, but use-cases for construction of identical bit |
| 22 | // generators (using the same seed sequence) may be helpful (e.g. replaying a |
| 23 | // simulation whose state is derived from variates of a bit generator). |
| 24 | |
| 25 | #ifndef ABSL_RANDOM_SEED_SEQUENCES_H_ |
| 26 | #define ABSL_RANDOM_SEED_SEQUENCES_H_ |
| 27 | |
| 28 | #include <iterator> |
| 29 | #include <random> |
| 30 | |
| 31 | #include "absl/base/config.h" |
| 32 | #include "absl/random/internal/salted_seed_seq.h" |
| 33 | #include "absl/random/internal/seed_material.h" |
| 34 | #include "absl/random/seed_gen_exception.h" |
| 35 | #include "absl/types/span.h" |
| 36 | |
| 37 | namespace absl { |
| 38 | ABSL_NAMESPACE_BEGIN |
| 39 | |
| 40 | // ----------------------------------------------------------------------------- |
| 41 | // absl::SeedSeq |
| 42 | // ----------------------------------------------------------------------------- |
| 43 | // |
| 44 | // `absl::SeedSeq` constructs a seed sequence according to [rand.req.seedseq] |
| 45 | // for use within bit generators. `absl::SeedSeq`, unlike `std::seed_seq` |
| 46 | // additionally salts the generated seeds with extra implementation-defined |
| 47 | // entropy. For that reason, you can use `absl::SeedSeq` in combination with |
| 48 | // standard library bit generators (e.g. `std::mt19937`) to introduce |
| 49 | // non-determinism in your seeds. |
| 50 | // |
| 51 | // Example: |
| 52 | // |
| 53 | // absl::SeedSeq my_seed_seq({a, b, c}); |
| 54 | // std::mt19937 my_bitgen(my_seed_seq); |
| 55 | // |
| 56 | using SeedSeq = random_internal::SaltedSeedSeq<std::seed_seq>; |
| 57 | |
| 58 | // ----------------------------------------------------------------------------- |
| 59 | // absl::CreateSeedSeqFrom(bitgen*) |
| 60 | // ----------------------------------------------------------------------------- |
| 61 | // |
| 62 | // Constructs a seed sequence conforming to [rand.req.seedseq] using variates |
| 63 | // produced by a provided bit generator. |
| 64 | // |
| 65 | // You should generally avoid direct construction of seed sequences, but |
| 66 | // use-cases for reuse of a seed sequence to construct identical bit generators |
| 67 | // may be helpful (eg. replaying a simulation whose state is derived from bit |
| 68 | // generator values). |
| 69 | // |
| 70 | // If bitgen == nullptr, then behavior is undefined. |
| 71 | // |
| 72 | // Example: |
| 73 | // |
| 74 | // absl::BitGen my_bitgen; |
| 75 | // auto seed_seq = absl::CreateSeedSeqFrom(&my_bitgen); |
| 76 | // absl::BitGen new_engine(seed_seq); // derived from my_bitgen, but not |
| 77 | // // correlated. |
| 78 | // |
| 79 | template <typename URBG> |
| 80 | SeedSeq CreateSeedSeqFrom(URBG* urbg) { |
| 81 | SeedSeq::result_type |
| 82 | seed_material[random_internal::kEntropyBlocksNeeded]; |
| 83 | |
| 84 | if (!random_internal::ReadSeedMaterialFromURBG( |
| 85 | urbg, absl::MakeSpan(seed_material))) { |
| 86 | random_internal::ThrowSeedGenException(); |
| 87 | } |
| 88 | return SeedSeq(std::begin(seed_material), std::end(seed_material)); |
| 89 | } |
| 90 | |
| 91 | // ----------------------------------------------------------------------------- |
| 92 | // absl::MakeSeedSeq() |
| 93 | // ----------------------------------------------------------------------------- |
| 94 | // |
| 95 | // Constructs an `absl::SeedSeq` salting the generated values using |
| 96 | // implementation-defined entropy. The returned sequence can be used to create |
| 97 | // equivalent bit generators correlated using this sequence. |
| 98 | // |
| 99 | // Example: |
| 100 | // |
| 101 | // auto my_seed_seq = absl::MakeSeedSeq(); |
| 102 | // std::mt19937 rng1(my_seed_seq); |
| 103 | // std::mt19937 rng2(my_seed_seq); |
| 104 | // EXPECT_EQ(rng1(), rng2()); |
| 105 | // |
| 106 | SeedSeq MakeSeedSeq(); |
| 107 | |
| 108 | ABSL_NAMESPACE_END |
| 109 | } // namespace absl |
| 110 | |
| 111 | #endif // ABSL_RANDOM_SEED_SEQUENCES_H_ |