boost 的 array 与 accumulators

boost.array 提供的是对数组的封装,一般写法如下

#include <boost/array.hpp>
#include <boost/lambda/lambda.hpp>
#include <algorithm>
#include <iterator>
#include <iostream>

int
main (int, char**) {
  boost::array<int, 5> a = {1, 3, 6, 2, 9} ;
  std::copy (a.begin (), a.end (),
             std::ostream_iterator<int> (std::cout, ", ")) ;
  std::cout << std::endl ;
  return 0 ;
}

同时还支持 operator[] 和 at 等常见操作。类似还有一个对多维数组的封装 boost.multi_array,使用起来先 通过 multi_array 模板确定类型和维数,如 multi_array<double, 3>,然后通过构造函数确定 array 每维的大小,如 multi_array<double, 3> (boost::extents<2, 3, 4>) 产生一个 2\times 3 \times 4 的数组。之后可以用类似 [0][1][0] 这种访问对应的元素。也支持动态的 resize。

boost.accumulators 提供了一个收集 accumulative information 的机制,最常见的无外于一些统计量(和、均值、高阶矩)。从使用者的角度来说,主要记住 accumulator_set 这个模板,其参数依次是数据类型(如 double),对应的 accumulators(如 boost::accumulators::stats<…>,比如 tag::mean 等),这个东西是个 functor,我们通过 operator() 将数据导入,最后通过 boost::accumulator::mean 等方法获得对应的值,下面是一个简单的例子

#include <boost/accumulators/accumulators.hpp>
#include <boost/accumulators/statistics/stats.hpp>
#include <boost/accumulators/statistics/mean.hpp>
#include <boost/accumulators/statistics/moment.hpp>
#include <boost/lexical_cast.hpp>

namespace acc = boost::accumulators ;

int
main (int argc, char* argv[]) {
  acc::accumulator_set<double,
                       acc::stats<acc::tag::mean,
                                  acc::tag::moment<2> > > s ;
  for (int i = 1 ; i < argc ; ++ i)
    s (boost::lexical_cast<double> (argv[i])) ;

  std::cout << "mean: " << acc::mean (s) << '\n'
            << "order-2 moment:" << acc::moment<2> (s)
            << '\n' ;
  return 0 ;
}

boost.accumulators 提供了丰富的统计相关的 accumulator 可以计算各种(样本)统计量,如

  • 计数(count)
  • 协方差(covariance)
  • 密度(density)
  • 均值误差(error_of<mean>)
  • 丰度(kurtosis),斜度(skewness)
  • 矩(moment):均值(mean),中位数(median),最大最小(max、min),
  • 对应加权版本

如果我们希望扩展,一般需要三个步骤,下面是文档里面的对应例子。第一步是实现具体的 accumulator,

#include <boost/accumulators/framework/accumulator_base.hpp>
#include <boost/accumulators/framework/parameters/sample.hpp>

namespace boost {                           // Putting your accumulators in the
namespace accumulators {                    // impl namespace has some
namespace impl {                            // advantages. See below.

template<typename Sample>
struct sum_accumulator                      // All accumulators should inherit from
  : accumulator_base                        // accumulator_base.
{
    typedef Sample result_type;             // The type returned by result() below.

    template<typename Args>                 // The constructor takes an argument pack.
    sum_accumulator(Args const & args)
      : sum(args[sample | Sample()])        // Maybe there is an initial value in the
    {                                       // argument pack. ('sample' is defined in
    }                                       // sample.hpp, included above.)

    template<typename Args>                 // The accumulate function is the function
    void operator ()(Args const & args)     // call operator, and it also accepts an
    {                                       // argument pack.
        this->sum += args[sample];
    }

    result_type result(dont_care) const     // The result function will also be passed
    {                                       // an argument pack, but we don't use it here,
        return this->sum;                   // so we use "dont_care" as the argument type.
    }
private:
    Sample sum;
};

}}}

第二步是提供对应的 tag 并给出依赖的其他 accumulator,

namespace boost { namespace accumulators { namespace tag {

struct mean                         // Features should inherit from
  : depends_on< count, sum >        // depends_on<> to specify dependencies
{
    // Define a nested typedef called 'impl' that specifies which
    // accumulator implements this feature.
    typedef accumulators::impl::mean_accumulator< mpl::_1 > impl;
};

}}}

第三步是提供一个 extractor 用来把结果拿出来。

namespace boost {
namespace accumulators {                // By convention, we put extractors
namespace extract {                     // in the 'extract' namespace

extractor< tag::mean > const mean = {}; // Simply define our extractor with
                                        // our feature tag, like this.
}
using extract::mean;                    // Pull the extractor into the
                                        // enclosing namespace.
}}

比较好奇 median 的实现,难道真的是两个 heap 么?

——————
And Abraham took Ishmael his son, and all that were born in his house, and all that were bought with his money, every male among the men of Abraham’s house; and circumcised the flesh of their foreskin in the selfsame day, as God had said to him.

Advertisements
boost 的 array 与 accumulators

一个有关“boost 的 array 与 accumulators”的想法

发表评论

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / 更改 )

Twitter picture

You are commenting using your Twitter account. Log Out / 更改 )

Facebook photo

You are commenting using your Facebook account. Log Out / 更改 )

Google+ photo

You are commenting using your Google+ account. Log Out / 更改 )

Connecting to %s