Skip to content

Commit

Permalink
RNGScope minor refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
szhorvat committed Jul 28, 2024
1 parent 7603f51 commit 595a1b4
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 31 deletions.
25 changes: 14 additions & 11 deletions examples/ex_rng_scope.cpp
Original file line number Diff line number Diff line change
@@ -1,30 +1,33 @@
#include <iostream>

#include <igraph.hpp>
#include "ex_vector_print.hpp"
#include <iostream>

// This example illustrates the use of ig::RNGScope, which provides a localized
// random state within the current scope.

int main() {
// Check that we can influence the RNG.
{
ig::RNGScope filled(1000);
ig::RNGScope filled(42);
std::cout << "New RNG scope:" << std::endl;
std::cout << " Draw from [0, 100]: " << igraph_rng_get_integer(igraph_rng_default(), 0, 100) << std::endl;
std::cout << " Draw from [0, 100]: " << igraph_rng_get_integer(igraph_rng_default(), 0, 100) << std::endl;
std::cout << " Draw from [0, 100]: " << RNG_INTEGER(0, 100) << std::endl;
std::cout << " Draw from [0, 100]: " << RNG_INTEGER(0, 100) << std::endl;
}

// Check that the destructor correctly unsets the RNG.
{
ig::RNGScope filled(1000);
ig::RNGScope filled(42);
std::cout << "New RNG scope:" << std::endl;
std::cout << " Draw from [0, 100]: " << igraph_rng_get_integer(igraph_rng_default(), 0, 100) << std::endl;
std::cout << " Draw from [0, 100]: " << RNG_INTEGER(0, 100) << std::endl;

{
ig::RNGScope nested; // uses a default seed and type.
ig::RNGScope nested; // uses a default type and a seed generated via std::random_device
std::cout << " New RNG scope:" << std::endl;
std::cout << " Draw from [0, 100]: " << igraph_rng_get_integer(igraph_rng_default(), 0, 100) << std::endl;
std::cout << " Draw from [0, 100]: " << igraph_rng_get_integer(igraph_rng_default(), 0, 100) << std::endl;
std::cout << " Draw from [0, 100]: " << RNG_INTEGER(0, 100) << std::endl;
std::cout << " Draw from [0, 100]: " << RNG_INTEGER(0, 100) << std::endl;
}

std::cout << " Draw from [0, 100]: " << igraph_rng_get_integer(igraph_rng_default(), 0, 100) << std::endl;
std::cout << " Draw from [0, 100]: " << RNG_INTEGER(0, 100) << std::endl;
}

return 0;
Expand Down
1 change: 1 addition & 0 deletions include/igraph.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <cassert>
#include <complex>
#include <iterator>
#include <random>
#include <stdexcept>
#include <type_traits>
#include <utility>
Expand Down
39 changes: 19 additions & 20 deletions include/rng_scope.hpp
Original file line number Diff line number Diff line change
@@ -1,41 +1,40 @@

class RNGScope {
igraph_rng_t *previous;
igraph_rng_t current;

constexpr const static igraph_rng_type_t *default_type = &igraph_rngtype_pcg32;

public:
RNGScope(igraph_uint_t seed) : RNGScope(seed, &igraph_rngtype_pcg32) {}
explicit RNGScope(igraph_uint_t seed) : RNGScope(seed, default_type) {}

RNGScope(igraph_uint_t seed, const igraph_rng_type_t* type) {
RNGScope(igraph_uint_t seed, const igraph_rng_type_t *type) {
check(igraph_rng_init(&current, type));

auto errcode = igraph_rng_seed(&current, seed);
igraph_error_t errcode = igraph_rng_seed(&current, seed);
if (errcode != IGRAPH_SUCCESS) {
igraph_rng_destroy(&current);
throw Exception(errcode);
}

previous = *(igraph_rng_default());
// TODO for igraph 1.0 where igraph_rng_set_default() returns the previous generator.
previous = igraph_rng_default();
igraph_rng_set_default(&current);
}

RNGScope(const igraph_rng_type_t* type) {
check(igraph_rng_init(&current, type));
previous = *(igraph_rng_default());
igraph_rng_set_default(&current);
}
explicit RNGScope(const igraph_rng_type_t *type) : RNGScope(std::random_device{}(), type) { }

RNGScope() : RNGScope(&igraph_rngtype_pcg32) {}
RNGScope() : RNGScope(default_type) { }

public:
// We shouldn't be copying or moving an RNGscope object, as this defeats the logic provided by scoping.
RNGScope(const RNGScope&) = delete;
RNGScope& operator=(const RNGScope&) = delete;
RNGScope(RNGScope&&) = delete;
RNGScope& operator=(RNGScope&&) = delete;
// We shouldn't be copying or moving an RNGScope object, as this defeats the logic provided by scoping.
RNGScope(const RNGScope &) = delete;
RNGScope & operator = (const RNGScope&) = delete;
RNGScope(RNGScope &&) = delete;
RNGScope & operator = (RNGScope &&) = delete;

~RNGScope() {
igraph_rng_set_default(&previous);
igraph_rng_set_default(previous);
igraph_rng_destroy(&current);
}

private:
igraph_rng_t previous;
igraph_rng_t current;
};

0 comments on commit 595a1b4

Please sign in to comment.