青木日記

<前月 | 最新 | 次月>

2003-04-01

パスに使える文字 (2)

なるほど。なんつーか、さすが Windowsって感じ。

1 + 1 != 2

UNIX にしても別の点じゃ似たようなもんですかね。


2003-04-02

脆弱なマシン、脆弱な OS

あーもう、なんで Libretto はこんなに弱っちいのだ! なにかって言うとファンをガーガー回してさ、 いきなり固まるしさ、いきなりリブートするしさ、 いきなりコンソールのカーソルが消えるしさ! 特に Me で Cygwin 使うのがよろしくないようだ。

まあそれ以外でもガンガン固まるんだけどさ。見境なく。 Sleipnir でタブを 20 枚くらい開くとたっぷり 1 分は戻ってこないね。 そういうときに迂闊にスクロールさせたりするともうだめよ。即死よ。 いくらなんでも弱すぎじゃない?

ReFe 0.6

久しぶりに ReFe をバージョンアップしました。

-withdocsrc はリファレンス全部と Ruby のソースコードのデータベースを入れたもの。 -withdoc はリファレンスのみ。無印は ReFe 本体だけ。全ファイルのリストは次のとこ。

それにしても、この程度の変更でこんなに時間使っちゃだめだよなあ。

ReFe 0.6 (2)

ユニットテストが全然動かないな。 最初のが 1.6 で動かないのは単なる手抜きだけど、 いま直したので動くはず。 うーん、家の RubyUnit が古いのかなあ。

そうでもないな。 TestUnit の RubyUnit 互換インターフェイスが間違ってるようだ。 RUNIT::TestRunner.new の引数がない。

まあいいや。このさい TestUnit に移行することにしよう。

なんとなく世の中が緩慢

そっか、四月の頭だから普通の人は忙しいんだ。

Unix の歴史

http://www.levenez.com/unix/

なんと A4 15 ページにもおよぶ Unix の系譜図が! 最後のほうは線の間隔が狭すぎて五線紙状態 (笑) さっそく印刷しますた。

本日のツッコミ (全1件)

なかだ [bin/refeなどがrefe/config.rbをrequireしていないという問題の他に、
case-insensitiveなファイルシステムでは一部のデータファイル名が衝突するという問題があります。
具体的にはdata/refe/function_source/rb/の下でいくつかファイルとディレクトリが衝突しますが、気づいてないだけで他にもあるかも知れません。]


2003-04-03

ReFe (3)

しまった、大文字小文字を区別しないファイルシステムのことは考えてなかったー! どうしよう。黙って大文字を全部エスケープするしかないか。 それとも -A にしようかなあ……うん、そのほうがいいな。そうしよう。

他に、refe -C data wrap で Data Wrap Struct が出ないという問題もありました。 こっちは検索ルーチンの間違い。

ReFe (4) データベース

別のデータベースもいちおう用意してあるんですけどね。 そっちは AMarshal と同じで、 Ruby のソースコードとして格納して eval します。 ただし 10 倍くらい遅いです。

ReFe (5)

うわあ、なんかエスケープ周りがバグバグしてるよう。 これはグロブパターンを真面目にパースしないとだめだな。

あ。それどころじゃねえや。 一文字が複数文字になるだけでまずいんだ。 '?' とかキャラクタクラスが全然動かなくなる。

やっぱり検索ルーチンは自前で書かないとだめか。 さようなら 10 倍速。考えが甘かった。

FDD RAID

http://ohlssonvox.8k.com/fdd_raid.htm

フロッピーで RAID?!


2003-04-04

ReFe 0.7

こっそりとバージョンアップしてみた。 ML に流すのは Windows でテストしてから……。

追記:Win2000 / NTFS でテストしました。まったく問題なし。


2003-04-06

遅延初期化

メール出し忘れてた。

消える前に「バカが征く」ミラー (もう消えたけど)。

無闇に遅延初期化っつーのはどうかと思います。
 
def getFoo
  if @foo.nil?
    @foo = createFoo
  else
    @foo
  end
end
 
こういうの。初期化しておくんならコンストラクタとかでやっとくのが本道じゃ
ないですかね。計算に時間がかかるとかがあれば別でしょうけど。

想像してみると、確かに initialize で初期化するほうがよいような気がします。 ではそれはなぜ「本道」なのかをできるだけ論理的に考えてみました。

まず、そういうもんだって言えば確かにそうです。 コンストラクタって言うくらいなんだからデータ構造を作るのに使うべきでしょう。 また読むほうもコンストラクタにはそういう役割があるだろうと期待しているので、 その期待に沿って書いたほうが読みやすいと感じるはずです (消極的な理由)。

またもう一つ、動的な構造をソースコードから想像するのが簡単になるという点が 挙げられます。データ構造を理解するのはコード読みの中でも根幹にあたりますから、 データ構造を想像しやすいコードは読みやすいでしょう。 従ってインスタンス変数はコンストラクタで初期化すべきです (積極的な理由)。

Ruby のように変数型のない言語では第二点は特に重要です。 変数が型ありの場合は、コンストラクタで代入していなくとも 変数定義さえ上のほうにあれば何が入るのかはとりあえずわかるからです。

逆に言うと、変数に型のない言語で読みやすいコードを書こうと思うと コンストラクタだけでデータ構造がわかるようにするほうがよい、 そうするように矯正される。かもしれません。単にわかりにくいコードに なるだけかもしれません。

遅延初期化 (2)

ちなみに Ruby で遅延初期化をするときは次のように書くのが簡潔です。

@ivar ||= make_object()

また ||= を使う場合に限り @ivar を初期化していなくても警告が出ません。

~/c/tmail % ruby -vwe '@ivar = 0 unless @ivar'
ruby 1.8.0 (2003-03-28) [i686-linux-gnu]
-e:1: warning: instance variable @ivar not initialized
 
~/c/tmail % ruby -vwe '@ivar ||= 0'
ruby 1.8.0 (2003-03-28) [i686-linux-gnu]

ただしこれはモジュール関数の中などでやむなく遅延初期化せざるを 得ない状況を救済するためではないかと思われます。

# 例
module FileUtils
  module_function
  def verbose_output( msg )
    @output ||= $stderr   # initializeが使えないので遅延初期化できない
    @output.puts(msg)
  end
end

initializeの位置

そうだ、initialize はクラス定義の最初に置くべきでしょう。 最初のころは「private だから」つーことで一番下に書いてたんですが、 前述のような理由を考えると initialize が先頭にないとまず意味が ありません。せっかく initialize が自動的に private になるように なってるんだから、その機能を活用しましょう。

あ、でもクラスの特異メソッドは initialize より前に置いてます。

include はいまだにブレがあるんですが、 だいたいクラス定義文の冒頭か initialize の直前ですかね。 冒頭に置く理由は「スーパークラスの記述と近いから」で、 initialize の前に置く理由は 「include はインスタンスメソッドの記述 (のショートカット) だから」です。 だから一部でしか使わないメソッドのために include するときは 例外的にその直前で include する場合もあります。

