憂鬱な午後のひととき


8月31日_
ETSeminar2008
無事終わった. 一人vs30人なのに最後まで熱かった. いや暑かった(会場が←すんません). 実際問題としては純粋によい公理体系を追求すればいい数学と違って, プログラミングでは目の前にある(泥臭い)コンピュータといかに乖離せずにモデル化するかという部分がつきまとうのでこういう話はなかなか難しいんだろうな.
・↓ちょっとぬか喜びだった. VC8SP1のregexを使っていた. boost::regexで測り直すとboost : jregex = 0.203 : 0.110@P4Dだった. まあでもまだジャンプ最適化とかやりたいところはいろいろある.
w_oさんが「俺の正規表現JITが速いコンテストしたい」って言ってた. 面白そう.
8月30日_
・みながLLのときにわんくま同盟 横浜勉強会 #1へ行ってみる. ここではLLって何? Linuxって何? Macって何?って感じで衝撃を受ける. Windows率めちゃ高し. Cryoliteさんやkinabaさんが触れていたType Erasureとかの話もあってなかなかよかった. 懇親会行きたかったけどまたの機会に.
・せこせことやっていた自分の夏休みの宿題Xbyak版正規表現実装とバグとり間に合わず. 明日alohakunになわけねーよって言いたかったのだが(笑). とりあえず動いたのだけベンチ(せこ).
const char *text = "ajevifjaesd<asdfasdfasd>safasdfasdfiv\
                    afasdfk<aaaaaaa>jasdfasdvslevrjaseivj\
                    fasiajevifjaesd<asdfasdfasd>safasdfas\
                    dfivafasdfk<aaaaaaabjasdfasdvslevrjas\
                    eivjfasijfajafveiabdevifjaesd<asdfasd\
                    fasd>safasdfasdfivafasdfkjasdfasdvsle\
                    vrjaseivjfasijfajafveiabda<aaab>sdfas\
                    dfaweifvasvfas";
const char *re = "<a+?b>";

tr1::regex re(pattern);
tr1::cmatch what;
const int count = 100000;
{
    boost::timer t;
    for (int i = 0; i < count; i++) {
        regex_search(text, textEnd, what, re);
    }
    printf("boost::regex=%.3f\n", t.elapsed());
}

bool ret;
jregex::JRegex re2(pattern);
std::vector<Pair> match;

{
    boost::timer t;
    for (int i = 0; i < count; i++) {
        ret = re2.matchVM(match, text, textEnd);
    }
    printf("vm   jregex=%.3f\n", t.elapsed());
}
{
    boost::timer t;
    for (int i = 0; i < count; i++) {
        ret = re2.matchJIT(match, text, textEnd);
    }
    printf("jit  jregex=%.3f\n", t.elapsed());
}

>boost::regex=1.141
>vm    jregex=1.390
>jit   jregex=0.157
@PentiumD 2.8GHz
役に立たないわけじゃなさそうな感じやけど, そもそもこのベンチ信用できるのかなあ. もうちょい頑張ってみるか.
8月27日_
64bit gccの1ULLはuint64_tとは異なる型になっている. templateの特殊化ではまった. sizeof = 8なんだから同じ意味にしてくれてもよかったと思うんだけど. ちなみに32bit gcc/32bit VC/64bit VCでは同じだった.
ああ, なるほどstdint.hのUINT64_C()を使えということか.
#include <stdio.h>
#include <boost/cstdint.hpp>
#include <iostream>

#ifdef _WIN32
typedef unsigned __int64 uint64_t;
#endif

template<typename T>
void put(T x, const char *str)
{
    std::cout << str << ":" << x << ":"
       << sizeof(x) << std::endl;
}

template<>
void put(uint64_t x, const char *str)
{
    std::cout << "specialized:" << str
        << ":" << x << ":" << sizeof(x) << std::endl;
}

#define PUT(x) put(x, #x)

int main()
{
    PUT(1);
    PUT(2L);
    PUT(3LL);
    PUT(4UL);
    PUT(5ULL);
    PUT(uint64_t(6));
    PUT(boost::uint64_t(7));
}
結果
1:1:4
2L:2:4
3LL:3:8
4UL:4:4
specialized:5ULL:5:8
   5ULL:5:8 ; *** 64bit gccでのみspecializedされない ***
