パスワードを忘れた? アカウント作成
191248 journal

cheekcatの日記: GIMP2.8 はシングルウィンドウモードを搭載 30

日記 by cheekcat

ars technicaの記事によると、画像編集ソフトとして名高いGIMPの次のメジャーリリースであるGIMP2.8にはシングルウィンドウモードが搭載されるようだ。
これはその名のとおり、あのGIMPの多く開いていたウィンドウが一つにまとまるという機能。個々のパネルの移動・リサイズができなかったり、複数の画像を開いていてタイトルバーの「×ボタン」を押しても一つの画像が閉じられるだけ、などまだ問題は多いようではある。

そんなGIMP2.8のリリースは今のところ2010年12月に予定されているらしい。まだまだ先のことだが楽しみですね。

54177 journal

cheekcatの日記: Google さんがおかしくなったので

日記 by cheekcat

こんな filter を書いて

(defun w3m-filter-google-remove-interstitial (url)
  (goto-char (point-min))
  (while (re-search-forward "href=\"/interstitial\\?url=\\([^\"]*\\)" nil t)
    (replace-match (concat "href=\"" (w3m-url-decode-string url)))))
 
(add-to-list 'w3m-filter-rules
         '("^http://[^/]*google\\.\\(com\\|co\\.jp\\)"
           w3m-filter-google-remove-interstitial))

さて、これでもうちゃんとぐぐれる!
と、ぐぐってみたら直ってた…

416308 journal

cheekcatの日記: FSF からステッカーもらった

日記 by cheekcat

Emacs あたりであれこれやってたら FSF からお手紙来ることになって今日届いた。
それで、多分 GPLv3 のステッカーも入ってたのだけど、どこに貼ろうかな。 ノートパソコンか筆箱か。

36468 journal

cheekcatの日記: 埋め込みスクリプト言語

日記 by cheekcat

今度作るプログラムをスクリプト言語で拡張できるようにしたいなぁ、と考えた。

- Windows でも動く
- 拡張部分の実装が簡単になる
- C/C++ と協調できる

あたりを条件に考えてみる。

Perl はらくだ本の一巻に C から呼び出す方法が載っていたが、 Windows でな
にが必要になるかわからない。

Ruby はこんなサイトもあるけれど公式でしっかりとはしてなさそう。 C/C++
との協調も悪そう…。
http://takahr.dhis.portside.net/cgi-bin/rwiki.cgi?cmd=view;name=r.out

Python は公式ドキュメントに C/C++ からの呼出し方法が書いてあるし
py2exe やら PyInstaller やらで Windows 対応もしっかりできそう。 Python
モジュール作った時に思ったけれど Python はスクリプト内のデータ構造にも
わりと簡単にアクセスできる。

Scheme は未調査。 独自 Lisp も一応考え中。

そこまで好きじゃあないことを除けば Python 一択って感じだなぁ。

まずは PyQt か PyGtk あたりで作って遅かったら適宜 C に変えていこう。

36355 journal

cheekcatの日記: 日記通知メールがバグってる? 1

日記 by cheekcat

witch さんの日記のメール通知が変だった。 片方の日記のタイトルが間違ってる。

(ROBO) X-10 今日の作業 (新リポ動作確認&起き上がりモーションチェック) <= 間違ってる
http://srad.jp/~witch/journal/453902

(ROBO) X-10 今日の作業 (新リポ動作確認&起き上がりモーションチェック)
http://srad.jp/~witch/journal/453903

#453902 の日記が 1:46
#453902 のメールの Date が 1:50:10
#453903 の日記が 1:55
#453902 のメールの Date が 2:05:06

んー? 未来予測?

462966 journal

cheekcatの日記: 最小hash関数

日記 by cheekcat

ひさしぶりにすごいコードを見た

お題は

2^a (1≦a≦9)を渡されたときaを求める方法で何かいい物はありませんか?
なるべくループやlogを使わない物がいいです

これの解答にこんなが来た。

"_\1\6\2\011\7\3__\5\010_\4"[n*0xCA030FF>>28];

もしくは

"\1\2\3\010\6\4\011__\7\5"[n*0x5300000>>28];

これは

#include <stdio.h>
#include <math.h>
 
int main()
{
  int i;
  for (i=1; i<10; i++){
    int n = pow(2,i);
    printf("%d %2d %2d\n",i,(unsigned int)n*0x5300000>>28,(unsigned int)n*0xCA030FF>>28);
  }
  return 0;
}

こういうコードを実行すれば原理がつかめる。

1  0  1
2  1  3
3  2  6
4  5 12
5 10  9
6  4  2
7  9  5
8  3 10
9  6  4

入力に対して出力が完全にばらけるようになっている。