requireの位置

require はファイル先頭。 最初の最初にファイル間の関係を理解するとき、 require が先頭にないと理解しづらいです。

本日のツッコミ (全6件)

ささだ [私は、遅延評価のことを忘れてしまったりすることが多多あるため、initializeで初期化します。require は、メソッドの中に書いちゃうことが結構あるんですが ^^;]

ただただし [じゃあ、「遅延初期化は最後から一個前の武器だ」ってことで。]

あおき [とか言いつつも遅延初期化使いまくってますけどね、ぼくは。
今日の話題は自戒を込めて書いてみました ^^;;;]

はら [attr_ 系は initialize の前ですかね。]

moriq [おお。タイムリー。
昨日このようなコードを書きました。

module DateOld
def roku
@roku = ほにゃほにゃ
instance_eval {
def self.roku
@roku
end
}
@roku
end
end

でも、こう書いたほうがいいですね。

module DateOld
def make_roku
ほにゃほにゃ
end
def roku
@roku ||= make_roku
end
end]

moriq [あ、でも make_roku は nil になることがある(@roku=nilでrokuは以後nilを返す)ので @roku ||= make_roku は採用しにくいな。]


2003-04-07

Haskell grep

すんごく間が空いたけど Haskell grep。 引数からファイル読むのは面倒なので stdin しか対象にしません。

module Main (main) where
 
import System
import IO
import Text.Regex
 
main :: IO ()
main =
    do
        args <- getArgs
        doGrep $ mkRegex (head args)
 
doGrep :: Regex -> IO ()
doGrep re =
    do
        cs <- getContents
        mapM_ (\line -> case matchRegex re line of
                             Just _ -> putStrLn line
                             Nothing -> return ()) (lines cs)

うーむ、ARGF が欲すい。

Hugs

最近の Haskell にはライブラリが二種類ある。 主な違いはレイアウトで、新しいライブラリは階層化されている。 これを階層化ライブラリ (hierarchical library) と言う。

GHC はデフォルトで階層化ライブラリを使う。 Hugs はデフォルトで古いライブラリを使う。 Hugs で階層化ライブラリを使いたいときは runhugs +N とする。

よくあることですが

秋葉原に行きました。

いつもどおり

軟派な PC パーツショップは素通りして末広町方面に向かいます。

……

ごめんなさい

嘘です。

ちょっとだけ寄りました。

Matrox のレイテストなヴィデオカード 「ぱへりあ」が見たかったんです。

あ、

ラジオデパートに寄りましょう。

でも

ハードウェア素人のわたしにとって

半固定抵抗や生のコネクタはさすがに手強すぎます。

そんなわけで

地下 1F をざっと見るくらいです。

あ、

ちょっとだけ Otto 5F (UNIX本舗) も見ておきましょう。

ところで

高いから買わないけど

PC サーバ屋には

なぜかときどき

Alpha が置いてあります。

Sun や hp は絶対に置いてないのに

Alpha だけあるんです。

どうしてでしょう?

どうやったら Alpha が PC サーバに見えるんですか?

もしかして

PS/2 端子が付いてたら全部 PC サーバですか?

さて

今度こそ末広町方面に向かいます。

エロゲやエロゲやエロゲや同人エロゲ

を売っている店のあたりを通りすぎて奥に向かいます。

ジャンク屋で ECC FP 16MB のメモリを二枚買いました。

あとで RS/6000 に付けてみることにします。

二枚でブランドが違うので

あぼーんかもしれません。

ドキドキですね。

さる店に来ました。

この店は高いです。

バカ高いです。

でもなぜか Alpha がよく出ます。

そんなわけで

今日も Alpha が置いてありました。

あの紺匡体は

明らかに AlphaStation 500 です。

と、いうことで

確保してきました。

来週には

家の Alpha が三台になります。

ついでに言うと

AlphaServer 800 もありました。

この AlphaServer 800 は

なぜか

他の店も合わせると 3 台もありました。

……

出所は同じ?

さて

帰りますか。

おっとその前に

ちょっとだけラジオデパートに寄っていこう。

と言うわけで

なぜか

SparcStation5 が手元にあるんですが

どういうことですか?

いくら半額セールだからって

いくら 2415 円 (税込) だからって

いまさら SparcStation5 はないんじゃないですか?

MicroSPARC ですよ?

sun4m ですよ?

Solaris 9 でサポートが切られると一瞬噂になった sun4m ですよ?

しかも

その 2415 円 (税込) ですら所持金ギリギリで

電車賃が 10 円足りないというのは

どういうことですか?

ああ

あのときチチブデンキの前で生茶さえ買わなければ。

そう思っても後の血祭りです。

……

狙って外したギャクは寒いです。

幸い (fortunately,)

御徒町から乗ると電車賃が 30 円下がります。

ただし

SS5 は

重いです。

MicroSPARC は

伊達じゃないんです。

不幸にして (unfortunately,)

カートなんて便利なもんは

持っていきませんでした。

今日は絶対に買わないぞ! なんて決意して

カートを持っていかなかったんです。

でも

買わないでいられるはずが

ないじゃないですか。

現実を見ればよかったんです。

ていうか

金持ってけよ。

(唐突に完)

本日のツッコミ (全2件)

たむら [あおきさん、おもしろすぎるよ ...]

kjana [Alpha-PC があったせいじゃないのかな? PS/2 があっても Indy
や EWS-4800 はあんまり置いてなさそうだし.

お花見ついでに AlphaServer-1000 とか SparcServer-1000 とか
AS/400e とか買っていかれます? :-) 先週はまだあった.ちょっ
と前には MicroVAX とかもあったんですけどね....]


2003-04-08

オブジェクト指向入門

たぶんそれです (と唐突に答えてみるテスト)。

『オブジェクト指向入門』 Bertrand Meyer著、二木厚吉監訳、酒匂寛・酒匂順子共訳、 アスキー出版局、1990

Flash6

Linux の Flash6 プラグインを入れてみた。 インストールはあっという間に終了したので about:plugins で確認。

動いてない……。なんでだろう。

~ % ldd /usr/mozilla/plugins/libflashplayer.so             aamine@harmony
        libpthread.so.0 => /lib/libpthread.so.0 (0x4022d000)
        libdl.so.2 => /lib/libdl.so.2 (0x40241000)
        libz.so.1 => /usr/lib/libz.so.1 (0x40245000)
        libX11.so.6 => /usr/X11R6/lib/libX11.so.6 (0x40253000)
        libXext.so.6 => /usr/X11R6/lib/libXext.so.6 (0x402ef000)
        libXt.so.6 => /usr/X11R6/lib/libXt.so.6 (0x402fa000)
        libstdc++-libc6.2-2.so.3 => not found
        libm.so.6 => /lib/libm.so.6 (0x40341000)
        libc.so.6 => /lib/libc.so.6 (0x40362000)
        libSM.so.6 => /usr/X11R6/lib/libSM.so.6 (0x40484000)
        libICE.so.6 => /usr/X11R6/lib/libICE.so.6 (0x4048d000)
        /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x80000000)

