2011-06-25 Sat
■ auto-complete.elでD言語を補完してみた [emacs][D言語]
auto-complete.elでD言語を保管するために、
auto-complete-d.elを書いてみた。
現在できること。
キーワードの補完ができる。
モジュール名の補完ができる。
使い方
(add-hook 'd-mode-hook (lambda () (ac-d-mode-setup)))
2010-03-13 Sat
■ chunk をデコード [D言語]
2009-08-21-1 のコードを,
std.regex を使って書き直し。
import std.string; import std.regex; import std.c.stdlib; import core.stdc.errno; byte[] decodeChunked(byte[] src) { string entityBody; char* endptr; auto reg = regex(q"{[\da-fA-F]+[^\r\n]*\r\n}"); //16進 auto m = match(cast(char[])src,reg); errno = 0; auto chunkSize = strtol(m.hit.toStringz,&endptr,16); if (errno == ERANGE){} if (m.hit.toStringz == endptr) {} while(chunkSize > 0) { entityBody ~= m.post[0 .. chunkSize]; m = match(m.post[chunkSize .. $],reg); errno = 0; chunkSize = strtol(m.hit.toStringz,&endptr,16); if (errno == ERANGE){} if (m.hit.toStringz == endptr) {} } return entityBody; }
2010-03-13 Sat
■ stdtol の戻り値は long じゃ無くて int [D言語]
http://www.kmonos.net/alang/d/2.0/phobos/std_c_stdlib.html
long strtol(in char*, char**, int);
uint strtoul(in char*, char**, int);
と記述されてた。
なんか strtol の戻り値が変。
core.stdc.stdlibを見ると、
strtol の戻り値が c_long 型になっていた。
core.stdc.configを見ると、
windows 上だと c_long 型は、
int の alias になっていた。
英語のドキュメントを見る。
http://www.digitalmars.com/d/2.0/phobos/std_c_stdlib.html
…
1.0のドキュメントを見る。
http://www.digitalmars.com/d/1.0/phobos/std_c_stdlib.html
long になっている。
2010-03-06 Sat
2010-03-05 Fri
■ std.regex での正規表現にはWYSIWYG文字列を使う [D言語]
std.regex での正規表現で普通の文字列を使うと、
regex 関数に渡す \ の数とマッチされる文字列の \ の数が、
一致しないので、しんどい。
auto r2 = regex("\"\\\""); //\"\\\" にマッチしないで \"\"にマッチ auto r3 = regex("\"\\\\\""); //\"\\\" にマッチ
WYSIWYG文字列つかうとエスケープが楽になる。
auto r1 = regex(`"\\"`); //\"\\\" にマッチ auto r2 = regex(r"`\\`"); //\`\\` にマッチ
この場合 " と ` が混在する \"\\` にマッチ正規表現が書けない。
そこで、" と ` が混在できるデリミタ指定文字列がおすすめ。
auto r1 = regex(q"{"\\`}"); //\"\\` にマッチ
2010-02-23 Tue
■ if文の条件内で宣言したい [D言語]
宣言が構造体の変数だとどう書く?
import std.stdio; struct S { int value; } void main() { if(auto s = S(10)) //Error: expression S(10) of type S does not have a boolean value { writeln(s.value); } }
こういう書き方ではないようだ。
クラスの場合はどうだろう。
import std.stdio; class C { int value; this(int value) { this.value = value; } } void main() { if(auto c = new C(10)) { writeln(c.value); } }
動いた。
構造体を new してみる。
import std.stdio; struct S { int value; this(int value) { this.value = value; } } void main() { if(auto s = new S(10)) { writeln(s.value); } }
動いた。
2010-02-23 Tue
■ D言語で気軽に時間測定がしたい [D言語]
C++ で気軽に時間測定がしたい
D言語で書いてみる。
クラスで書いてみた。
import std.stdio; import std.format; import std.utf; import std.perf; scope class Benchmark(T=PerformanceCounter) { alias T.interval_t interval_t; T timer; char[] msg; this(...) { void putc(dchar c) { std.utf.encode(msg, c); } std.format.doFormat(&putc, _arguments, _argptr); timer = new T; timer.start; } ~this() { timer.stop; interval_t elapsedMsec = timer.milliseconds; stderr.writefln("%s: %s msec", msg, elapsedMsec); } }
スコープ変数にしてデストラクタが動くようにする。
void main() { { int i = 10_000_000 scope benchmark = Benchmark!()("sleep(%d)",i); Thread.sleep(i); } }
sleep(10000000): 1000 msec
構造体で書いてみる。
import std.stdio; import std.format; import std.utf; import std.perf; struct Benchmark(T=PerformanceCounter) { alias T.interval_t interval_t; T timer; char[] msg; this(...) { void putc(dchar c) { std.utf.encode(msg, c); } std.format.doFormat(&putc, _arguments, _argptr); timer = new T; timer.start; } ~this() { timer.stop; interval_t elapsedMsec = timer.milliseconds; stderr.writefln("%s: %s msec", msg, elapsedMsec); } }
void main() { { int i = 10_000_000 auto benchmark = Benchmark!()("sleep(%d)",i); Thread.sleep(i); } }
sleep(10000000): 1000 msec
これだと入れ子のたびに名前をつけなくてはいけない。
だから if 文の条件中に宣言しているのか?
結構難しい。
delegate を使って書いてみる。
import std.stdio; import std.format; import std.utf; import std.perf; void benchmark(T=PerformanceCounter)(void delegate() dg,...) { alias T.interval_t interval_t; T timer = new T; char[] msg; void putc(dchar c) { std.utf.encode(msg, c); } std.format.doFormat(&putc, _arguments, _argptr); timer.start; dg(); timer.stop; interval_t elapsedMsec = timer.milliseconds; stderr.writefln("%s: %s msec", msg, elapsedMsec); }
void main() { for(int i = 0; i <= 3; i++) { benchmark({ Thread.sleep( i * 10_000_000 ); },"sleep(%d)", i * 10_000_000 ); } }
sleep(0): 11 msec sleep(10000000): 999 msec sleep(20000000): 2004 msec sleep(30000000): 3002 msec
けっこうそれっぽい?
2010-02-04 Thu
■ Pentium III 800 MHz はちょっと遅い: [D言語]
ブルートフォースで暗号化されている zip の
キーを捜すコードを書いた。
オプションなしでコンパイルしたものを、
Pentium III 800 MHz で実行してみた。
40万キー/秒 の処理速度だった。
2^32 個の範囲だと 3時間かかる。
2^96 個の範囲だと 6.31318894 × 10^15 年
import std.stdio; import std.perf; import std.random; import std.zlib; uint key0,key1,key2; uint[] makeCRCTable() { uint[] table; uint r; for (int i = 0; i < 256; i++) { r = i; for (int j = 0; j < 8; j++) { if (r & 1) { r = (r >> 1) ^ 0xEDB88320U; }else{ r >>= 1; } } table ~= r; } return table; } invariant uint[] crctable = makeCRCTable(); uint crc32(uint crc, ubyte b) { return ((crc >> 8) ^ crctable[(crc & 0xFF) ^ b]); } void initializeKeys(in ubyte[] password) { key0 = 305419896; key1 = 591751049; key2 = 878082192; foreach(c;password) updateKeys(c); } void updateKeys(in ubyte c) { key0 = crc32(key0,c); key1 += key0 & 0xff; key1 = key1 * 134775813 + 1; key2 = crc32(key2,key1 >> 24); } ubyte decryptByte() { uint temp = key2 | 2; return (((temp * (temp ^ 1)) >> 8) & 0xFF); } ubyte[] encrypt(in ubyte[] password, in ubyte[] planetext, in uint crc) { initializeKeys(password); Random gen; ubyte[12] header; foreach(ref c;header[0 .. 10]) { gen.seed(unpredictableSeed); c = cast(ubyte)gen.front; } header[11] = crc >> 24 & 0xff; ubyte[] ciphertext; foreach(c;header ~ planetext) { ubyte temp = decryptByte(); updateKeys(c); ciphertext ~= c ^ temp; } return ciphertext; } bool check(in ubyte[] ciphertext, in uint crc) in { assert(ciphertext.length > 12); } body { ubyte[12] header = ciphertext[0 .. 12]; for(int i = 0;i<12;i++) { ubyte temp = header[i] ^ decryptByte(); updateKeys(temp); header[i] = temp; } if(header[11] != (crc >> 24)) return false; ubyte[] planetext; foreach(c;ciphertext[12 .. $]) { ubyte temp = c ^ decryptByte(); updateKeys(temp); planetext ~= temp; } if(std.zlib.crc32(0,planetext) != crc) return false; return true; } void main() { ubyte[] planetext = cast(ubyte[])("Hello world!!"); uint crc = std.zlib.crc32(0,planetext); ubyte[] password = cast(ubyte[])("password"); ubyte[] ciphertext = encrypt(password,planetext,crc); //initializeKeys(password); 0x5ff8707d 0xba789085 0xea9b4e4d //writefln("key2 = %08x key1 = %08x key0 = %08x", key2, key1, key0); alias PerformanceCounter.interval_t interval_t; auto timer = new PerformanceCounter; timer.start(); for(ulong i = 0xE92442F3; i < 0x100000000U; i++) // 2400万件 ぐらい { key2 = 0x5ff8707d; key1 = 0xba789085; key0 = cast(uint)i; if(check(ciphertext,crc)) break; } timer.stop(); interval_t elapsedMsec = timer.milliseconds; writefln("Time elapsed: %s msec", elapsedMsec); }
-O -inline つけてコンパイルしたら処理時間が半分になった。
半分になっても終わりそうも無い。
Opteron 246 x2 で192万キー/秒か
2^32 個の範囲だと 37分
2010-01-20 Wed
■ UTF-8 の文字数を求める [D言語]
以下のコードで求まる
import std.stdio; import std.utf; void main() { string s = "あいうえお"; //UTF-8 な文字列 size_t count = toUCSindex(s,s.length); writeln(count); //文字数は 5 }
逆に任意の文字位置からバイト位置を求めるには以下のコード。
import std.stdio; import std.utf; void main() { string s = "あいうえお"; //UTF-8 な文字列 size_t index = toUTFindex(s,3);//3文字目の位置 writeln(index); }
2010-01-20 Wed
2010-01-19 Tue
■ 要素が構造体の連想配列が作れない? [D言語]
javascript 見たいな、
opDispatch と Variant を使った、
任意の名前の任意の値を格納できるクラスを作ろうとした。
で、 Variant を要素に持つ連想配列を作って、
dmd 2.039 でコンパイルしたら dmd がこけた。
import std.stdio; import std.variant; void main() { Variant[string] va; writeln(va.length); //Assertion failure: 'impl' on line 3882 in file 'mtype.c' }
ただの構造体でもやってみたら、
要素が構造体の連想配列が作れた。
import std.stdio; struct S{} void main() { S[string] sa; writeln(sa.length); //OK }
import std.variant を追加してみる。
import std.stdio; import std.variant; struct S{} void main() { S[string] sa; writeln(sa.length); //Assertion failure: 'impl' on line 3882 in file 'mtype.c' }
えー
std.variant をインポートすると、要素が構造体の連想配列が作れない?
import std.variant assoc array Issue で検索
これっぽい?
digitalmars.D - Variant[string] associative array ... fail?`
Issue 2451 - Adding structs that use opAssign or postblit to an AA is broken
2010-10-20 追記
std.variantをimportするだけでコンパイルエラー - はてなかよっ!
Issue 3552 - ICE(mtype.c): declaring a variable called 'AssociativeArray' then using an AA.
なるほど、 AssociativeArray って名前がだめなのか
import std.stdio; struct S{} void main() { int AssociativeArray; S[string] sa; writeln(sa.length); //Assertion failure: 'impl' on line 3882 in file 'mtype.c' }
2009-12-10 Thu
2009-12-07 Mon
2009-11-26 Thu
■ OpenCV の記事のサンプルがコンパイルできるようになった [D言語][OpenCV]
OpenCV の記事のサンプルが動く程度に変換した。
- cv.d
- cvtypes.d
- cxcore.d
- cxtypes.d
- highgui.d
OpenCVで学ぶ画像認識:第3回 オブジェクト検出してみよう|gihyo.jp … 技術評論社
module sample; pragma(lib,"cv200.lib"); pragma(lib,"cxcore200.lib"); pragma(lib,"highgui200.lib"); private import opencv.c.cxcore; private import opencv.c.highgui; private import opencv.c.cvtypes; private import opencv.c.cv; private import std.string; void main() { /* 画像のロード */ string imgfile = "photo.jpg"; IplImage* image = cvLoadImage(toStringz(imgfile),1); /* 正面顔検出器のロード */ CvHaarClassifierCascade* cascade = cast(CvHaarClassifierCascade*)cvLoad( "haarcascade_frontalface_default.xml" ); CvMemStorage* storage = cvCreateMemStorage(0); CvSeq* faces; /* 顔検出 */ faces = cvHaarDetectObjects(image,cascade,storage); /* 顔領域の描画 */ for(int i = 0;i < faces.total; i++) { /* extract the rectanlges only */ CvRect face_rect = *cast(CvRect*)cvGetSeqElem(faces,i); cvRectangle(image,cvPoint(face_rect.x,face_rect.y), cvPoint((face_rect.x+face_rect.width), (face_rect.y+face_rect.height)), CV_RGB(255,0,0),3); } /* 画像の表示 */ cvReleaseMemStorage(&storage); cvNamedWindow("face_detect",0); cvShowImage("face_detect",image); cvWaitKey(0); cvReleaseHaarClassifierCascade(&cascade); cvReleaseImage(&image); }
2009-11-24 Tue
■ OpenCV のサンプルがコンパイルできるようになった [D言語][OpenCV]
OpenCV のサンプルが動く程度に変換した。
- cxcore.d
- cxtypes.d
- highgui.d
トラックバーの利用 cvCreateTrackbar, cvGetTrackbarPos, cvSetTrackbarPos
module sample; pragma(lib,"highgui200.lib"); pragma(lib,"cxcore200.lib"); import opencv.c.highgui; import opencv.c.cxtypes; import opencv.c.cxcore; import std.conv; import std.string; CvFont font; IplImage* img; void main() { // (1)画像領域を確保し,初期化する img = cvCreateImage (cvSize (400, 200), IPL_DEPTH_8U, 3); cvZero (img); cvInitFont (&font, CV_FONT_HERSHEY_DUPLEX, 1.0, 1.0); // (2)ウィンドウ,およびトラックバーを作成する cvNamedWindow("Image",CV_WINDOW_AUTOSIZE); cvCreateTrackbar ("Trackbar1", "Image", null, 100, &on_trackbar1); cvCreateTrackbar ("Trackbar2", "Image", null, 100, &on_trackbar2); cvShowImage ("Image", img); cvWaitKey(0); cvDestroyWindow("Image"); cvReleaseImage (&img); } extern(C) void on_trackbar1(int val) { // (3)トラックバー2を,トラックバー1に同期させる cvSetTrackbarPos ("Trackbar2", "Image".ptr, val); // (4)トラックバー1の値を描画する cvRectangle (img, cvPoint (0, 0), cvPoint (400, 50), cvScalar (0), CV_FILLED, 8, 0); cvPutText (img, toStringz(to!(string)(val)), cvPoint (15, 30), &font, CV_RGB (0, 200, 100)); cvShowImage ("Image", img); } extern(C) void on_trackbar2(int val) { int pos1, pos2; // (5)トラックバー2の移動範囲を,トラックバー1の値±20に限定する pos1 = cvGetTrackbarPos ("Trackbar1", "Image"); if (pos1 > val) pos2 = pos1 - 20 < val ? val : pos1 - 20; else pos2 = pos1 + 20 > val ? val : pos1 + 20; cvSetTrackbarPos ("Trackbar2", "Image", pos2); // (6)トラックバー2の値を描画する cvRectangle (img, cvPoint (0, 50), cvPoint (400, 100), cvScalar (0), CV_FILLED); cvPutText (img,toStringz(to!(string)(pos2)), cvPoint (15, 80), &font, CV_RGB (200, 200, 0)); cvShowImage ("Image", img); }
2009-11-23 Mon
■ そういう方法もあるのか [D言語]
dsource.org の bindings を眺めてびっくりした。
OpenAL と OpenGL では、
static this で dll をロードしていた。
OpenCV のヘッダを変換している途中で、
この方法を見ちゃうと、もにょもにょする。
std.loader のドキュメントって載っていない。
D言語研究には std.loader のページがあった。
2009-11-20 Fri
■ 暗黙の型推論が駄目なとき [D言語][OpenCV]
OpenCV のヘッダを変換しているときに
暗黙の型推論を使うとエラーに遭遇した。
こいうヘッダのとき、
#define FOO point( 0, 0 ) typedef struct Point { int x,y; } Point; Point point(int x, int y) { Point p; p.x = x; p.y = y; return p; }
暗黙の型推論を期待して
const FOO = point( 0, 0 ); //FOO は Point 型 sruct Point { int x; int y; } Point point(int x, int y) { Point p; p.x = x; p.y = y; return p; }
こう書くと、
Error: forward reference to point
これを、
const Point FOO = point( 0, 0 );
と型を明示する用にすると回避できた。
2009-11-18 Wed
■ highgui を使ってみる [D言語][OpenCV]
OpenCV をビルドできたかな?
D言語から OpenCV を呼んでみる。
highgui200.lib を coffimplib で変換
highgui200.dll と cxcore200.dll にパスを通す。
以下のソースを作成
module test; pragma(lib,"highgui200.lib"); extern(C){ const CV_WINDOW_AUTOSIZE = 1; int cvNamedWindow(char* name,int flags); void cvDestroyWindow(char* name); int cvWaitKey(int delay); } void main() { cvNamedWindow(cast(char*)"Window".ptr,CV_WINDOW_AUTOSIZE); cvWaitKey(0); cvDestroyWindow(cast(char*)"Window".ptr); }
で、ウインドウが表示された。
リンクするライブラリはデバッグとリリースで
別のライブラリにするべきだろうか?
debug{ pragma(lib,"highgui200d.lib"); }else{ pragma(lib,"highgui200.lib"); }
2009-11-15 Sun
■ OpenCVをダウンロードしてきた [D言語][OpenCV]
インストール
OpenCV Installation Guideを読む
CMakeってのが必要
OpenCV2.0.0をビルドするを読む
ビルド
2009-11-13 Fri
■ クラステンプレートとコンストラクタテンプレート [D言語]
D言語にはコンストラクタテンプレートがない。
string wstring dstring 版の
3つのコンストラクタをもつクラス。
class Foo { this(string c){...} this(wstring w){...} this(dstring d){...} }
関数テンプレートのように定義してみる。
class Foo { this(T)(T s){...} }
auto a = new Foo("bar"w);// Error: no constructor for Foo
ドキュメントに載っている通りエラーになる。
かわりに、
クラステンプレートを使ってみる。
class Foo(T) { this(T s){...} }
auto foo = new Foo!(wstring)("bar"w);//wstring 版の Foo のコンストラクタ
どうせなら、クラステンプレートの引数は、
コンストラクタの引数から推論してほしい。
あー
クラステンプレートとコンストラクタテンプレートでは、
意味合いが違うか。
クラステンプレートの場合は、
テンプレート引数ごとに違う型になる。