前の月 / 次の月 / 最新

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分

過去ログ

2011 : 01 02 03 04 05 06 07 08 09 10 11 12
2010 : 01 02 03 04 05 06 07 08 09 10 11 12
2009 : 01 02 03 04 05 06 07 08 09 10 11 12
2008 : 01 02 03 04 05 06 07 08 09 10 11 12
2007 : 01 02 03 04 05 06 07 08 09 10 11 12