specialized:uint64_t(6):6:8
specialized:boost::uint64_t(7):7:8
8月23日_
problem 28もやってみた. min, maxって何と思ったが方針はQ上関数の常套手段. 面白かった.
分配律からa∧b=(a-b)∧0 + bとしてφ(x):=x∧0とおいて交換則からφ(x)=φ(-x)+xを, 結合則からφ(r)=rφ(1) for r ∈ Q>=0を導き, φ(1)が0ならminに!0(=1)ならmaxになると解いた. いきなりrの存在に言及するよりは多少分かりやすい?
8月22日_
・今日は電車の路線を乗り間違えたり, 会社の最寄り駅を降り過ごしたり, 帰りは人身事故により途中から歩いたりで散々だった.
・kinabaさん経由で実数上の二項演算 * が (a*b)*c = a+b+c を満たすなら * は足し算である
ちょっと面白かった. ちなみに似たような感じの「実数R上の実数値関数fに対してf(x + y) = f(x) + f(y) for all x, y∈R, f(1) = 1 ⇒ f(x) = x?」は高校の数学をはるかに超える難しい問題.
8月18日_
↓これかな(HKLM\SOFTWARE\Microsoft\VCExpress\9.0\Languages\Extensionless Files\). 明日試してみる.
8月15日_
tr1で追加されたregexをVS2008 Express Editionで開くと正しくhppヘッダと認識されて色もつくのにVS2008 Professional Editionで開くと単なるテキストと認識されてしまってる. 不思議だ. どこかレジストリに追加し忘れているのだろうか.
8月14日_
gcc + tr1でこけた理由が分かった. include/c++/4.3.0/tr1_impl/regexを見ると
template<typename _Bi_iter, typename _Allocator,
   typename _Ch_type, typename _Rx_traits>
inline bool
regex_search(_Bi_iter __first, _Bi_iter __last,
     match_results<_Bi_iter, _Allocator>& __m,
     const basic_regex<_Ch_type, _Rx_traits>& __re,
     regex_constants::match_flag_type __flags
     = regex_constants::match_default)
{ return false; }
なんやそれ. あとgccは<regex>でもincludeできるようだ. その場合は名前空間がstd::tr1でなくstdになるのか. このあたり(VCで使えるようになるのは)まだまだ先と思っていたので全然フォローしてなかった.
8月13日_
VS2008 SP1登場
Feature Packから漸く, (expressでも)TR1を正式サポート. shared_ptrやregexを使う手元の簡単なサンプルは無事動いた. ただそのサンプルは(VC, gcc) x (boost, tr1)の4つの組み合わせではgcc + tr1でのみこけた. 何故だろう. TR1 Fixes In VC9 SP1によるとVCのtr1::regexはboost::regexよりも速いらしい. 今度ベンチとってみよう. しかしincludeディレクトリがgccは<tr1/regex>でVCは<regex>か. 同じにして欲しかったなあ.
8月12日_
めもりかくほ
C onlyでわりと規模の大きいときは呼び出し元で確保するとして, 最初にポインタをNULLにして渡すと必要なサイズだけが返ってきて改めてそのサイズを確保して呼び出すというのが一番安全かな. でもその手順を毎回書くのは面倒だから呼び出し先で確保してほしい, しかしライブラリがWindowsのDLLにもなりえるというところまで考えるなら, メモリ確保関数を一緒に渡してそれで確保してもらうというのに(昔は)落ち着いた. 今ならDLLにせずhppで値返ししてまう.
・↓boost::xpressiveならbasic_string決め打ちでない感じもしたが, コンパイル時間の増大と調査時間切れで却下. いつかまた.
8月11日_
boost::regex<charT> でcharT = char, wchar_t以外(たとえばuint32_t))を使おうとするとえらい苦労する. WindowsではBOOST_REGEX_NO_W32を定義しないとコンパイルできなかった(これが直接の原因ではない. 単なる対処療法). Linuxではbuildはできたが実行時にbad_cast例外が発生する. どうしようかな. 内部でbasic_string決め打ちで使われているのが意外と不便だ.
8月6日_
VC2008って
typedef std::complex<double> Complex;

Complex gen(double x)
{
    Complex z(x, x);
    return z * z;
}

double func(double x)
{
    return std::norm(gen(x));
}
程度の値返しついてはNRVOが働いて綺麗に多項式の計算になる(gcc4.3.0よりもいい)んやけど,
std::string gen1(const std::string& in)
{
    return in + "abc";
}

std::string gen2(const std::string& in)
{
    return gen1(in) + "def";
}

std::string gen3(const std::string& in, int x)
{
    return x ? gen1(in) : gen2(in);
}

gen3(in, 0);
にたいしては(RVOがなんらかの足かせになるのか)最後の無条件分岐すら最適化されない(__forceinlineをつけても展開されない). トータルのコピー削減は結構がんばっているとは言え, やはりまだまだstd::stringの値返しは止めた方が無難かなあ.
8月4日_
↓って書いたけど楕円暗号なんて数論のテーマとしては面白くないよな. でもいきなりやるよりは「解析編」とか「幾何編」があって, 読者にバックグラウンドを与えた上で「つなげる」ほうがいいと思うなあ.
8月3日_
『数学ガール/フェルマーの最終定理』(結城浩)
「フェルマーの定理」がどう調理されるのかと思ったら肩すかし. ミルカさんさえにとっても明らかに荷が重すぎた(まあ, 難しいんだから仕方ないんやけど). 群や環が出て, 楕円曲線が出たのに群構造をすっとばしちゃったのはどうかと思った. 数式を一つ一つ丁寧に追っかけていくのが信条であるなら, 初等整数論+αの手頃な題材(たとえば楕円曲線暗号とか)でまとめた方が背伸びなくいけたんじゃないかな. あるいはこれを読んで数学勉強してみようという人がターゲットならそういう人向けの文献を充実させるとか.

御意見は光成滋生<herumi@nifty.com>までお願いします