[Accumulators] Passing construction arguments to dependent statistics

Given recent discussion on Time Series and Accumulators, I thought I would have a go at implementing a FIR filter for Accumulators, and have run into a problem. I decided to do this in two parts; first create a (reusable) delay statistic (similar to tail) that provides a history buffer for the signal and then create the filter (similar to tail_variate) , that will depend on the delay buffer. I have created the delay buffer with a length determined by a cache_size argument. This works well. I am now creating the filter, which has a "coefficents" argument to set the filter coefficients. I would like to pass the size of the coefficients list as the cache_size argument to the underlying delay buffer. Is this possible?

Hugo Duncan wrote:
Given recent discussion on Time Series and Accumulators, I thought I would have a go at implementing a FIR filter for Accumulators, and have run into a problem.
I decided to do this in two parts; first create a (reusable) delay statistic (similar to tail) that provides a history buffer for the signal and then create the filter (similar to tail_variate) , that will depend on the delay buffer.
I have created the delay buffer with a length determined by a cache_size argument. This works well.
I am now creating the filter, which has a "coefficents" argument to set the filter coefficients. I would like to pass the size of the coefficients list as the cache_size argument to the underlying delay buffer.
Is this possible?
Certainly. You can use Boost.Parameter to define a new keyword: BOOST_PARAMETER_NAME(coefficients) The accumulator_set has constructors that take named parameters and builds and argument pack. accumulator_set<... > acc( ..., coefficients = 5, ...); The resulting argument pack is passed as the constructor parameter to all the accumulators in the set. Your accumulator can then extract the coefficients argument from the pack with "args[coefficients]". HTH, -- Eric Niebler Boost Consulting www.boost-consulting.com The Astoria Seminar ==> http://www.astoriaseminar.com

