boostすげえな

boostは噂の通り、熱いですね。ほんとにこれがC++か? と思えるほど。STLを初めて見た時もかなりの衝撃でしたが、boostはその上を行ってます。C++さんはまた遠くに行ってしまったんだね…

そういえばSTLのbitsetはコンパイル時に長さを決めるので扱いづらいなぁという印象を受けたことがあったなぁと思ってboostのbitsetを見てみると、boostには実行時に長さを変えることができるdynamic_bitsetがありました。がんばるなぁ。

試しにboost.pythonを使ってPythonから使えるモジュールにしてみました。

Python 2.5.1 (r251:54863, Oct 30 2007, 13:45:26)
[GCC 4.1.2 20070925 (Red Hat 4.1.2-33)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import bitset
>>> b=bitset.bitset(12)
>>> b
bitset("000000000000")
>>> len(b)
12
>>> dir(b)
['__and__', '__class__', '__delattr__', '__dict__', '__doc__', '__eq__', '__ge__',
 '__getattribute__', '__getitem__', '__gt__', '__hash__', '__iand__', '__ilshift__',
 '__init__', '__instance_size__', '__invert__', '__ior__', '__irshift__', '__isub__',
 '__ixor__', '__le__', '__len__', '__lshift__', '__lt__', '__module__', '__ne__',
 '__new__', '__nonzero__', '__or__', '__reduce__', '__reduce_ex__', '__repr__',
 '__rshift__', '__setattr__', '__setitem__', '__str__', '__sub__', '__weakref__',
 '__xor__', 'any', 'clear', 'count', 'find_first', 'find_next', 'flip',
 'is_proper_subset_of', 'is_subset_of', 'none', 'num_blocks',
 'push_back', 'reset', 'resize', 'swap', 'to_ulong']
>>> b[4]=1
>>> print b
000000010000
>>> b
bitset("000000010000")
>>> b.flip()
>>> b
bitset("111111101111")
>>> b.flip()
>>> b
bitset("000000010000")
>>> b.flip(2)
>>> b
bitset("000000010100")
>>> b[4:9]
bitset("00001")
>>> b[-1]
False
>>> b[:5]
bitset("10100")

普通にto_string()を使ってるのに、バイトオーダの影響か、後ろから表示されてますね。boostもboost.pythonもまだよくわからない部分が多いですが、使えなくもないと思います。b1&b2,b1|b2,b1^b2とか~b1といった演算、あとシフトと引き算、大小比較もboostのものをそのまま使ってやってます。

サイズの変更がb.resize(new_size, true_or_false)、末尾に追加するのがb.push_back(true_or_false)。

ソースは続きに。

#include <iostream>
#include <boost/dynamic_bitset.hpp>
#include <boost/python.hpp>
#include <boost/python/slice.hpp>
#include <bitset>

using namespace boost::python;

typedef boost::dynamic_bitset<> bbset;

void bbset_set(bbset &b, long n, bool val){
  if(n<0) n=b.size()+n;
  b=b.set(n,val);
}
bool bbset_test(bbset &b, long n){
  if(n<0) n=b.size()+n;
  return b.test(n);
}
bbset bbset_get(bbset &b, slice s){
  extract<int> int_start(s.start());
  extract<int> int_stop(s.stop());
  extract<int> int_step(s.step());
  int start=0,stop=-1,step=1;
  // std::cout << s << std::endl;
  if(int_start.check()){ start=int_start(); }
  if(int_stop.check()) { stop=int_stop(); }
  if(int_step.check()) { step=int_step(); }
  if(start<0){ start=b.size()+start; }
  if(stop<0) { stop=b.size()+stop;   }
  bbset ret=bbset((stop-start)/step);
  for(int j=0,i=start; i<stop; j++, i+=step){
    ret[j]=b[i];
  }
  return ret;
}
void bbset_flipa(bbset &b, long n){ b=b.flip(n); }
void bbset_flip(bbset &b){ b=b.flip(); }
void bbset_reseta(bbset &b, long n){ b=b.reset(n); }
void bbset_reset(bbset &b, long n){ b=b.reset(); }
bbset bbset_sub(bbset &b1, bbset &b2){ return b1-b2; }
bbset bbset_and(bbset &b1, bbset &b2){ return b1&b2; }
bbset bbset_or(bbset &b1, bbset &b2){ return b1|b2; }
bbset bbset_xor(bbset &b1, bbset &b2){ return b1^b2; }
bbset bbset_isub(bbset &b1, const bbset &b2){ b1-=b2; return b1; }
bbset bbset_iand(bbset &b1, const bbset &b2){ b1&=b2; return b1; }
bbset bbset_ixor(bbset &b1, const bbset &b2){ b1^=b2; return b1; }
bbset bbset_ior(bbset &b1,  const bbset &b2){ b1|=b2; return b1; }
bbset bbset_ilshift(bbset &b1, long n){ b1<<=n; return b1; }
bbset bbset_irshift(bbset &b1, long n){ b1>>=n; return b1; }
bool bbset_eq(bbset &b1, bbset &b2){ return b1==b2; }
bool bbset_ne(bbset &b1, bbset &b2){ return b1!=b2; }
bool bbset_gt(bbset &b1, bbset &b2){ return b1>b2; }
bool bbset_lt(bbset &b1, bbset &b2){ return b1<b2; }
bool bbset_ge(bbset &b1, bbset &b2){ return b1>=b2; }
bool bbset_le(bbset &b1, bbset &b2){ return b1<=b2; }

std::string bbset_str(bbset &b)
{
  std::string ret;
  to_string(b, ret);
  return ret;
}

std::string bbset_repr(bbset &b)
{
  std::string hd="bitset(\"";
  std::string tl="\")";
  std::string mi;
  to_string(b, mi);
  return hd+mi+tl;
}

BOOST_PYTHON_MODULE(bitset){
  class_<bbset>("bitset", init<long>())
    .def(init<long,unsigned long>())
    .def(init<bbset>())
    .def(init<std::string>())
    .def("count", &bbset::count)
    .def("any", &bbset::any)
    .def("none", &bbset::none)
    .def("flip", &bbset_flipa)
    .def("flip", &bbset_flip)
    .def("reset", &bbset_reseta)
    .def("reset", &bbset_reset)
    .def("swap", &bbset::swap)
    .def("to_ulong", &bbset::to_ulong)
    .def("num_blocks", &bbset::num_blocks)
    .def("resize", &bbset::resize)
    .def("push_back", &bbset::push_back)
    .def("is_subset_of", &bbset::is_subset_of)
    .def("is_proper_subset_of", &bbset::is_proper_subset_of)
    .def("clear", &bbset::clear)
    .def("find_first", &bbset::find_first)
    .def("find_next", &bbset::find_next)
    .def("__invert__", &bbset::operator~)
    .def("__len__", &bbset::size)
    .def("__nonzero__", &bbset::any)
    .def("__setitem__", &bbset_set)
    .def("__getitem__", &bbset_test)
    .def("__getitem__", &bbset_get)
    .def("__str__", &bbset_str)
    .def("__repr__", &bbset_repr)
    .def("__lshift__", &bbset::operator<<)
    .def("__rshift__", &bbset::operator>>)
    .def("__and__", &bbset_and)
    .def("__xor__", &bbset_xor)
    .def("__or__", &bbset_or)
    .def("__sub__", &bbset_sub)
    .def("__iand__", &bbset_iand)
    .def("__ixor__", &bbset_ixor)
    .def("__ior__", &bbset_ior)
    .def("__isub__", &bbset_isub)
    .def("__ilshift__", &bbset_ilshift)
    .def("__irshift__", &bbset_irshift)
    .def("__eq__", &bbset_eq)
    .def("__ne__", &bbset_ne)
    .def("__gt__", &bbset_gt)
    .def("__lt__", &bbset_lt)
    .def("__ge__", &bbset_ge)
    .def("__le__", &bbset_le)
  ;
}
// g++ -I/usr/include/python2.5 -shared -o bitset.so bitset.C -lboost_python -fPIC

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です