summaryrefslogtreecommitdiff
path: root/gnuradio-runtime/lib/block_executor.cc
diff options
context:
space:
mode:
authorAndy Walls <awalls.cx18@gmail.com>2018-01-05 15:48:26 -0500
committerMarcus Müller <marcus@hostalia.de>2018-08-23 19:31:13 +0200
commitb09536999ebf45065fd4b06dd40a56782991b492 (patch)
treefa1c8dfb1829c72f871e039b66d2e0f7679b8137 /gnuradio-runtime/lib/block_executor.cc
parent9ea30c8d94f006649ec4626cbc333e93e5c029a5 (diff)
runtime: Use multiprecision rational arithmetic to propagate tags
Avoid floating point precision problems in propagation of tags for the following cases: - Common relative rates that are non-terminating in binary (1/3, 1/5, 1/7, ...) - Large tag offsets - Inexact floating point reciprocals when specifying the relative rate This change to the runtime only fixes the tag propagation problems for blocks with a fixed/unchanging relative rate. This change adds a dependency on the MIPR library (a fork of the GMP library) to perform multiple precision interger rational arithmetic. MIPR was chosen as it purports to maintain a properly working Windows build for cross-platform compatability. Optimizations in MIPR are also targeted to ARM in additional to x86-64.
Diffstat (limited to 'gnuradio-runtime/lib/block_executor.cc')
-rw-r--r--gnuradio-runtime/lib/block_executor.cc54
1 files changed, 41 insertions, 13 deletions
diff --git a/gnuradio-runtime/lib/block_executor.cc b/gnuradio-runtime/lib/block_executor.cc
index 754744449a..6152ff6765 100644
--- a/gnuradio-runtime/lib/block_executor.cc
+++ b/gnuradio-runtime/lib/block_executor.cc
@@ -94,8 +94,11 @@ namespace gr {
static bool
propagate_tags(block::tag_propagation_policy_t policy, block_detail *d,
const std::vector<uint64_t> &start_nitems_read, double rrate,
+ mpq_class &mp_rrate, bool use_fp_rrate,
std::vector<tag_t> &rtags, long block_id)
{
+ static const mpq_class one_half(1, 2);
+
// Move tags downstream
// if a sink, we don't need to move downstream
if(d->sink_p()) {
@@ -131,7 +134,7 @@ namespace gr {
out_buf[o]->add_item_tag(*t);
}
}
- else {
+ else if(use_fp_rrate) {
for(t = rtags.begin(); t != rtags.end(); t++) {
tag_t new_tag = *t;
new_tag.offset = ((double)new_tag.offset * rrate) + 0.5;
@@ -139,6 +142,16 @@ namespace gr {
out_buf[o]->add_item_tag(new_tag);
}
}
+ else {
+ mpz_class offset;
+ for(t = rtags.begin(); t != rtags.end(); t++) {
+ tag_t new_tag = *t;
+ offset = new_tag.offset * mp_rrate + one_half;
+ new_tag.offset = offset.get_ui();
+ for(int o = 0; o < d->noutputs(); o++)
+ out_buf[o]->add_item_tag(new_tag);
+ }
+ }
}
}
break;
@@ -159,10 +172,26 @@ namespace gr {
out_buf = d->output(i);
std::vector<tag_t>::iterator t;
- for(t = rtags.begin(); t != rtags.end(); t++) {
- tag_t new_tag = *t;
- new_tag.offset = ((double)new_tag.offset * rrate) + 0.5;
- out_buf->add_item_tag(new_tag);
+ if(rrate == 1.0) {
+ for(t = rtags.begin(); t != rtags.end(); t++) {
+ out_buf->add_item_tag(*t);
+ }
+ }
+ else if(use_fp_rrate) {
+ for(t = rtags.begin(); t != rtags.end(); t++) {
+ tag_t new_tag = *t;
+ new_tag.offset = ((double)new_tag.offset * rrate) + 0.5;
+ out_buf->add_item_tag(new_tag);
+ }
+ }
+ else {
+ mpz_class offset;
+ for(t = rtags.begin(); t != rtags.end(); t++) {
+ tag_t new_tag = *t;
+ offset = new_tag.offset * mp_rrate + one_half;
+ new_tag.offset = offset.get_ui();
+ out_buf->add_item_tag(new_tag);
+ }
}
}
}
@@ -212,7 +241,6 @@ namespace gr {
int max_noutput_items;
int new_alignment = 0;
int alignment_state = -1;
- double rrate;
block *m = d_block.get();
block_detail *d = m->detail().get();
@@ -321,10 +349,8 @@ namespace gr {
noutput_items = min_available_space(d, m->output_multiple(), m->min_noutput_items());
if(ENABLE_LOGGING) {
*d_log << " regular ";
- if(m->relative_rate() >= 1.0)
- *d_log << "1:" << m->relative_rate() << std::endl;
- else
- *d_log << 1.0/m->relative_rate() << ":1\n";
+ *d_log << m->relative_rate_i() << ":"
+ << m->relative_rate_d() << std::endl;
*d_log << " max_items_avail = " << max_items_avail << std::endl;
*d_log << " noutput_items = " << noutput_items << std::endl;
}
@@ -490,6 +516,7 @@ namespace gr {
// Now propagate the tags based on the new relative rate
if(!propagate_tags(m->tag_propagation_policy(), d,
d_start_nitems_read, m->relative_rate(),
+ m->mp_relative_rate(), m->update_rate(),
d_returned_tags, m->unique_id()))
goto were_done;
@@ -505,9 +532,10 @@ namespace gr {
// In the block constructor, use enable_update_rate(true).
if(m->update_rate()) {
//rrate = ((double)(m->nitems_written(0))) / ((double)m->nitems_read(0));
- rrate = (double)n / (double)d->consumed();
- if(rrate > 0)
- m->set_relative_rate(rrate);
+ //if(rrate > 0.0)
+ // m->set_relative_rate(rrate);
+ if((n > 0) && (d->consumed() > 0))
+ m->set_relative_rate((uint64_t)n, (uint64_t)d->consumed());
}
if(d->d_produce_or > 0) // block produced something