The resulting argument pack is passed as the constructor parameter to all the accumulators in the set. Your accumulator can then extract the coefficients argument from the pack with "args[coefficients]".
Done this, but I want to pass an array of values to coefficients, ie it looks like, eg: array<double,5> coeffs={0.1,0.2,0.1}; accumulator_set<... > acc( .., coefficients = coeffs, ...); So far so good. My filter depends on the delay buffer I have defined which has the cache_size constructor argument. Since I am specifying the list of coefficients, I want the cache_size to be set to the number of elements in my coefficient list, with out having to specify it, ie without having to write: array<double,5> coeffs={0.1,0.2,0.1}; accumulator_set<... > acc( .., coefficients = coeffs, cache_size=5...); Not sure if this is possible through boost::Parameters (first time I have seen this used, BTW, I'm impressed), or if I need to have the filter access the delay post construction, or if it is just not possible.

Hugo Duncan wrote:
The resulting argument pack is passed as the constructor parameter to all the accumulators in the set. Your accumulator can then extract the coefficients argument from the pack with "args[coefficients]".
Done this, but I want to pass an array of values to coefficients, ie it looks like, eg:
array<double,5> coeffs={0.1,0.2,0.1}; accumulator_set<... > acc( .., coefficients = coeffs, ...);
So far so good.
My filter depends on the delay buffer I have defined which has the cache_size constructor argument. Since I am specifying the list of coefficients, I want the cache_size to be set to the number of elements in my coefficient list, with out having to specify it, ie without having to write:
array<double,5> coeffs={0.1,0.2,0.1}; accumulator_set<... > acc( .., coefficients = coeffs, cache_size=5...);
Not sure if this is possible through boost::Parameters (first time I have seen this used, BTW, I'm impressed), or if I need to have the filter access the delay post construction, or if it is just not possible.
Let me see if I understand. You want the delay buffer to use the cache_size parameter if it is specified, and if not, check to see if the coefficients parameter is specified, and if so, use the size of the coefficients array. This is possible. In your delay buffer constructor, you can calculate the cache size as: struct must_specify_cache_size_or_coefficients {}; ... template<class Args> delay_buffer_impl(Args const &args) : cache_size_( args[delay_buffer::cache_size | boost::size( args[coefficients | must_specify_cache_size_or_coefficients() ] ) ] ) {} That's not tested -- it's just an idea. -- Eric Niebler Boost Consulting www.boost-consulting.com The Astoria Seminar ==> http://www.astoriaseminar.com

The resulting argument pack is passed as the constructor parameter to all the accumulators in the set. Your accumulator can then extract the coefficients argument from the pack with "args[coefficients]".
My filter depends on the delay buffer I have defined which has the cache_size constructor argument. Since I am specifying the list of coefficients, I want the cache_size to be set to the number of elements in my coefficient list, with out having to specify it, ie without having to write:
array<double,5> coeffs={0.1,0.2,0.1}; accumulator_set<... > acc( .., coefficients = coeffs, cache_size=5...);
Let me see if I understand. You want the delay buffer to use the cache_size parameter if it is specified, and if not, check to see if the coefficients parameter is specified, and if so, use the size of the coefficients array. This is possible.
[cut proposed solution] Thanks Eric, that would probably work (as long as I define the coefficients named paramter seperately from the filter or the delay). Ideally, though, I was looking for a solution that allowed me to reuse the delay buffer without modifying it. That way it could be used as a lower layer for any algorithm that needed recent time history. Maybe I am being over ambitious...

Hugo Duncan wrote:
Let me see if I understand. You want the delay buffer to use the cache_size parameter if it is specified, and if not, check to see if the coefficients parameter is specified, and if so, use the size of the coefficients array. This is possible.
[cut proposed solution]
Thanks Eric, that would probably work (as long as I define the coefficients named paramter seperately from the filter or the delay).
Ideally, though, I was looking for a solution that allowed me to reuse the delay buffer without modifying it. That way it could be used as a lower layer for any algorithm that needed recent time history. Maybe I am being over ambitious...
The coupling of the cache_size and the coefficients parameters has to be expressed in code somewhere. Where do you suggest? -- Eric Niebler Boost Consulting www.boost-consulting.com The Astoria Seminar ==> http://www.astoriaseminar.com

Ideally, though, I was looking for a solution that allowed me to reuse the delay buffer without modifying it. That way it could be used as a lower layer for any algorithm that needed recent time history. Maybe I am being over ambitious...
The coupling of the cache_size and the coefficients parameters has to be expressed in code somewhere. Where do you suggest?
It would be nice to do it in the filter code. The coefficents parameter is a parameter of the filter after all, and the use of the delay can be looked at as an implementation detail. If the filter constructor (body) could access the delay buffer, then the delay buffer could expose a method to allow resizing. Is that possible?

Hugo Duncan wrote:
Ideally, though, I was looking for a solution that allowed me to reuse the delay buffer without modifying it. That way it could be used as a lower layer for any algorithm that needed recent time history. Maybe I am being over ambitious... The coupling of the cache_size and the coefficients parameters has to be expressed in code somewhere. Where do you suggest?
It would be nice to do it in the filter code. The coefficents parameter is a parameter of the filter after all, and the use of the delay can be looked at as an implementation detail. If the filter constructor (body) could access the delay buffer, then the delay buffer could expose a method to allow resizing. Is that possible?
Ah, ok. Yes, that's possible. In the version you have, that would be done with a post-constructor. In the post-review version (which I haven't made available yet), post-constructors are dead, accumulators within the set are guaranteed to be constructed only after the accumulators on which they depend are constructed, and the entire accumulator_set is available in the argument pack. You'd basically do something like: template<class Args> filter_impl(Args const &args) : ... { // filter depends on delay_buffer, so delay_buffer is // guaranteed to be constructed already. find_accumulator<tag::delay_buffer>(args[accumulator]). resize(boost::size(args[coefficients])); } I'll try to package up the latest version of accumulators Real Soon. If you can't wait, just put the same code in a member function called post_construct and it should do the right thing. Either way, you'll need to write your delay_buffer_impl so that it works when cache_size is not specified. -- Eric Niebler Boost Consulting www.boost-consulting.com The Astoria Seminar ==> http://www.astoriaseminar.com

Ah, ok. Yes, that's possible.
I have even found it in the docs, now I know what I'm looking for :-) Thanks for your help. When I have something working I'll upload it to the vault, if you are interested...

When I have something working I'll upload it to the vault
OK, its there in Math-Numerics as accumulators_filters.tgz There are the headers, and simple unit tests. No docs. I had to do a little const_cast'ing to use find_accumulator.

Hugo Duncan wrote:
When I have something working I'll upload it to the vault
OK, its there in Math-Numerics as accumulators_filters.tgz
Cool. And for those of us who aren't familiar with FIR filters (like myself), http://en.wikipedia.org/wiki/Finite_impulse_response.
There are the headers, and simple unit tests. No docs.
Docs would be very nice.
I had to do a little const_cast'ing to use find_accumulator.
Sorry 'bout that. Just fixed in my local repository. -- Eric Niebler Boost Consulting www.boost-consulting.com The Astoria Seminar ==> http://www.astoriaseminar.com
participants (2)
-
Eric Niebler
-
Hugo Duncan