最新ページ / カテゴリ最新ページ / 1 2 3 4 5 次ページ / page 1 (5)

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

n進数的文字列を数値に変換 [D言語]

std.conv の to で、出来そうで出来ない。
to で出来るのは10進数の変換。

auto a = to!(int)("0xFF"); //NG
auto b = to!(int)("255"); //OK

std.c.stdlib の strto* を使う。

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

トラックバックが壊れてた [D言語]

エンコードされている文字列にエンコードされていない文字列を追加していたのと、
excerpt を 255 文字で切り捨てる処理に問題があった。

//excerpt は string 型で、エンコードされている
if(excerpt.length > 252) excerpt = excerpt[0 .. 252] ~ "...";

excerpt はデコードしてから長さを調べなくてはならない。
excerpt.length は文字数ではないので間違い。

std.utf を使って文字数を計算するようにする。

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

配列の宣言 [D言語]

前置配列宣言

// int の4要素配列 の3要素配列
int[4][3] a;

後置配列宣言

// int の4要素配列 の3要素配列
int a[3][4];

以前(多次元配列にはまる)、
前置配列宣言と後置配列宣言の違いで、引っ掛った。

言語仕様を眺めていたら、
両方の宣言を混ぜて使えるのに気が付いた。

// int の4要素配列 の3要素配列
int[4] a[3];

別名を使うと、1次元の配列っぽく宣言できる。

// int の4要素配列
alias int[4] A;

// 前置配列宣言
A[3] a;

// 後置配列宣言
A b[3];

2009-12-07 Mon

OpenCVのD言語用ポーティング [D言語][OpenCV]

D言語友の会OpenCVのD言語用ポーティングが投稿された。

同じ様な事をしていたので参考になる。

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 のコンストラクタ

どうせなら、クラステンプレートの引数は、
コンストラクタの引数から推論してほしい。

あー
クラステンプレートとコンストラクタテンプレートでは、
意味合いが違うか。

クラステンプレートの場合は、
テンプレート引数ごとに違う型になる。