犯人は貴様か!

なんだよ libstdc++-libc6.2-2.so.3 って。

~ % ls /usr/lib/libstdc++*
/usr/lib/libstdc++-libc6.1-1.so.2  /usr/lib/libstdc++.so.2.8.0
/usr/lib/libstdc++.a               /usr/lib/libstdc++.so.2.9
/usr/lib/libstdc++.a.2.10.0        /usr/lib/libstdc++.so.2.9.0
/usr/lib/libstdc++.la              /usr/lib/libstdc++.so.27
/usr/lib/libstdc++.so              /usr/lib/libstdc++.so.5
/usr/lib/libstdc++.so.2            /usr/lib/libstdc++.so.5.0.2
/usr/lib/libstdc++.so.2.8

当然ないですな。 てけとうにシンボリックリンクを張っておこう。

~ % cd /usr/lib
/usr/lib % sudo ln -s libstdc++.so.5 libstdc++-libc6.2-2.so.3

動いた。解決したようだ。

本日のツッコミ (全2件)

ただただし [話の流れはわからないけど、Meyer本はMy Bibleです]

たかはし [OOSCことめいやー本第2版は翻訳完了しているとの噂(Artonさん宇野るいもさん本pp.199)]


2003-04-11

図書館

http://www.namikilab.tuat.ac.jp/~sasada/diary/200304.html#d11

図書館に RHG が二冊も?!

物好きな人もいるもんですね。

大阪

花見しに大阪へ行ってきます。 往復に高速バスを使って安くあげようと思ったのに切符が取れなかったので、 ヤケになってのぞみを使うことにしました。一度乗ってみたかったんだ。

たらいまわし関数の続き

たらいまわし関数と Haskell の話の続きです。 3/23 の原先生のツッコミより。

> 非正格ってnon-strictの訳ですよね。
> この「non〜」っていう用語が不思議な気がします。
> 非正格ならこのような最適化を必ずするのでか?
> それともこれは最適化ではなく、非正格なら自動的に
> そういう計算の仕方をしてしまうのでしょうか。

必ずするわけじゃないと思います。 ぼくも勉強中なんであんまり深いことは言えませんが、 山下さんの受け売りで説明してみます。

Ruby で次のような式を計算すると、

f(g(1), g(2))

まず引数の g(1) と g(2) を計算して、それを f に渡します。 しかし Haskell では式のどこから計算されるかが決まっていません。 つまり f を展開してしまったあとに g(1) や g(2) を計算できます。

結果として次のようなことが起こります。Ruby で以下のような関数を書くと、 g(1) か g(2) どちらかの計算時間が必ず無駄になります。

def my_if( cond, t, f )
  if cond
    t
  else
    f
  end
end
 
p my_if(true, g(1), g(2))

しかし Haskell だと先に my_if を展開してしまうことができるため、 g(1) と g(2) のどちらかは無駄になることがあらかじめわかるんです。 だからまず cond だけ計算してみて、 その後で t か f のどちらかだけを求めるということができます。 つまり g(1) か g(2) のどちらかはそもそも計算されずに終わります。 たらいまわし関数の計算が速いのはこのようなことが各所で起こるからです。

具体的に見てみると、

tarai :: Int -> Int -> Int -> Int
tarai x y z
    | x <= y    = y
    | otherwise = tarai (tarai (x-1) y z)
                        (tarai (y-1) z x)
                        (tarai (z-1) x y)

三行目は「x <= y の場合は y」と記述しているんですが、 この場合 z は関係がありません。つまりそもそも計算しなくてよいわけです。 だから Haskell で計算するとかなり計算量が減って速くなるという仕組みです。

ところが John McCarthy が間違ったバージョン (竹内関数) では

tak :: Int -> Int -> Int -> Int
tak x y z
    | x <= y    = z
    | otherwise = tak (tak (x-1) y z)
                      (tak (y-1) z x)
                      (tak (z-1) x y)

となっていて、x <= y のときは z を返すことになってます。 だからどの場合でも z の計算は省略できません。 結果として non-strict だろうが strict だろうが同じ計算量になるわけです。

本日のツッコミ (全5件)

笹川 賢一 [先日のSICPではどうも。
TAKyとTAKzがあるんですね。知らんかったです。Mathematica計算の楽しみ(ヴァルディ)に実行時間の話があるけど、当方難しくて理解不能。原始帰納的関数ではないけど計算可能なのか?
Hugsでやってみたら tak 12 6 0 の結果は1だった。SMLでやると12になる。なぜ???]

笹川 賢一 [すみませ〜ん。tarai(TAKy)とTak(TAKz)を取り違えてました。
非正格も正格も同じ計算結果、しかしHaskellの方がダントツに速い。]

なかだ [なるほどねぇ。さすが言語レベルで遅延評価をサポートしてると違いますね。

class Tarai
include Comparable

def initialize(x, y, z)
@x, @y, @z = x, y, z
@t = 0
end
def tarai_inspect(level = 3)
return "?" if (level -= 1) < 0
s = "Tarai(" <<
[@x, @y, @z].map {|x| Tarai === x ? x.tarai_inspect(level) : x}.join(", ") <<
")"
s << ("%#d" % @t) unless @t.zero?
s
end
def +(val)
@t += val
end
def -(val)
@t -= val
end
def <=>(val)
to_int() <=> val.to_int
end
def coerce(val)
case val
when Integer
[val, to_int()]
else
super
end
end
def to_int
@t += if !@x
0
elsif @x <= @y
@y
else
Tarai.new(Tarai.new(@x-1, @y, @z),
Tarai.new(@y-1, @z, @x),
Tarai.new(@z-1, @x, @y)).to_i
end
@x = nil
@t
end
alias to_i to_int
def to_s
to_i.to_s
end
end

if $0 == __FILE__
a = 12, 6, 0
ARGV.each_with_index {|v, i| a[i] = v.to_i}
t = Tarai.new(*a)
puts "#{t.inspect} = #{t}"
end]

はら [あ、なるほど。最適化じゃなくて、引数に対する遅延評価なんですね。]

はら [こうすると Ruby でもそれっぽくなるかな。

class Integer
def call; self; end
end

class Proc
def -(x); proc{call - x.call}; end
end

def tarai( x, y, z )
if x.call <= y.call
then y.call
else
tarai(proc{tarai(x-1, y, z)},
proc{tarai(y-1, z, x)},
proc{tarai(z-1, x, y)})
end
end

puts tarai(12, 6, 0)]


2003-04-12

大阪

12:10

大阪は森ノ宮に着きましたー。全国何処にでもある漫画喫茶から書き込んでます。

しかしのぞみは速いですね。さすがに線路の幅が太いだけのことはあります。

あ、そう言えば帰りの時間を書いてませんでした。明日日曜の深夜に高速バスで帰ります。これに伴い月曜まで反応が止まりますのでよろしく。

本日のツッコミ (全1件)

