01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
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); } }
動いた。
■ 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分