0x53 = 01010011 (2)

これを bit shift した時、 int の幅 32bit で切り詰められることを考慮すると

1 0         => 0000 =  0
2 01        => 0001 =  1
3 010       => 0010 =  2
4 0101      => 0101 =  5
5 01010     => 1010 = 10
6 010100    => 0100 =  4
7 0101001   => 1001 =  9
8 01010011  => 0011 =  3
9 010100110 => 0110 =  6

となる。 そして、文字列を lookup すると答が出るわけですね。

さて、この完全 hash 関数の作りかた。適当なものでいいならともかく最小を探す
ならプログラムにたよるのがよいだろう。Python ならこんな感じか。

# でも、なんとなく法則がありそうな感じもする

generator って初めて使ったけど楽しい。

総当りしてるからこのプログラムは遅い。 ほんとは gen_bit あたりで適当に
木を切っていかなきゃいけないのだろうね。

#!/usr/bin/python
 
import sys
from itertools import count
import re
 
def bitstr(string, bits):
    return "0"*(bits-len(string))+string[-bits:]
 
def gen_bit_len(seed,length):
    if len(seed) == length:
        yield seed
    else:
        gen = gen_bit_len(seed+"0",length)
        for x in gen:
            yield x
        gen = gen_bit_len(seed+"1",length)
        for x in gen:
            yield x
 
def gen_bit(n):
    g = count(n)
    for x in g:
        gen = gen_bit_len("",x)
        for y in gen:
            yield y
 
def two2ten(two):
    res=0
    for x in range(1,len(two)+1):
        res+=int(two[-x])*(2**(x-1))
    return res
 
def gen_hash(n, bits):
    gen = gen_bit(n)
 
    for curbit in gen:
        bitmap = {}
        ok = True
        for x in range(1,n+1):
            tmp = bitstr(curbit[:x],bits)
            if bitmap.has_key(tmp):
                ok = False
                break
            bitmap[tmp] = 1
        if ok:
            yield curbit
 
if not len(sys.argv) in (2,3):
    print "Usage: %s <number> [<bit>]" % sys.argv[0]
    sys.exit(1)
 
n = int(sys.argv[1])
 
mbits = 1
while True:
   if n <= 2**mbits:
       break
   mbits+=1
 
if len(sys.argv) == 3:
    bits = int(sys.argv[2])
else:
    bits = mbits
 
if bits < mbits:
    print "bits too small, should be larger than %d" % mbits-1
    sys.exit(1)
 
min_len = -1
hash_list = []
min_hash = -1
print "Start %d bit search" % bits
print
for curbit in gen_hash(n, bits):
    if min_len <> -1 and min_len < len(curbit):
        break
    min_len = len(curbit)
    m = -1
    for x in range(1,n+1):
        ten = two2ten(bitstr(curbit[:x],bits))
        if m < ten:
            m = ten
    if min_hash <> -1 and min_hash < m:
        continue
    elif m < min_hash:
        hash_list = []
    min_hash = m
    hash_list.append(curbit)
 
for curbit in hash_list:
    bitmap = ["_"] * (2**bits)
    for x in range(1,n+1):
        tmp_str = bitstr(curbit[:x],bits)
        ten = two2ten(tmp_str)
        if m < ten:
            m = ten
        bitmap[ten] = r"\0%o" % x
        print "%5d => %5d (%s)" % (x, ten, tmp_str)
    print curbit
    s = ''.join(bitmap[:m+1])
    print "\"%s\"(0x%X<<i)>>%d" % (s, two2ten(curbit+"0"*(32-len(curbit))), 32-bits)
    print

30563 journal

cheekcatの日記: gcc の bug?

日記 by cheekcat

こういう test.c をコンパイルすると

     1    int main(void)
     2    {
     3            static const int size = 16;
     4            struct structA {
     5              int foo[size];
     6            };
     7            struct structB {
     8              int foo[16];
     9            };
    10            struct structA *ptrA;
    11            struct structB *ptrB;
    12
    13            ptrA = (typeof(*ptrA) *) 0x12345;
    14            ptrB = (typeof(*ptrB) *) 0x67890;
    15
    16            ptrA = ({ (typeof(*ptrA) *) 0x12345; });
    17            ptrB = ({ (typeof(*ptrB) *) 0x67890; });
    18
    19            return 0;
    20    }

% gcc -Wall test.c
test.c: In function ‘main’:
test.c:16: 警告: statement with no effect

と、なる。

多分、 定数を添字に使った配列を含む struct は ({}) の中でうまく typeof
がとれないのだろう。とりあえず x86_64-pc-linux-gnu-gcc-4.2.4 と
x86_64-pc-linux-gnu-gcc-4.3.1 で確認。

27729 journal