(う) [到着早過ぎ! ^^;]


2003-04-13

まだ大阪

17:02

あー、漫画喫茶って本当にどこでもありますね。

昨日は楽しかったです。ちょと寒かったですね。今日は暑すぎ。

まとめは柳川さんとSheepmanさんがあらかたかいてくださったようなので省略ー。Crayのガワだけでも欲しいなあ。

そだ、夜は無事ホテルに泊まれました。5800円でした。出たとこ勝負はうまくいったようです。ご心配おかけしました。

今日の行動

奈良に行ってきました。時計落とすわ、ドブにはまるわで泣きそうです。

日本橋にも行きました。最初はカニのあたりに行ってしまったりしたものの、何とかたどり着きました。しかし当然ながら店が全然わかりません。ワークステーションは見かけませんねえ。OEMのUltraとかCiscoルータを見かけたくらいでしょうか。それにもう足が痛くて痛くて…。法隆寺から王寺まで歩いたのはまずかった。

本日のツッコミ (全1件)

kjana [あら残念.今日みたところでもちゃんといろいろありましたのに.
「わんだーらんどの上」だけじゃ説明としては弱すぎだったか.
SUN Ultra Enterprise 3000 が増えてたな.4way SMP.]


2003-04-14

帰ってきたー

09:01 帰宅。

習性

帰ってきて即座にパソコンの電源を入れてしまうあたりが終わってると思う。

本日のツッコミ (全3件)

ささだ [ただいま、とPCに語りかけないだけいいんぢゃないでしょうか。]

nobsun [「さびしかった」と尋ねてたりして。。。]

