summaryrefslogtreecommitdiff
path: root/gr-analog
diff options
context:
space:
mode:
Diffstat (limited to 'gr-analog')
-rw-r--r--gr-analog/include/gnuradio/analog/fastnoise_source_X.h.t3
-rw-r--r--gr-analog/lib/fastnoise_source_X_impl.cc.t34
-rw-r--r--gr-analog/lib/fastnoise_source_X_impl.h.t2
-rw-r--r--gr-analog/python/analog/qa_fastnoise.py120
4 files changed, 124 insertions, 35 deletions
diff --git a/gr-analog/include/gnuradio/analog/fastnoise_source_X.h.t b/gr-analog/include/gnuradio/analog/fastnoise_source_X.h.t
index 850633979c..f588299604 100644
--- a/gr-analog/include/gnuradio/analog/fastnoise_source_X.h.t
+++ b/gr-analog/include/gnuradio/analog/fastnoise_source_X.h.t
@@ -29,6 +29,8 @@
#include <gnuradio/analog/noise_type.h>
#include <gnuradio/sync_block.h>
+#include <vector>
+
namespace gr {
namespace analog {
@@ -62,6 +64,7 @@ namespace gr {
long seed = 0, long samples=1024*16);
virtual @TYPE@ sample() = 0;
virtual @TYPE@ sample_unbiased() = 0;
+ virtual const std::vector<@TYPE@>& samples() const = 0;
/*!
* Set the noise type. Nominally from the
diff --git a/gr-analog/lib/fastnoise_source_X_impl.cc.t b/gr-analog/lib/fastnoise_source_X_impl.cc.t
index 940918b11b..72c6cb0582 100644
--- a/gr-analog/lib/fastnoise_source_X_impl.cc.t
+++ b/gr-analog/lib/fastnoise_source_X_impl.cc.t
@@ -27,6 +27,7 @@
#endif
#include "@IMPL_NAME@.h"
+#include <gnuradio/xoroshiro128p.h>
#include <gnuradio/io_signature.h>
#include <stdexcept>
@@ -46,13 +47,13 @@ namespace gr {
io_signature::make(1, 1, sizeof(@TYPE@))),
d_type(type),
#if @IS_COMPLEX@ // complex?
- d_ampl(ampl/sqrtf(2.0f)),
+ d_ampl(ampl/sqrtf(2.0f))
#else
- d_ampl(ampl),
+ d_ampl(ampl)
#endif
- d_rng(seed)
{
d_samples.resize(samples);
+ xoroshiro128p_seed(d_state, (uint64_t) seed);
generate();
}
@@ -144,32 +145,27 @@ namespace gr {
@TYPE@ @IMPL_NAME@::sample()
{
-#ifdef HAVE_RAND48
- size_t idx = lrand48() % d_samples.size();
-#else
- size_t idx = rand() % d_samples.size();
-#endif
+ size_t idx = xoroshiro128p_next(d_state) % d_samples.size();
return d_samples[idx];
}
-#ifndef FASTNOISE_RANDOM_SIGN
-#ifndef HAVE_RAND48
-#define FASTNOISE_RANDOM_SIGN ((rand()%2==0)?1:-1)
-#else
-#define FASTNOISE_RANDOM_SIGN ((lrand48()%2==0)?1:-1)
-#endif
-#endif
-
@TYPE@ @IMPL_NAME@::sample_unbiased()
{
+ uint64_t random_int = xoroshiro128p_next(d_state);
#if @IS_COMPLEX@
gr_complex s(sample());
- return gr_complex(FASTNOISE_RANDOM_SIGN * s.real(),
- FASTNOISE_RANDOM_SIGN * s.imag());
+ float re = (random_int & (UINT64_C(1)<<23)) ? (- s.real()) : (s.real());
+ float im = (random_int & (UINT64_C(1)<<42)) ? (- s.real()) : (s.real());
+ return gr_complex(re, im);
#else
- return FASTNOISE_RANDOM_SIGN * sample();
+ float s = sample();
+ return (random_int & (1<<23)) ? (-s) : s;
#endif
}
+ const std::vector<@TYPE@>& @IMPL_NAME@::samples() const
+ {
+ return d_samples;
+ }
} /* namespace analog */
} /* namespace gr */
diff --git a/gr-analog/lib/fastnoise_source_X_impl.h.t b/gr-analog/lib/fastnoise_source_X_impl.h.t
index 8ad1e4f8fe..ef0465729d 100644
--- a/gr-analog/lib/fastnoise_source_X_impl.h.t
+++ b/gr-analog/lib/fastnoise_source_X_impl.h.t
@@ -38,6 +38,7 @@ namespace gr {
float d_ampl;
gr::random d_rng;
std::vector<@TYPE@> d_samples;
+ uint64_t d_state[2];
public:
@IMPL_NAME@(noise_type_t type, float ampl, long seed, long samples);
@@ -49,6 +50,7 @@ namespace gr {
void set_type(noise_type_t type);
void set_amplitude(float ampl);
void generate();
+ const std::vector<@TYPE@>& samples() const;
noise_type_t type() const { return d_type; }
float amplitude() const { return d_ampl; }
diff --git a/gr-analog/python/analog/qa_fastnoise.py b/gr-analog/python/analog/qa_fastnoise.py
index 91e1cb87b7..f712d66ca7 100644
--- a/gr-analog/python/analog/qa_fastnoise.py
+++ b/gr-analog/python/analog/qa_fastnoise.py
@@ -20,32 +20,120 @@
# Boston, MA 02110-1301, USA.
#
-from gnuradio import gr, gr_unittest, analog
+from gnuradio import gr, gr_unittest, analog, blocks
+import numpy
+
class test_fastnoise_source(gr_unittest.TestCase):
def setUp (self):
- self.tb = gr.top_block ()
+
+ self.num = 2**22
+ self.num_items = 10**6
+ self.default_args = {"samples": self.num, "seed": 43, "ampl": 1}
def tearDown (self):
- self.tb = None
+ pass
+
+ def run_test_real(self, form):
+ """ Run test case with float input/output
+ """
+ tb = gr.top_block()
+ src = analog.fastnoise_source_f(type=form, **self.default_args)
+ head = blocks.head(nitems=self.num_items, sizeof_stream_item=gr.sizeof_float)
+ sink = blocks.vector_sink_f()
+ tb.connect(src, head, sink)
+ tb.run()
+ return numpy.array(sink.data())
+
+ def run_test_complex(self, form):
+ """ Run test case with complex input/output
+ """
+ tb = gr.top_block()
+ src = analog.fastnoise_source_c(type=form, **self.default_args)
+ head = blocks.head(nitems=self.num_items, sizeof_stream_item=gr.sizeof_gr_complex)
+ sink = blocks.vector_sink_c()
+ tb.connect(src, head, sink)
+ tb.run()
+ return numpy.array(sink.data())
+
+ def test_001_real_uniform_moments(self):
+
+ data = self.run_test_real(analog.GR_UNIFORM)
+
+ self.assertAlmostEqual(min(data), -1, places=4)
+ self.assertAlmostEqual(max(data), 1, places=4)
+
+ # mean, variance
+ self.assertAlmostEqual(data.mean(), 0, places=2)
+ self.assertAlmostEqual(data.var(), (1-(-1))**2./12, places=3)
+
+ def test_001_real_gaussian_moments(self):
+ data = self.run_test_real(analog.GR_GAUSSIAN)
+
+ # mean, variance
+ self.assertAlmostEqual(data.mean(), 0, places=2)
+ self.assertAlmostEqual(data.var(), 1, places=2)
- def test_001(self):
- # Just confirm that we can instantiate a noise source
- op = analog.fastnoise_source_f(analog.GR_GAUSSIAN, 10, 10)
+ def test_001_real_laplacian_moments(self):
+ data = self.run_test_real(analog.GR_LAPLACIAN)
- def test_002(self):
- # Test get methods
- set_type = analog.GR_GAUSSIAN
- set_ampl = 10
- op = analog.fastnoise_source_f(set_type, set_ampl, 10)
- get_type = op.type()
- get_ampl = op.amplitude()
+ # mean, variance
+ self.assertAlmostEqual(data.mean(), 0, places=2)
+ self.assertAlmostEqual(data.var(), 2, places=2)
- self.assertEqual(get_type, set_type)
- self.assertEqual(get_ampl, set_ampl)
+ def test_001_complex_uniform_moments(self):
+ data = self.run_test_complex(analog.GR_UNIFORM)
+ # mean, variance
+ self.assertAlmostEqual(data.real.mean(), 0, places=2)
+ self.assertAlmostEqual(data.real.var(), 0.5*(1-(-1))**2./12, places=3)
+ self.assertAlmostEqual(data.imag.mean(), 0, places=2)
+ self.assertAlmostEqual(data.imag.var(), 0.5*(1-(-1))**2./12, places=3)
+
+ def test_001_complex_gaussian_moments(self):
+ data = self.run_test_complex(analog.GR_GAUSSIAN)
+
+ # mean, variance
+ self.assertAlmostEqual(data.real.mean(), 0, places=2)
+ self.assertAlmostEqual(data.real.var(), 0.5, places=2)
+
+ self.assertAlmostEqual(data.imag.mean(), 0, places=2)
+ self.assertAlmostEqual(data.imag.var(), 0.5, places=2)
+
+ def test_002_real_uniform_reproducibility(self):
+ data1 = self.run_test_real(analog.GR_UNIFORM)
+ data2 = self.run_test_real(analog.GR_UNIFORM)
+
+ # It's pseudoramdo thus must be equal
+ self.assertTrue(numpy.array_equal(data1, data2))
+
+ def test_002_real_gaussian_reproducibility(self):
+ data1 = self.run_test_real(analog.GR_GAUSSIAN)
+ data2 = self.run_test_real(analog.GR_GAUSSIAN)
+
+ self.assertTrue(numpy.array_equal(data1, data2))
+
+ def test_003_real_uniform_pool(self):
+ src = analog.fastnoise_source_f(type=analog.GR_UNIFORM, **self.default_args)
+ src2 = analog.fastnoise_source_f(type=analog.GR_UNIFORM, **self.default_args)
+ self.assertTrue(numpy.array_equal(numpy.array(src.samples()), numpy.array(src2.samples())))
+ def test_003_real_gaussian_pool(self):
+ src = analog.fastnoise_source_f(type=analog.GR_GAUSSIAN, **self.default_args)
+ src2 = analog.fastnoise_source_f(type=analog.GR_GAUSSIAN, **self.default_args)
+ self.assertTrue(numpy.array_equal(numpy.array(src.samples()), numpy.array(src2.samples())))
+ def test_003_cmplx_gaussian_pool(self):
+ src = analog.fastnoise_source_c(type=analog.GR_GAUSSIAN, **self.default_args)
+ src2 = analog.fastnoise_source_c(type=analog.GR_GAUSSIAN, **self.default_args)
+ self.assertTrue(numpy.array_equal(numpy.array(src.samples()), numpy.array(src2.samples())))
+ def test_003_cmplx_uniform_pool(self):
+ src = analog.fastnoise_source_c(type=analog.GR_UNIFORM, **self.default_args)
+ src2 = analog.fastnoise_source_c(type=analog.GR_UNIFORM, **self.default_args)
+ self.assertTrue(numpy.array_equal(numpy.array(src.samples()), numpy.array(src2.samples())))
+ def test_003_real_laplacian_pool(self):
+ src = analog.fastnoise_source_f(type=analog.GR_LAPLACIAN, **self.default_args)
+ src2 = analog.fastnoise_source_f(type=analog.GR_LAPLACIAN, **self.default_args)
+ self.assertTrue(numpy.array_equal(numpy.array(src.samples()), numpy.array(src2.samples())))
if __name__ == '__main__':
gr_unittest.run(test_fastnoise_source, "test_fastnoise_source.xml")
-