summaryrefslogtreecommitdiff
path: root/gr-analog/lib
diff options
context:
space:
mode:
authorMarcus Müller <mmueller@gnuradio.org>2021-03-25 18:13:35 +0100
committerGitHub <noreply@github.com>2021-03-25 13:13:35 -0400
commit4dd02dac2fcaf45f398c074735a7359330f78d77 (patch)
treeb09529d96288fbdfb3ad703c3475fbb1154e2548 /gr-analog/lib
parent9a08594ae534c41d20e21187618de9ff3cc67336 (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.cc74
-rw-r--r--gr-analog/lib/fastnoise_source_impl.h3
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;