あおき [しないしない (^^;;
ホスト名も音楽用語だし。]


2003-04-16

ダウン

関西行きは思ったよりこたえてたようです。 月曜にうっかり眠りこんだら火曜の午後まで 一瞬たりとも目醒めませんでした。

AlphaStation500

でまあ、記憶力が激烈にいいかたなら覚えているかもしれませんが、 先週 AlphaStation500 を確保してきたのでした。 それを受けとってきました。昨日。紺匡体ですよ紺匡体。 この型は [d|i|g|i|t|a|l] のロゴもきれいでいい感じ。

内部はバコバコとパーツが外れていくギミック満載でかなり萌えます。 このへんはいずれゆっくり写真付きページで。

OS は NetBSD にしました。いいっすね、NetBSD。 /etc/rc.conf 設定しないとシングルユーザモードに叩き落とすし。 inetd が動いてると思って油断したら一つもポートが開いてないし。 telnet して su しようと思ったら「wheel じゃないとダメ」って言われるし。 この偏屈さがいい感じだ。

おにゅー

メインマシンを新しくしました。というか、 いままで Linux と Windows 2000 のデュアルブートだったのを 二台に分割したついでにマシンをアップグレードしたんです。

というわけで自己満足スペック自慢

[Linux]

  • Intel Pentium4 2.4(B)GHz
  • PC2700 DDR SDRAM 1GB (512MBx2)
  • Intel D845PESV
  • IBM IC35L020 (ATA 20GB)
  • Seagate ST380011A (ATA 80GB)
  • ELSA ELAZER III (Riva TNT2)

CPU・マザーボード・チップセットを Intel 固め。 秘かに Intel は好きです。AMD 嫌いです。

メモリ 1GB。使っても使っても余る。 正直、こんなにいらないっす。

HDD は IBM を見捨てて Seagate に流れました。 だって、だって、日立だよ日立!? そんなもんを俺のメインマシンに入れてたまるかー!

サウンドだの CD-R だのと言ったヌルいデバイスは付けてません。 と言いたいところですがサウンドはオンボードです。ちっ。

ビデオカードがいまさら TNT2 なのは使いまわしだからです。

一番高いパーツはケース。 総アルミ製で 4 まんえんでした。

速度はあんまり変わったような気がしません。 ディスク I/O が速くなるとハッキリわかるんですが、 CPU が速くなるだけでは相当の速度差がないとわかりません。

あっ、Racc が速くなってる! Ruby の parse.y を処理する時間が 8 秒から 4 秒になりました。 ますます高速化の意欲が薄れます!

ところで何か忘れてるような気がしてると思ったらフロッピードライブを 付けていませんでした。いいかげんいらないかなあ、とも思ったんですが、 昨日 NetBSD/Alpha のブートフロッピーを焼くのに使ったばっかりなので 必要ないとも言えません。

PShare Ex

ついでにぷらっとほーむの PShare Ex を買ってきました。 モニタとキーボードとマウスを一括して切り替えられるってやつですな。 Linux と Windows 2000 が分かれたのが動機です。 ワークステーションとかサブの Linux マシンが増える分には ssh だけで 済むんですが、Windows が増えてしまうとどうにもなりません。

どうも KVM スイッチにはかなり当たり外れがあるらしく、 安物だとそれなりに玉砕するみたいです。 んで、いろいろ含めて評判がいいのは主に以下の二つ。

そのかわり値段も高いです。PShare Ex は 約 3 万円でした。

次回は使用レポート。

つか

金使いすぎ。

NetBSD/Alpha

ああそうそう、NetBSD/Alpha ですけど。 あまりに簡単にインストールできたんで拍子抜けしました。 特に書くこともないくらい。 インストーラがよくできてるってことでしょう。

本日のツッコミ (全2件)

ただただし [やっぱ、開発者に速いマシンを与えてはいけないというのは本当だなぁ >高速化の意欲が薄れます]

あおき [いやいや、無駄な高速化をしなくなって生産性が
よくなると考えるべきでしょう ^^;;;]


2003-04-18

ブザー

ブザーが鳴るのは嫌いなのでずっとコード自体を外してるんですけど、 なんと今回のマザー (とケース) はコードを外してもブザーが鳴ります。 どこで鳴らしてるのか知らないけど、余計なお世話です。

PShare Ex 使用感レポート

端的に言って、かなりよいです。 以下の構成で何の問題もなく使えてます。

[共有デバイス]

  • NANAO E55D
  • ノーブランドナチュラルキーボード (PS/2)
  • Logitech MouseMan (PS/2, 3 ボタン)

[1号機]

  • Intel D845PESV (i845PE チップセット)
  • ELSA ELASER III (RIVA TNT2)
  • 1280x1024, 85Hz
  • Linux 2.4.20 + X 4.3.0 (nv)

[2号機]

  • ASUS CUSL2-C (i815EP チップセット)
  • ELSA Gradiac 517SE (GeForce4MX)
  • 1152x864, 85Hz
  • Windows 2000

「Ctrl 2 回」「Ctrl + Alt + Shift」「Scroll Lock 2 回」 のいずれかで切り替えモードに入り、さらに「数字 + Enter」で切り替え。 それぞれ有効無効も設定できるので安心です。 Emacs を使う人は「Ctrl 2 回」はオフにしといたほうがいいかも。

一番心配だったのはリフレッシュレート 85Hz だったんですが、 とりあえず問題ないようです。でもケーブルには「1600x1200 75Hz」 と書いてあるので本当はまずいのかもしれません。 でももしかしたらあれは「最大 1600x1200 75Hz」ということで、 解像度を下げればリフレッシュレートは上げてよい、 ということかもしれません。まあ、動いたんでよしとします。 85Hz と 75Hz は肉眼でも判別できてしまうので、 ちょっと 75Hz で使う気はしません。

画像も、切替器を入れる前と区別が付きません。 あ、これは元からモニタ切替器を使ってたからかな。 いずれにしてもテキストがくっきり読めるレベルですし、ゆがみも出ていません。

もちろんキーボード・マウスも正常動作してます。うーん、これはいい。 3 万円は高かったけど安定動作には変えられません。 きっちり動いてくれれば可です。

RHG 読書会

あ……? 明日か! うわあ、今日は木曜日だとばっかり思ってたよ。


2003-04-19

RHG 読書会

今月もやってまいりました。 今回は難所の状態付きスキャナです。 ここは間違いも多いんだよなあ。土下座。(してないけど)

内容のログはいつも通り RWiki に。

Rubyな話題いろいろ

大阪花見、なぜか一週間すぎた今になって思い出したように記録が出てますね……。 今日の RHG 読書会で出た話も合わせていろいろ書いてみます。

  • stdio

stdio を捨てるのはやっぱし 1.9 みたいです。 必然的に Windows の gets + スレッド問題も 1.9 で解決しそうですね。

  • 正規表現エンジン

鬼車も 1.9。 「regex.c でバグを見付けても鬼車で再現しないとどうでもいいような気がする」 という声がありました。

  • Ruby のパーサ

いろんなところで何度も出てる話ではあるけども、 やっぱり Ruby プログラムをパースするのは大変すぎます。 たとえば ruby-mode.el や irb はかなり苦労しているようです。 パーサが公式にモジュール化されるのは 2.0 ですから、 それまではどうにかしなければなりません。 Ripper みたいのを自動生成できると楽なんですけど……。

  • lib/tk*.rb

やっぱり tk 関係はディレクトリに入れたいよね。 という話を無理矢理してきました。

この話も含めて、1.7 では lib/ 以下にいろいろ入るので、 その分これよりも気を遣ってやる必要が出てきそうです。 「readbytes.rbなんていらねえだろ」とかいう話もありました。

  • lib/fileutils.rb

オプション渡しを全面的にハッシュにする決意を固めました。 近日中にパッチ書いて ruby-dev ML に流します。 どうせまだ 1.7 にしか入ってないので互換性は一切考慮しません。 ちなみに instruby.rb だけはこっちで追従させときますので。

  • Racc

あーそうだ、パーサジェネレータ標準添付してほしい、ってのもあったなあ……。 いる?


2003-04-20

たらいまわしべんち

http://sheepman.parfait.ne.jp/20030418.html#p05

あ、sheepman さんのところに派生してる。

うーむ、おかしいなあ。 家だと lambda 使って遅延評価しても Hugs のほうが速いです。 GHC でコンパイルするとさらに激速。

~/c/test/haskell % cat lazy-tarai.rb
def tarai( x, y, z )
  if x.call <= y.call
  then y.call
  else tarai(lambda { tarai(lambda{x.call-1}, y, z) },
             lambda { tarai(lambda{y.call-1}, z, x) },
             lambda { tarai(lambda{z.call-1}, x, y) })
  end
end
 
puts tarai(lambda{48}, lambda{24}, lambda{0})
 
~/c/test/haskell % cat tarai.hs
module Main where
 
main :: IO ()
main = do
          print (tarai 48 24 0)
 
tarai :: Int -> Int -> Int -> Int
tarai x y z
    | x <= y    = y
    | otherwise = tarai (tarai (x-1) y z)
                        (tarai (y-1) z x)
                        (tarai (z-1) x y)
 
 
~/c/test/haskell % time ruby lazy-tarai.rb
48
ruby lazy-tarai.rb  0.44s user 0.00s system 104% cpu 0.419 total
 
~/c/test/haskell % time runhugs tarai.hs
48
runhugs tarai.hs  0.07s user 0.00s system 148% cpu 0.047 total
 
~/c/test/haskell % ghc -O -o tarai tarai.hs
~/c/test/haskell % time ./tarai
48
./tarai  0.00s user 0.00s system 0% cpu 0.000 total

つーか、GHC は速すぎだなあ。 定数畳み込みされてるのかと思ったんですが、 引数を大きくすると実行時間も増えていくところからすると ちゃんと計算しているようです。

3/22 の原先生の返り値をキャッシュするバージョンでも、 引数を (96,48,0) にすると Hugs に負けます。

~/c/test/haskell % time ruby memo-tarai.rb
96
ruby memo-tarai.rb  0.40s user 0.00s system 101% cpu 0.394 total
 
~/c/test/haskell % time runhugs tarai.hs
96
runhugs tarai.hs  0.10s user 0.00s system 107% cpu 0.093 total

ようするに、こないだのでは引数が小さすぎると。

ruby-dev summary

改めて見ると今週はすごい流量が少ないな。 _vsnprintf の話は結局結論が出てないっぽいし、 bigdecimal 関係だけか。まあこういう週もあるやね。

本日のツッコミ (全4件)

shiro [lambdaだけでは計算量が完全な遅延評価ほど減らないように思います。
http://www.shiro.dreamhost.com/scheme/wiliki/wiliki.cgi?Scheme:たらいまわしべんち]

shiro [おっと。リンク失敗しました。ごめんなさい。
http://www.shiro.dreamhost.com/scheme/wiliki/wiliki.cgi?Scheme%3a%a4%bf%a4%e9%a4%a4%a4%de%a4%ef%a4%b7%a4%d9%a4%f3%a4%c1&l=jp]

ささだ [原先生版のは配列生成のコストが結構ありそうな予感.あと,コンパイルによる最適かもあるんでしょうね.

配列生成は,tarai(96,48,0) なので,[x,y,z] が 35K 作られる.なら,作らないようにしよう.

というわけで,

$memo = {}
def tarai2( x, y, z )
getv(x,y,z) || putv(x,y,z)
end

def getv x,y,z
($memo[x] && $memo[x][y] && $memo[x][y][z])
end

def putv x,y,z
r = if x <= y
y
else
tarai2(
tarai2(x-1,y,z),
tarai2(y-1,z,x),
tarai2(z-1,x,y))
end
x = $memo[x] ||= {x=>{}}
#p x
y = x[y] ||= {y=>{}}
#p y
y[z] = r
end
=>
0.734000 0.000000 0.734000 ( 0.750000) # 原先生
0.375000 0.000000 0.375000 ( 0.391000) # 今回の

しかし,われながらダサい.]

はら [体裁を気にせずスピードを求めるなら:

def tarai( x, y )
if x <= y
then y
else
z = yield
tarai(tarai(x-1, y){z}, tarai(y-1, z){x}){ tarai(z-1, x){y} }
end
end

puts tarai(192, 96){0}]


2003-04-25

たらいまわしべんち最終章

しつこくたらいをまわしてみる。

うーむ、原先生ファイナルバージョンがかなり速いですねえ。 第三引数だけ遅延評価するとは凄いアイデアです。

ただ、やっぱりそれでも引数をデカくすると Hugs に負けるんですよー。

~/c/tarai % time ruby yield-tarai.rb                       aamine@harmony
768
ruby yield-tarai.rb  2.20s user 0.01s system 101% cpu 2.187 total
 
~/c/tarai % time runhugs tarai.hs                          aamine@harmony
768
runhugs tarai.hs  2.13s user 0.01s system 101% cpu 2.118 total

これは (768,384,0) で試した場合で、引数を倍にするともっと差が広がります。 笹田さん版も同じですね。 やはりどうやっても完全な遅延評価をしている Haskell 版には敵わないようです。

Ruby / memoise

ちなみに笹田さんの多段ハッシュ版は次のように書いたほうが短くて速いです。

$memo = {}
 
def tarai( x, y, z )
  (($memo[x] ||= {})[y] ||= {})[z] ||= tarai0(x,y,z)
end
 
def tarai0(x, y, z)
  if x <= y
  then y
  else tarai(tarai(x-1,y,z),
             tarai(y-1,z,x),
             tarai(z-1,x,y))
  end
end
 
puts tarai(768, 384, 0)
 
 
~/c/tarai % time ruby mhash-tarai.rb     # 笹田さんのオリジナル
768
ruby mhash-tarai.rb  15.21s user 0.25s system 100% cpu 15.452 total
 
~/c/tarai % time ruby mhash-tarai2.rb    # 青木改良版
768
ruby mhash-tarai2.rb  10.41s user 0.08s system 100% cpu 10.487 total

また負の整数がないと考えてよいのなら 配列を使うとさらに高速化できます。

$memo = []
 
# x だけは -1 になることがあるので +1 しておく。
def tarai( x, y, z )
  (($memo[x+1] ||= [])[y] ||= [])[z] ||= tarai0(x,y,z)
end
 
def tarai0(x, y, z)
  if x <= y
  then y
  else tarai(tarai(x-1,y,z),
             tarai(y-1,z,x),
             tarai(z-1,x,y))
  end
end
 
puts tarai(768, 384, 0)
 
 
~/c/tarai % time ruby mhash-tarai3.rb                      aamine@harmony
768
ruby mhash-tarai3.rb  8.15s user 0.09s system 100% cpu 8.230 total

まだ「第三引数のみyield」には敵わないものの、かなり速くなりました。

C / memoise (1)

C の力任せに計算するやつが Ruby memo 版にすら負けているのが気にくわなかったので、 C でも多次元配列に計算結果をキャッシュするようにしてみました。

#include <stdio.h>
#include <stdlib.h>
 
#define K1 192
#define K2 96
#define K3 0
 
static int tarai(int, int, int);
static inline int tarai0(int, int, int);
static void initialize_cache_table(int);
 
#define max3(a,b,c) max(max(a,b),c)
#define max(x,y) ((x) > (y) ? (x) : (y))
 
int
main(int argc, char **argv)
{
    initialize_cache_table(max3(K1, K2, K3) + 2);
    printf("%d\n", tarai(K1, K2, K3));
    exit(0);
}
 
static int *cache;
static int table_width;
 
static void
initialize_cache_table(int width)
{
    int i, j, k;
 
    table_width = width;
    cache = malloc(width * width * width * sizeof(int));
    if (!cache) {
        fprintf(stderr, "malloc failed\n");
        exit(3);
    }
    for (i = 0; i < width; i++) {
        for (j = 0; j < width; j++) {
            for (k = 0; k < width; k++) {
                cache[(i * width * width) + (j * width) + k] = -2;
            }
        }
    }
}
 
static int
tarai(int x, int y, int z)
{
    int result;
    int key;
    int w = table_width;
 
    key = ((x+1)*w*w) + ((y+1)*w) + (z+1);
    result = cache[key];
    if (result != -2)
        return result;
    result = tarai0(x, y, z);
    cache[key] = result;
    return result;
}
 
static inline int
tarai0(int x, int y, int z)
{
    if (x <= y) return y;
    return tarai(tarai(x-1, y, z),
                 tarai(y-1, z, x),
                 tarai(z-1, x, y));
}

これもかなり速かったんですが、キャッシュの密度が粗すぎるため、 (768,384,0) では malloc() が失敗してしまいました。がくり。

C / memoise (2)

やはり多次元配列では芸がなさすぎました。 イリッフィベクタにしてみます。

#include <stdio.h>
#include <stdlib.h>
 
#define K1 768
#define K2 384
#define K3 0
 
static void *new_cache(void*);
static int tarai(int, int, int);
static inline int tarai0(int, int, int);
 
#define max3(a,b,c) max(max(a,b),c)
#define max(x,y) ((x) > (y) ? (x) : (y))
 
void **cache;
int cache_size;
 
int
main(int argc, char **argv)
{
    cache_size = max3(K1, K2, K3) + 2;
    cache = new_cache(0);
    printf("%d\n", tarai(K1, K2, K3));
    exit(0);
}
 
static void*
new_cache(void *val)
{
    void **p;
    int i;
 
    p = malloc(sizeof(void**) * cache_size);
    if (!p) {
        fprintf(stderr, "malloc failed\n");
        exit(3);
    }
    for (i = 0; i < cache_size; i++) {
        p[i] = val;
    }
    return p;
}
 
static int
tarai(int x, int y, int z)
{
    void **p1, **p2;
    int result;
 
    if (!(p1 = cache[x+1])) {
        cache[x+1] = p1 = new_cache(0);
    }
    if (!(p2 = p1[y])) {
        p1[y] = p2 = new_cache(-2);
    }
    if ((result = p2[z]) == -2) {
        p2[z] = result = tarai0(x,y,z);
    }
    return result;
}
 
static inline int
tarai0(int x, int y, int z)
{
    if (x <= y) return y;
    return tarai(tarai(x-1, y, z),
                 tarai(y-1, z, x),
                 tarai(z-1, x, y));
}

ちっ、こっちのほうが多次元配列を使うより短かかったか。

~/c/tarai % gcc -O6 -finline-functions -omemo-tarai memo-tarai2.c
memo-tarai2.c: In function `tarai':
memo-tarai2.c:54: warning: passing arg 1 of `new_cache' makes pointer from integer without a cast
memo-tarai2.c:56: warning: assignment makes integer from pointer without a cast
memo-tarai2.c:57: warning: assignment makes pointer from integer without a cast

黙れコンパイラ。俺が正義だ!

~/c/tarai % time ./memo-tarai                              aamine@harmony
768
./memo-tarai  0.57s user 1.68s system 101% cpu 2.227 total
 
~/c/tarai % time runhugs tarai.hs                          aamine@harmony
768
runhugs tarai.hs  2.11s user 0.02s system 100% cpu 2.122 total

おしい。もうちょっとなんですけどね。 まだキャッシュの密度が薄いみたいなので、 データ構造を工夫すればまだ速くできそうです。

ただ、こうやって速くしたバージョンが本当に正しい値を計算してるか わからないんですよね。Haskell 版にしても Ruby yield 版にしても、 プログラムが正しそうであることはちょっと見れば確かめられます。 でもここで書いた C 版のプログラムが本当に正しいかどうかは ちょっと見ただけではわかりません。 少なくとも引数に負の数を与えると SEGV するわけだし。

C / memoise (3)

ええい、ここまでやったら行くとこまで逝け! st_table を利用した C / memoise version 3。

#include <stdio.h>
#include <stdlib.h>
#include "st.h"
 
#define K1 768
#define K2 384
#define K3 0
 
static int tarai(int, int, int);
static inline int tarai0(int, int, int);
 
st_table *cache;
 
int
main(int argc, char **argv)
{
    cache = st_init_numtable();
    printf("%d\n", tarai(K1, K2, K3));
    exit(0);
}
 
static int
tarai(int x, int y, int z)
{
    st_table *t1, *t2;
    int result;
 
    if (!st_lookup(cache, x, &t1)) {
        t1 = st_init_numtable();
        st_add_direct(cache, x, t1);
    }
    if (!st_lookup(t1, y, &t2)) {
        t2 = st_init_numtable();
        st_add_direct(t1, y, t2);
    }
    if (!st_lookup(t2, z, &result)) {
        result = tarai0(x,y,z);
        st_add_direct(t2, z, result);
    }
    return result;
}
 
static inline int
tarai0(int x, int y, int z)
{
    if (x <= y) return y;
    return tarai(tarai(x-1, y, z),
                 tarai(y-1, z, x),
                 tarai(z-1, x, y));
}
 
 
~/c/tarai % gcc -O6 -Wall -finline-functions memo-tarai3.c st.c alloc.c -omemo-tarai
memo-tarai3.c: In function `tarai':
memo-tarai3.c:28: warning: passing arg 3 of `st_lookup' from incompatible pointer type
memo-tarai3.c:30: warning: passing arg 3 of `st_add_direct' makes integer from pointer without a cast
memo-tarai3.c:32: warning: passing arg 3 of `st_lookup' from incompatible pointer type
memo-tarai3.c:34: warning: passing arg 3 of `st_add_direct' makes integer from pointer without a cast
memo-tarai3.c:36: warning: passing arg 3 of `st_lookup' from incompatible pointer type
 
~/c/tarai % time ./memo-tarai                              aamine@harmony
768
./memo-tarai  1.34s user 0.07s system 101% cpu 1.387 total

やたー

ちなみに

真の最速はコレみたいです。

~/c/tarai % ghc -O -o tarai tarai.hs                       aamine@harmony
~/c/tarai % time ./tarai                                   aamine@harmony
768
./tarai  0.01s user 0.00s system 579% cpu 0.002 total

to_int

見逃してましたが、4/13 の中田さんのやつが結構速いですね。 基本的には lambda を使うのと同じですけど、to_int を使って むりやりオブジェクト指向ぽくしてるのが特徴ですか。

# ちょっと修正したものを再掲
 
class Tarai
 
  include Comparable
 
  def initialize(x, y, z)
    @x, @y, @z = x, y, z
    @t = 0
  end
 
  def tarai_inspect(level = 3)
    return "?" if (level -= 1) < 0
    s = "Tarai(" <<
        [@x, @y, @z].map {|x| Tarai === x ? x.tarai_inspect(level) : x}.join(", ") <<
        ")"
    s << ("%#d" % @t) unless @t.zero?
    s
  end
 
  def +(val)
    @t += val
  end
 
  def -(val)
    @t -= val
  end
 
  def <=>(val)
    to_int() <=> val.to_int
  end
 
  def coerce(val)
    case val
    when Integer
      [val, to_int()]
    else
      super
    end
  end
 
  def to_int
    @t += if !@x
            0
          elsif @x <= @y
            @y
          else
            Tarai.new(Tarai.new(@x-1, @y, @z),
                      Tarai.new(@y-1, @z, @x),
                      Tarai.new(@z-1, @x, @y)).to_i
          end
    @x = nil
    @t
  end
 
  alias to_i to_int
 
  def to_s
    to_i.to_s
  end
 
end
 
 
t = Tarai.new(*ARGV.map {|n| n.to_i })
puts "#{t.inspect} = #{t}"

たらいまわしパック

全部まとめました。

思う存分たらいまわしてください。

文字列を整数に変換

めも

# Ruby
"15".to_i        # チェックが甘い。e.g. "a".to_i == 0
Integer("15")    # チェックが厳しい。 e.g. Integer("a") は例外
 
; Scheme
(string->number "15")
 
 -- Haskell
read "15" :: Int
 
 -- Haskell (2) HaXml から抜粋
atoi :: String -> Int
atoi = foldl (\x y-> x*10 + ord y - ord '0') 0

Scheme / delay force

遅ればせながら shiro さんとこの Wiki も見てきました。

おおっ、delay/force なんてので遅延評価できるんですね。 Scheme って凄いなー。

まだ続くらしい

うーむ、原先生最新バージョンは……これは…… デフォルト引数を使うことで第三引数の無駄な評価を さらに一段減らしたんですね。す、凄すぎ。 これで (768,384,0) までは Hugs に勝てるようになりました。

本日のツッコミ (全8件)

ささだ [失礼ながら,笑ってしまいました.いやぁ,ようやる.つまり,Cで最速を目指すなら,GHC相当を書け,と.

ちなみに,mswin版だとスタック足りないっぽいです>768
インチキとして,tarai(z-1,x,y) は消してしまう,とかありますけど(卑怯).まぁ,そのための遅延評価なわけですが.

しかし,一般的にどういうシチュエーションでこの発想を利用するんだろう?]

はら [ピンポイント遅延評価ってのはどうでしょう:

def tarai( x, y, z = nil )
if x <= y
then y
else
z ||= yield
tarai(tarai(x-1, y, z), tarai(y-1, z, x)){ tarai(z-1, x, y) }
end
end

puts tarai(ARGV[0].to_i, ARGV[1].to_i, ARGV[2].to_i)]

はら [本来のHakellの話に戻すと(^^;、、、質問です:

(1)Haskell はmemoiseはしないのでしょうか。
(2)Haskell はローカルなmemoise(引数を2度評価しないこと)はしますよね?
(3)gosh の lambda 版が速くないのは、クロージャ生成のコストのせいでしょうか。

ruby-math に行った方がいいかなあ。]

あおき [Haskell ML はどうでしょ。
http://www.sampou.org/haskell/
に案内があります。]

shiro [(3)に関して:ちゃんと測ったことは無いのですが、delayも環境を保存しているので、生成のコストはクロージャとあまり変わらないと思います。lambda版が速くないのは単純に計算量の問題だと思います。
実装れべるで言えば、delayで作成されたpromiseは最初のforceの時にその内容が評価されて記憶されます。以降のforceは記憶された内容を返すだけです。クロージャの場合は呼び出す度に内容を評価してしまいます。Rubyでも結果をキャッシュするpromiseオブジェクトを作れば同じ様な計算量になると思います。
(キャッシュするというと副作用めいていて関数的でないですが、セマンティクスとしては、そもそも関数的な式は何度評価しても同じなので、その結果をキャッシュするのは処理系による最適化ということになると思います)。]

はら [内容を評価するタイミングについてはlambda版もHaskellも同じでは。違いは(僕の言葉でいうところの)ローカルなメモを取るかどうかではないかと想像するのですが。例えば

(define (tarai x y z)
(let ((x0 (x)) (y0 (y)))
(if (<= x0 y0)
y0
(tarai (lambda () (tarai (lambda () (- x0 1)) y z))
(lambda () (tarai (lambda () (- y0 1)) z x))
(lambda () (tarai (lambda () (- (z) 1)) x y))))))

とすると劇的に速くなります。]

shiro [確かに、ローカルで一回評価しておくと、計算量は遅延評価と同じ、線形になりますね。こちらで検証してみました:
http://www.shiro.dreamhost.com/scheme/wiliki/wiliki.cgi?Scheme%3a%a4%bf%a4%e9%a4%a4%a4%de%a4%ef%a4%b7%a4%d9%a4%f3%a4%c1]

nobsun [うぇーっ。すごいことになっていますねぇ。
Haskellの簡約は、outermost graph reduction といって、同じ変数に束縛
した式は高々一度しか簡約しないというものです。要するに、変数は式を指す
ポインタでみたいなものになっているわけです。
Introduction to Functional Programming using Haskell 2ed. §7.1]


2003-04-28

つっこみ

もうお気付きかと思いますが、 ツッコミ表示欄で改行とインデントが効くようにしました。 tDiary の思想 (『ツッコミは、短く鋭く……』) からは 外れていきますが、便利なのでいいということにします。

つーか、この日記は bpt 値 (Bytes per Tukkomi) が異様に高いよね。

頭文字 L

やつを追う前に言っておくッ!

おれは今やつのスタンドをほんのちょっぴりだが体験した

 

い…いや…体験したというよりはまったく理解を超えていたのだが………

あ…ありのまま 今起こった事を話すぜ!

『おれは 椅子を買いに行ったと思ったら いつのまにか FlexScan L665 を買っていた』

L665 ファーストインプレッション

そういうわけで L665 です。NANAO の 18.1" 液晶モニタでは一番安いやつです……。 ビック P 館で約 13 万でした。 ポイントで 10% 引きなので実質 115000 円くらいでしょうか。 秋葉原で粘ればもうちょっと安いところはあるんですが、 衝動買いイオンが抜けてしまう前に買わないといけなかったのでやむをえません。

財布が許せば L685EX (同じく NANAO の 18.1" 液晶モニタのかなり高いやつ) を買いたかったんですが、税抜で約 20 万の値札を見てしまうとさすがに躊躇します。 画質は明らかによさそうなんですけどねー。 ですがそんなことばっかり言っていると L685 のインプレッションになってしまうので 未練はサッパリ捨てて L665 に戻ることにします。

感想。うん。いいんじゃないですかね。モニタだけで手持ちの金が尽きてしまって DVI 出力のビデオカードが買えなかったもんでとりあえずアナログ接続なんですが、 すげえクッキリ画質で満足です。滲みなし、ムラなし、歪みなし。 白は白く、黒は黒く、非常にキチッと出てます。 これまでは同じく NANAO の E55D っていうそこそこ良い CRT モニタだったんですが、 今度の L665 があまりにクッキリ映るため、 今まで平気で使ってたフォントがすんごく汚く見えます。 明日 DVI のビデオカード買ってきたらいったいどうなることか。

大きいのもやっぱいいですね。液晶 18.1" だと CRT ではどのくらいかな。 20" くらいですか? 目が悪いのでサイズが上がってかなり楽になりました。

ドット抜けもほぼなし。端のほうに常時点灯が一個と常時青が一個。しかも 常に白背景の kterm を開いていると常時点灯は見えません。有利です。

デザインも NANAO のはたいてい好きなんで文句なし。 強いて言うとスリムエッジのほうがカッコいいけども、 L557 とか L767 の階段パネルよりはずっといいでしょ。

液晶モニタ with Linux

あっ、そうだその前に、Linux で液晶モニタを使うときって特殊なんですね。 液晶モニタを使うときは XF86Config のモードラインでは モニタの種類に関係なく VESA の値を指定しないといけないみたいです。 L665 は 1280x1024 ドットなので、以下の二つを指定しました。

# モードライン指定:X 3.3 の解説ページに載ってたけど X 4.3 でもそのままで OK だった
# 1280x1024 @ 60Hz
ModeLine "1280x1024"  108.000  1280 1320 1440 1688 1024 1025 1028 1066 +HSync +VSync
# 640x480 @ 60Hz (緊急用)
ModeLine "640x480"  25.175  640 648 752 800  480 490 492 525 -HSync -VSync

なにぃ、xf86cfg? そんなもんは却下だ。手で書け!

椅子

ああ、L665 を買っちゃったから椅子はおあずけかなあ。 いいかげん壊れかけの 9600 円の椅子は捨てたいんだけど……。

注意書き

あ、ちなみにぼくは NANAO 信者なので モニタの感想に関してはあまり信用しないでください。 しかも買った直後ですから。

本日のツッコミ (全3件)

たかはし [ツッコミはもう少し行間を狭くしたほうが見やすいと思います。
line-heightは%指定するとfont-sizeの大きさX%値をそのまま子要素に継承するっぽいんで、小要素でフォントの大きさを変えたらline-heightを再指定するか、親要素のline-heightを数値で指定しておくのがよさそうです(CSSはあんまり詳しくないので嘘かも)。]

あおき [なるほど、確かにそういう動きをしてるみたいです。
合わせなおしておきました。ありがとうございます。]

はら [僕はL565ですが、それに比べると隣の88Fは故障しているとしか思えません。]


2003-04-29

GeForce4 with Linux

へー、最近は nVIDIA が直接 Linux 用ドライバを提供してるのか。 GeForce4 が使えるとは思わなかったな。 どーしようかな、古いの探すのも面倒だし、GeForce4 にしようかな。

本日のツッコミ (全2件)

Yuya [EIZO L565を2台並べて使ってます。アナログ接続なので、画質は普通かな。]

Yuya [やべ。1つ上の日記につっこんだつもりだったのに・・・。]


<前月 | 最新 | 次月>
2002|04|05|06|07|08|09|10|11|12|
2003|01|02|03|04|05|06|07|08|09|10|11|12|
2004|01|02|03|04|05|06|07|08|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|11|12|
2006|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|
2008|01|02|04|05|06|09|10|
2009|07|
2010|09|