diff options
author | Marcus Müller <mmueller@gnuradio.org> | 2021-03-25 18:13:35 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-03-25 13:13:35 -0400 |
commit | 4dd02dac2fcaf45f398c074735a7359330f78d77 (patch) | |
tree | b09529d96288fbdfb3ad703c3475fbb1154e2548 /gr-analog/lib | |
parent | 9a08594ae534c41d20e21187618de9ff3cc67336 (diff) |
analog/fastnoise: avoid modulo operation when picking indices
When the pool is power-of-2-sized, index generation can be done using a simple bitmask. Document this, add logging info.
- use unsigned and fixed-length int where due
- avoid expensive integer modulo operation when possible
- extract power-of-two constexpr
- don't clutter the logs for small pool sizes
Signed-off-by: Marcus Müller <marcus@hostalia.de>
Diffstat (limited to 'gr-analog/lib')
-rw-r--r-- | gr-analog/lib/fastnoise_source_impl.cc | 74 | ||||
-rw-r--r-- | gr-analog/lib/fastnoise_source_impl.h | 3 |
2 files changed, 59 insertions, 18 deletions
diff --git a/gr-analog/lib/fastnoise_source_impl.cc b/gr-analog/lib/fastnoise_source_impl.cc index f0f9200cee..dd319f5126 100644 --- a/gr-analog/lib/fastnoise_source_impl.cc +++ b/gr-analog/lib/fastnoise_source_impl.cc @@ -13,6 +13,8 @@ #include <config.h> #endif +#include <boost/format.hpp> + #include "fastnoise_source_impl.h" #include <gnuradio/io_signature.h> #include <gnuradio/xoroshiro128p.h> @@ -22,9 +24,16 @@ namespace gr { namespace analog { +bool constexpr is_pwr_of_two(size_t value) +{ + // simple binary trick: an integer x is power of 2 if x-1 is all 1s, but only below + // the old 1-position. + // also, zero is not a power of two + return value && !(value & (value - 1)); +} template <class T> typename fastnoise_source<T>::sptr -fastnoise_source<T>::make(noise_type_t type, float ampl, long seed, long samples) +fastnoise_source<T>::make(noise_type_t type, float ampl, uint64_t seed, size_t samples) { return gnuradio::make_block_sptr<fastnoise_source_impl<T>>(type, ampl, seed, samples); } @@ -32,16 +41,23 @@ fastnoise_source<T>::make(noise_type_t type, float ampl, long seed, long samples template <> void fastnoise_source_impl<gr_complex>::generate() { - int noutput_items = d_samples.size(); + size_t noutput_items = d_samples.size(); + if (noutput_items >= 1 << 23) { + GR_LOG_INFO( + d_logger, + boost::format("Generating %d complex values. This might take a while.") % + noutput_items); + } + switch (d_type) { case GR_UNIFORM: - for (int i = 0; i < noutput_items; i++) + for (size_t i = 0; i < noutput_items; i++) d_samples[i] = gr_complex(d_ampl * ((d_rng.ran1() * 2.0) - 1.0), d_ampl * ((d_rng.ran1() * 2.0) - 1.0)); break; case GR_GAUSSIAN: - for (int i = 0; i < noutput_items; i++) + for (size_t i = 0; i < noutput_items; i++) d_samples[i] = d_ampl * d_rng.rayleigh_complex(); break; default: @@ -52,17 +68,24 @@ void fastnoise_source_impl<gr_complex>::generate() template <class T> fastnoise_source_impl<T>::fastnoise_source_impl(noise_type_t type, float ampl, - long seed, - long samples) + uint64_t seed, + size_t samples) : sync_block("fastnoise_source", io_signature::make(0, 0, 0), io_signature::make(1, 1, sizeof(T))), d_type(type), d_ampl(ampl), - d_rng(seed) + d_rng(seed), + d_bitmask(is_pwr_of_two(samples) ? samples - 1 : 0) { + if (!d_bitmask) { + GR_LOG_INFO(this->d_logger, + boost::format("Using non-power-of-2 sample pool size %d. This has " + "negative effect on performance.") % + samples); + } d_samples.resize(samples); - xoroshiro128p_seed(d_state, (uint64_t)seed); + xoroshiro128p_seed(d_state, seed); generate(); } @@ -70,15 +93,22 @@ fastnoise_source_impl<T>::fastnoise_source_impl(noise_type_t type, template <> fastnoise_source_impl<gr_complex>::fastnoise_source_impl(noise_type_t type, float ampl, - long seed, - long samples) + uint64_t seed, + size_t samples) : sync_block("fastnoise_source", io_signature::make(0, 0, 0), io_signature::make(1, 1, sizeof(gr_complex))), d_type(type), d_ampl(ampl / sqrtf(2.0f)), - d_rng(seed) + d_rng(seed), + d_bitmask(is_pwr_of_two(samples) ? samples - 1 : 0) { + if (!d_bitmask) { + GR_LOG_INFO(d_logger, + boost::format("Using non-power-of-2 sample pool size %d. This has " + "negative effect on performance.") % + samples); + } d_samples.resize(samples); xoroshiro128p_seed(d_state, (uint64_t)seed); generate(); @@ -117,25 +147,30 @@ void fastnoise_source_impl<gr_complex>::set_amplitude(float ampl) template <class T> void fastnoise_source_impl<T>::generate() { - int noutput_items = d_samples.size(); + size_t noutput_items = d_samples.size(); + if (noutput_items >= 1 << 23) { + GR_LOG_INFO(this->d_logger, + boost::format("Generating %d values. This might take a while.") % + noutput_items); + } switch (d_type) { case GR_UNIFORM: - for (int i = 0; i < noutput_items; i++) + for (size_t i = 0; i < noutput_items; i++) d_samples[i] = (T)(d_ampl * ((d_rng.ran1() * 2.0) - 1.0)); break; case GR_GAUSSIAN: - for (int i = 0; i < noutput_items; i++) + for (size_t i = 0; i < noutput_items; i++) d_samples[i] = (T)(d_ampl * d_rng.gasdev()); break; case GR_LAPLACIAN: - for (int i = 0; i < noutput_items; i++) + for (size_t i = 0; i < noutput_items; i++) d_samples[i] = (T)(d_ampl * d_rng.laplacian()); break; case GR_IMPULSE: // FIXME changeable impulse settings - for (int i = 0; i < noutput_items; i++) + for (size_t i = 0; i < noutput_items; i++) d_samples[i] = (T)(d_ampl * d_rng.impulse(9)); break; default: @@ -163,7 +198,12 @@ int fastnoise_source_impl<T>::work(int noutput_items, template <class T> T fastnoise_source_impl<T>::sample() { - size_t idx = xoroshiro128p_next(d_state) % d_samples.size(); + size_t idx; + if (d_bitmask) { + idx = xoroshiro128p_next(d_state) & d_bitmask; + } else { + idx = xoroshiro128p_next(d_state) % d_samples.size(); + } return d_samples[idx]; } diff --git a/gr-analog/lib/fastnoise_source_impl.h b/gr-analog/lib/fastnoise_source_impl.h index 872f41e4b1..d20a1178ec 100644 --- a/gr-analog/lib/fastnoise_source_impl.h +++ b/gr-analog/lib/fastnoise_source_impl.h @@ -28,9 +28,10 @@ private: gr::random d_rng; std::vector<T> d_samples; uint64_t d_state[2]; + size_t d_bitmask; public: - fastnoise_source_impl(noise_type_t type, float ampl, long seed, long samples); + fastnoise_source_impl(noise_type_t type, float ampl, uint64_t seed, size_t samples); ~fastnoise_source_impl() override; T sample() override; |