# Blocks.complex\_to\_arg() implementation

**URL:** <https://www.ruby-forum.com/t/blocks-complex-to-arg-implementation/231529>\
**Category:** GNU Radio\
**Created:** [August 13, 2014, 4:16pm UTC](https://www.ruby-forum.com/t/blocks-complex-to-arg-implementation/231529 "2014-08-13T16:16:45Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![addis\_a](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/c4cdca/32.png) [@addis\_a](https://www.ruby-forum.com/u/addis_a)\
**Post date:** [August 13, 2014, 4:16pm UTC](https://www.ruby-forum.com/t/blocks-complex-to-arg-implementation/231529/1 "2014-08-13T16:16:45Z")

</div>

Hello,

I haven’t checked if it is true for the code currently in git (some  
network problems here, I cannot access the repository), but in GNURadio  
3.7.2 the complex\_to\_arg() block is implemented with an atan2() function  
which has a quite large error (for my purposes, at least) and not the  
standard math library atan2() function.

I think that this should be mentioned in the documentation. Should I  
send a patch to add this info to the documentation?

Furthermore, even if the block does not use Volk for the computation the  
block constructor still enforces alignment of the buffer to satisfy Volk  
requirements, or at least this is what I believe the following code  
does:

```
  const int alignment_multiple =

```

volk\_get\_alignment() / sizeof(float);  
set\_alignment(std::max(1,alignment\_multiple));

I think this should be removed. Should I send a patch for this as well?

There is interest in adding a complex\_to\_arg\_slow() or similar block  
that trades execution speed for precision?

Thanks. Cheers,  
Daniele

---

<div class="post-metadata">

**Author:** ![Daniele\_N](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/74df32/32.png) [@Daniele\_N](https://www.ruby-forum.com/u/Daniele_N)\
**Post date:** [August 13, 2014, 4:38pm UTC](https://www.ruby-forum.com/t/blocks-complex-to-arg-implementation/231529/2 "2014-08-13T16:38:48Z")

</div>

On Wed, Aug 13, 2014 at 10:15 AM, Daniele N. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> 

The version we have in there is much (MUCH) faster than the libm atan2  
function. So yes, we trade off a bit of error for a massive  
computational  
gain. The error is very small from what I recall, expect in a few  
instances  
(near 0 or near pi/2 or something like that). Having a graph of the  
error  
somewhere would be helpful.

But yes, I agree. Mentioning that this function is a fast approximation  
in  
the documentation would be a good thing. Please send a patch (via a  
github  
pull request preferably).

> There is interest in adding a complex\_to\_arg\_slow() or similar block  
> that trades execution speed for precision?
> 
> Thanks. Cheers,  
> Daniele

The fast atan method we use is still faster than what we have in VOLK. I  
remember testing this out myself, which included putting that code into  
the  
constructor. However, take a look at this post:

> **[Volk Benchmarking — Rondeau Research](http://www.trondeau.com/blog/2012/2/17/volk-benchmarking.html)**
>
> Benchmarking Volk in GNU Radio 
> The intention of Volk is to increase the speed of our signal processing capabilities in GNU Radio, and so there needs to be a way to look at this. In particular, there were some under-the-hood changes to the scheduler...

We see an improvement in speed of blocks by doing the alignment.  
Actually,  
I think that all blocks should probably have their alignment set whether  
or  
not they use VOLK. But that would be a lot of work to do correctly with  
all  
of our blocks to make sure it’s done right and is actually giving us a  
benefit. But having test this one in particular, no, I don’t see any  
need  
to remove this code.

Tom

---

<div class="post-metadata">

**Author:** ![Daniele\_N](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/74df32/32.png) [@Daniele\_N](https://www.ruby-forum.com/u/Daniele_N)\
**Post date:** [August 14, 2014, 11:16am UTC](https://www.ruby-forum.com/t/blocks-complex-to-arg-implementation/231529/3 "2014-08-14T11:16:41Z")

</div>

On 13/08/2014 16:37, Tom R. wrote:

> The version we have in there is much (MUCH) faster than the libm atan2  
> function. So yes, we trade off a bit of error for a massive  
> computational gain. The error is very small from what I recall, expect  
> in a few instances (near 0 or near pi/2 or something like that). Having  
> a graph of the error somewhere would be helpful.

I think it depends on the point of view, for me it is a bit of  
computational gain for a massive error 🙂

> The fast atan method we use is still faster than what we have in VOLK. I  
> remember testing this out myself, which included putting that code into  
> the constructor. However, take a look at this post:
> 
> [Volk Benchmarking — Rondeau Research](http://www.trondeau.com/blog/2012/2/17/volk-benchmarking.html)

I don’t see anything specific to the atan2() and alignment there.

> We see an improvement in speed of blocks by doing the alignment.  
> Actually, I think that all blocks should probably have their alignment  
> set whether or not they use VOLK. But that would be a lot of work to do  
> correctly with all of our blocks to make sure it’s done right and is  
> actually giving us a benefit. But having test this one in particular,  
> no, I don’t see any need to remove this code.

I see. Probably a comment in the code mentioning this, to avoid other  
being puzzled, is in order here 🙂

Cheers,  
Daniele

---

<div class="post-metadata">

**Author:** ![Daniele\_N](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/74df32/32.png) [@Daniele\_N](https://www.ruby-forum.com/u/Daniele_N)\
**Post date:** [August 14, 2014, 3:12pm UTC](https://www.ruby-forum.com/t/blocks-complex-to-arg-implementation/231529/4 "2014-08-14T15:12:05Z")

</div>

On Thu, Aug 14, 2014 at 5:15 AM, Daniele N. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> On 13/08/2014 16:37, Tom R. wrote:
> 
> > The version we have in there is much (MUCH) faster than the libm atan2  
> > function. So yes, we trade off a bit of error for a massive  
> > computational gain. The error is very small from what I recall, expect  
> > in a few instances (near 0 or near pi/2 or something like that). Having  
> > a graph of the error somewhere would be helpful.
> 
> I think it depends on the point of view, for me it is a bit of  
> computational gain for a massive error 🙂

You say “massive error”, but I’ve plotted the error between the fast  
atan  
and the libm atan function before and have not noticed any error to be  
“massive”. On the other hand, the “bit” of computational gain is,  
indeed,  
quite a lot.

> > The fast atan method we use is still faster than what we have in VOLK. I  
> > remember testing this out myself, which included putting that code into  
> > the constructor. However, take a look at this post:
> > 
> > [Volk Benchmarking — Rondeau Research](http://www.trondeau.com/blog/2012/2/17/volk-benchmarking.html)
> 
> I don’t see anything specific to the atan2() and alignment there.

Nothing specific to the atan function. The post shows that changing from  
not using alignment to using alignment provides a boost in performance  
even  
before adding actual calls to VOLK. That’s what the difference between  
the  
red and blue bars shows.

Tom

---

<div class="post-metadata">

**Author:** ![Daniele\_N](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/74df32/32.png) [@Daniele\_N](https://www.ruby-forum.com/u/Daniele_N)\
**Post date:** [August 14, 2014, 3:26pm UTC](https://www.ruby-forum.com/t/blocks-complex-to-arg-implementation/231529/5 "2014-08-14T15:26:59Z")

</div>

On 14/08/2014 15:10, Tom R. wrote:

> ```
> I think it depends on the point of view, for me it is a bit of
> computational gain for a massive error :)
> 
> ```
> 
> You say “massive error”, but I’ve plotted the error between the fast  
> atan and the libm atan function before and have not noticed any error to  
> be “massive”. On the other hand, the “bit” of computational gain is,  
> indeed, quite a lot.

I was trying to stress that the speed vs correctness tradeoff should be  
evaluated case by case on the base of the requirements and limitations  
and that the results of this evaluation may be quite different depending  
on the situation.

Indeed in my current project I’m using both the fast atan and the libm  
atan to compute different hings in the same flow-graph (for a PLL loop  
the linear approximation for small angles is perfectly fine, not so much  
for other measurements).

I may have completely wrong expectations, but I’m used to mathematical  
functions that, if not specified, return results exact within the  
precision of the number representation used. Any optimization trading  
precision for speed should be documented. I think we agree on that.  
The remaining discussion is purely academic 🙂

Cheers,  
Daniele

---

<div class="post-metadata">

**Author:** ![Daniele\_N](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/74df32/32.png) [@Daniele\_N](https://www.ruby-forum.com/u/Daniele_N)\
**Post date:** [August 14, 2014, 5:32pm UTC](https://www.ruby-forum.com/t/blocks-complex-to-arg-implementation/231529/6 "2014-08-14T17:32:45Z")

</div>

On Thu, Aug 14, 2014 at 9:25 AM, Daniele N. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> > ```
> > > in a few instances (near 0 or near pi/2 or something like that).
> > 
> > ```
> 
> I may have completely wrong expectations, but I’m used to mathematical  
> functions that, if not specified, return results exact within the  
> precision of the number representation used. Any optimization trading  
> precision for speed should be documented. I think we agree on that.  
> The remaining discussion is purely academic 🙂
> 
> Cheers,  
> Daniele

I don’t think that it’s academic at all. We’re dealing with processing  
noisy signals here, often coming at us very quickly. We work in the  
tradeoff space between speed and performance and try to balance them  
well.  
This isn’t like Matlab with double-precision math. In this case, the  
complexity of the atan function is really high. Meanwhile, I just pulled  
up  
my old tests, and the maximum error between fast\_atan2f and atan2f is  
0.00194 radians. I’m curious what application you are using that’s  
requiring that level of precision? And what noiseless environment you  
are  
in where you can make that determination?

As for the documentation: yes, I’m always in favor of adding information  
to  
the documentation to make things more clear.

Tom