cheekcatの日記: Emacs CVS HEAD で M+ フォントを使うと落ちる 5

日記 by cheekcat

Emacs の CVS HEAD で M+ フォントを使いたいのだけれど、 Emacs が SEGV を出してしんでしまう。

gdb で追ってみたけど、理解できない挙動をしてくれる…。

cheekcat@yue 1115 % gdb --directory=/usr/portage/distfiles/cvs-src/emacs/src/ --args emacs -Q
GNU gdb 6.8
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-pc-linux-gnu"...
(gdb) r
Starting program: /usr/bin/emacs -Q
[Thread debugging using libthread_db enabled]
[New Thread 0x7f5ea63e86f0 (LWP 6253)]
 
Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7f5ea63e86f0 (LWP 6253)]
0x00000000004dd01e in realize_x_face (cache=0x183a220, attrs=0x7fffae415a30) at xfaces.c:5837
5837            fontset = default_face->fontset;

まずは xfaces.c の realize_x_face() の一部から

.-------------------------------------------------------------------------------
|   default_face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
|   if (default_face
|       && lface_same_font_attributes_p (default_face->lface, attrs))
|     {
|       face->font = default_face->font;
|       face->fontset
|     = make_fontset_for_ascii_face (f, default_face->fontset, face);
|     }
|   else
|     {
|       /* If the face attribute ATTRS specifies a fontset, use it as
|      the base of a new realized fontset.  Otherwise, use the same
|      base fontset as of the default face.  The base determines
|      registry and encoding of a font.  It may also determine
|      foundry and family.  The other fields of font name pattern
|      are constructed from ATTRS.  */
|       int fontset = face_fontset (attrs);
|
|       /* If we are realizing the default face, ATTRS should specify a
|      fontset.  In other words, if FONTSET is -1, we are not
|      realizing the default face, thus the default face should have
|      already been realized.  */
|       if (fontset == -1)
|     fontset = default_face->fontset;
|       if (fontset == -1)
|     abort ();
|       if (! FONT_OBJECT_P (attrs[LFACE_FONT_INDEX]))
|     attrs[LFACE_FONT_INDEX]
|       = font_load_for_lface (f, attrs, attrs[LFACE_FONT_INDEX]);
|       if (FONT_OBJECT_P (attrs[LFACE_FONT_INDEX]))
|     {
|       face->font = XFONT_OBJECT (attrs[LFACE_FONT_INDEX]);
|       face->fontset = make_fontset_for_ascii_face (f, fontset, face);
|     }
|       else
|     {
|       face->font = NULL;
|       face->fontset = -1;
|     }
|     }
`-------------------------------------------------------------------------------

SEGV が出るのは次の行。

    fontset = default_face->fontset;

ここで、 default_face == 0 なので SEGV が出ている。 関係する変数を見て
おこう。

(gdb) print default_face
$1 = (struct face *) 0x0
(gdb) print fontset
$2 = -1
(gdb) print attrs
$3 = (Lisp_Object *) 0x7fffae415a30

さて、次に face_fontset() を見てみる。

xfaces.c face_fontset()

.-------------------------------------------------------------------------------
| static int
| face_fontset (attrs)
|      Lisp_Object *attrs;
| {
|   Lisp_Object name;
|
|   name = attrs[LFACE_FONTSET_INDEX];
|   if (!STRINGP (name))
|     return -1;
|   return fs_query_fontset (name, 0);
| }
`-------------------------------------------------------------------------------

ということで、 face_fontset (attrs) == -1 なのだから !STRINGP(name)
0 が成り立つはずである。

ところが

(gdb) print attrs[LFACE_FONTSET_INDEX]
$4 = 22619155
(gdb) print Fstringp(attrs[LFACE_FONTSET_INDEX])
$5 = 11844081
(gdb) print Qt
$6 = 11844081
(gdb) print Qnil
$7 = 11843985

と、 Fstringp(attrs[LFACE_FONTSET_INDEX]) は Qt を返しているのだ。

一応正確を期すために Fstringp() を見ておこう。

DEFUN ("stringp", Fstringp, Sstringp, 1, 1, 0,
       doc: /* Return t if OBJECT is a string.  */)
     (object)
     Lisp_Object object;
{
  if (STRINGP (object))
    return Qt;
  return Qnil;
}

このように STRINGP(attrs[LFACE_FONTSET_INDEX]) 0 が成り立っているし、
同時に!STRINGP(attrs[LFACE_FONTSET_INDEX]) 0 も成り立っているように
思えるのである。

どこかにミスがあるのだろうが、どこにあるのだろう?

typodupeerror

皆さんもソースを読むときに、行と行の間を読むような気持ちで見てほしい -- あるハッカー

読み込み中...