Entries

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

SSD 128GBって言うけれど

実質121GB。
1k=1000換算も鬱陶しいのに、さらに減るか。
残りはウェアレベリングにでも使っているのかね。

bad instruction `swp

タグ: Boost iPhone

iPhone OS向けのコンパイルでBoost 1.36.0の shared_ptr 等を使用すると

bad instruction `swp r3,r8,[r4]'

というエラーが出てコンパイルが通らない(1.35.0なら通る)。

理由はARM向けのスピンロック関数がThumbでサポートしていないswp命令を使っているため
既に修正コードは上がっているので、必要ならチェックアウトしてこよう。
特に1.36.0にこだわる理由がなければ、1.35.0や1.37.0を使うのも手だ。

MacBook Pro (Late 2008) 買ったよ

カスタマイズ内容

  • Core 2 Duo 2.8GHz
  • SSD 128GB

SSDに触れるのは今回が初めて。実に静かで、良い物だ。
これで、光ディスクとファン以外、機械音が発生する要素はなくなった。
……もっとも、これまで使っていたMacBook Proはバッテリー駆動時にコンデンサが振動してノイズを発していたわけだが。

どれだけアクセスが頻発してもうるさくならないが、逆にスワップの発生を音で知ることもできなくなった。
「スワップしたらガリガリ音を出すツール」とかあったら……いや、いらんか。
アクセス速度の善し悪しはよくわからんが、Firefox等、アプリケーションの起動はえらい速い。
SSDのおかげ……なのかもしれないが、比較対象が「2年半使ったCore Duo 2.0GHzのMacBook Pro」なもんで、速くなる要因が多く、やっぱりよくわからない。

新しいトラックパッドは思ったより固い。
でもってカチカチうるさい。
「ボタンがなくなってパッド全体がへこむようになった」と聞いた時は「指1本で押し下げたままドラッグできるのか」と思ったが、そんなことはなかった。
結局、パッドの下の方(幾分柔らかめ)を押し下げてドラッグするわけだが、それでも「普段指を1本しか添えておけない(2本以上置くとポインタが動かなくなる)割には」固い。

ボタンが消えたことが影響しているのか、ボタンクリックだけでなく、タップクリックの操作感も微妙に変わっている。
例えば、これまで「ポインタを移動して右クリック」という操作は

  1. トラックパッドに指を1本載せ、ポインタを移動させる
  2. ポインタの移動に使った指はそのまま、もう1本の指を隣に降ろす
  3. 2本の指をパッドから離す

という手順で行えたが、今回はポインタの移動に使った指を一度パッドから離さないとクリックにならない。
指を離さない方法は、ポインタの位置がずれることがなくて良かったのだが……

新しく追加されたジェスチャーについては、4本指はまあこれでいい。
しかし3本指は、ことSafariでは「タブの切り替え」の方が良かった。
「戻る」や「進む」は右クリックメニューから選べがいいし。
新しくタブを開くことも多いし。

パッドのクリック感にはやや不満があるが、滑り具合の方は文句なしに素晴らしい。
これまで使っていたものは、経年劣化のためかパッド以外の部分の方が滑りがいいくらいだった。
この滑り分だけでも買い替えた甲斐がある。

オーバーフロー アンダーフロー

タグ: C++

オーバーフロー(算術オーバーフロー)とは、「値が表現可能な最大値を上回る」こと。
アンダーフローとは、「値が表現可能な最小値を下回る」こと。
では、そもそも「最大値」や「最小値」とは何か。

浮動小数点数に限って言えば、オーバーフローもアンダーフローも標準規格IEEE 754で定義されているので話は早い。
これによると、オーバーフローは「正負問わず無限大に等しく」、アンダーフローは「正負問わず0とその次の非正規化数(32ビット浮動小数点数なら±2の-150乗)の間を指す」となっている。
つまり最大値や最小値は「絶対値」で考えるわけだ。

それに対し、「整数アンダーフロー」は例えば8ビット符合付き整数型であれば「演算の結果が-128より小さくなること」を指す。
浮動小数点数のアンダーフローとは違い、絶対値ではない。
この考え方自体は std::numeric_limits::min() の戻り値にも通じるものがある。

が、「整数アンダーフロー」はむしろアンダーフローとは別の概念と捉えるべきだろう。
ややこしいし、少なくともC言語の規格では「整数アンダーフロー」を「アンダーフロー」とは呼ばず、IEEE 754同様「負のオーバーフロー」と呼んでいる(§5.1.2.3例6)。

Objective-CでDoxygen

タグ: Objective-C Doxygen

Objective-CのコードをDoxygen 1.5.7(MacPortで入れた)でドキュメント化してみる。

まずは適当なコードを用意。
今回は、主にカテゴリがどのようにドキュメント化されるかを調べる。

@interface Sample : NSObject
- (void)f1;
- (void)f2;
@end

/**
 * @brief Sample クラスの Foo カテゴリ
 */
@interface Sample(Foo)
- (void)bar;
@end

/**
 * @category Sample(Hoge)
 * @brief Sample クラスの Hoge カテゴリ
 */
@interface Sample (Hoge)
- (void)fuga;
@end

@implementation Sample

/**
 * @brief インタフェースに含まれるメソッド1。
 *
 * Sample::bar を呼ぶ
 */
- (void)f1
{
	[self bar];
}

/**
 * @brief インタフェースに含まれるメソッド2。
 *
 * Sample::fuga を呼ぶ
 */
- (void)f2
{
	[self fuga];
}

@end

@implementation Sample(Foo)

/// @name ローカルメソッド
//@{
/**
 * @brief Foo カテゴリのローカルメソッド
 *
 * @param[in] n 出力する整数
 */
- (void)baz:(int)n
{
	NSLog(@"%d", n);
}
//@}

/**
 * @brief Foo カテゴリのインタフェースに含まれるメソッド
 *
 * Sample::baz: を呼ぶ。
 */
- (void)bar
{
	[self baz:1];
}

@end

@implementation Sample (Hoge)

/// @name ローカルメソッド
//@{
/**
 * @brief Hoge カテゴリのローカルメソッド
 *
 * @param[in] d 出力する実数
 */
- (void)piyo:(double)d
{
	NSLog(@"%f", d);
}
//@}

/**
 * @brief Hoge カテゴリのインタフェースに含まれるメソッド
 *
 * Sample::piyo: を呼ぶ。
 */
- (void)fuga
{
	[self piyo:1.0];
}

@end

Doxyfileはこのように書いた。

OUTPUT_LANGUAGE = Japanese
EXTRACT_ALL = YES
EXTRACT_LOCAL_METHODS = YES
GENERATE_LATEX = NO

この設定でドキュメントを生成。
クラス構成はこのようになった。

クラス構成図

カテゴリはクラスとほぼ同じ扱いを受ける。
例えば Foo カテゴリの説明には(コメントから自動生成された以外の) Sample クラスへのリンクは存在せず、あたかも独立した1クラスのように見える。

カテゴリFoo

@category を明示すると、「クラス」の表記が「カテゴリ」に変わる。
が、それだけ。
他は @category を指定しない場合と全く同じである。

カテゴリHoge

「全く同じ」という割には Hoge カテゴリの説明が妙に薄いが、これは @implementation 文でクラス名とカテゴリ名の間にスペースを空けているため。
このように記述すると、Doxygen 1.5.7はインプリメント部の説明を全てクラスの方に持って行ってしまう。

クラスSample

カテゴリとクラスの違いは、唯一、メソッドリンクの自動生成箇所にのみ見受けられる。

DOT_FONTNAME ni Hiragino

タグ: Doxygen

Mac OS XのDoxygenで DOT_FONTNAME にヒラギノを指定したい場合どう書けば良いのか調べた。

こうだった。

DOT_FONTNAME = "Hiragino Kaku Gothic Pro"

もしやと思い、以前書いたWindows環境でのMSゴシックの指定をこう書き換えてみた。

DOT_FONTNAME = "MS Gothic"
DOT_FONTPATH =

ちゃんとMSゴシックで書いてくれた。
というか、以前の書き方ではMSゴシックにできなかった上、勝手にMS明朝になった
うぬぬぅ、この辺の挙動が変わりそうな更新、何かしたっけかな……

10月14日のココロ日記(BlogPet)

いつか、喜ぶ動作がほしいです。ココロの夢です。

*このエントリは、ブログペットのココロが書いてます♪

天体戦士サンレッド

放送開始前は「1巻の表紙」しか事前情報を得てなくてまるで期待していなかったのだが……これは、いい。
地域密着型悪の組織ダイナストカバル」好きの私には、「神奈川県川崎市を舞台に世界征服を企む悪の怪人組織フロシャイム」という設定はあまりに魅力。
地上波放送はtvkのみで、あとはCSとニコニコ動画で配信という的確で思い切りの良い戦略も素敵。
色んな意味で、自分にとって今期一番のアニメ。

プロパティに慣れると

タグ: Objective-C

インスタンス変数にオブジェクトを格納するときに releaseretain を忘れる。
というか前の記事で忘れていた(修正済)。

release はまだ dealloc で使うから良い。
「割り当て」て「自動解放しない」ローカルオブジェクトの解放にも使う。
が、 retain は……プロパティを使っている場合、キー値を手動監視するときくらいしか出番がない。
まあ、うっかり忘れがちな所有権操作がそれだけ簡略化されているということだから、それはそれで歓迎すべきことではあるのだが。

keyPathsForValuesAffecting<Key>

タグ: Objective-C
#import <Foundation/Foundation.h>

@interface Foo : NSObject
{
	NSString* left;
	NSString* right;
}
- (void)setLeft:(NSString*)newLeft right:(NSString*)newRight;
@property (nonatomic, retain) NSString* left;
@property (nonatomic, retain) NSString* right;
@property (nonatomic, readonly) NSString* combined;
@end

@implementation Foo
@synthesize left, right;

+ (NSSet*)keyPathsForValuesAffectingCombined
{
	return [NSSet setWithObjects:@"left", @"right", nil];
}

- (void)dealloc
{
	[right release];
	[left release];
	[super dealloc];
}

/* 手動通知の宣言をしなくても willChangeValueForKey は正しく動作しているようだが、さて……
+ (BOOL)automaticallyNotifiesObserversForKey:(NSString*)theKey
{
	if([theKey isEqualToString:@"left"] || [theKey isEqualToString:@"right"])
		return NO;
	
	return [super automaticallyNotifiesObserversForKey:theKey];
}

- (void)setLeft:(NSString*)newLeft
{
	if(left != newLeft)
	{
		[self willChangeValueForKey:@"left"];
		[left release];
		left = [newLeft retain];
		[self didChangeValueForKey:@"left"];
	}
}

- (void)setRight:(NSString*)newRight
{
	if(right != newRight)
	{
		[self willChangeValueForKey:@"right"];
		[right release];
		right = [newRight retain];
		[self didChangeValueForKey:@"right"];
	}
}
*/

- (void)setLeft:(NSString*)newLeft right:(NSString*)newRight
{
	[self willChangeValueForKey:@"left"];
	[self willChangeValueForKey:@"right"];
	if(left != newLeft)
	{
		[left release];
		left = [newLeft retain];
	}
	if(right != newRight)
	{
		[right release];
		right = [newRight retain];
	}
	[self didChangeValueForKey:@"right"];
	[self didChangeValueForKey:@"left"];
}

- (NSString*)combined
{
	return [NSString stringWithFormat:@"%@ %@", left, right];
}

@end

@interface Bar : NSObject
@end

@implementation Bar
- (void)observeValueForKeyPath:(NSString*)keyPath
                      ofObject:(id)object
						change:(NSDictionary*)change
                       context:(void*)context
{
	NSLog(
		@"%@ %@ %@",
		[change objectForKey:NSKeyValueChangeNotificationIsPriorKey],
		keyPath,
		[change objectForKey:NSKeyValueChangeNewKey]
	);
}
@end

int main(int argc, const char* argv[])
{
	NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
	Foo* foo = [[Foo alloc] init];
	Bar* bar = [[Bar alloc] init];
	[foo
		addObserver: bar
		forKeyPath: @"left"
		options: NSKeyValueObservingOptionNew
		context: NULL
	];
	[foo
		addObserver: bar
		forKeyPath: @"right"
		options: NSKeyValueObservingOptionNew
		context: NULL
	];
	[foo
		addObserver: bar
		forKeyPath: @"combined"
		options: NSKeyValueObservingOptionNew | NSKeyValueObservingOptionPrior
		context: NULL
	];
	foo.left = @"(-";
	foo.right = @"-)";
	[foo setLeft:@"(^" right:@"^)"];
	[foo removeObserver:bar forKeyPath:@"combined"];
	[foo removeObserver:bar forKeyPath:@"right"];
	[foo removeObserver:bar forKeyPath:@"left"];
	[bar release];
	[foo release];
	[pool drain];
    return 0;
}

Xcode 3.1.1 で実行。

1 combined (null)
(null) combined (- (null)
(null) left (-
1 combined (null)
(null) combined (- -)
(null) right -)
1 combined (null)
1 combined (null)
(null) combined (^ ^)
(null) right ^)
(null) combined (^ ^)
(null) left (^

ドキュメントの通りに変化の通知をネストさせれば、 combined の変更通知は1回に収まるのではないかと期待したのだが……(^ ^)(^ ^)
このような「依存関係を持つキー」に限らず、「一固まりの変更」を厳密に認識するには、 NSKeyValueObservingOptionPrior を指定して willChangeValueForKeydidChangeValueForKey のネストを自分で正しく把握しなければならないようだ。

KVOと構造体

タグ: Objective-C
#import <Foundation/Foundation.h>

struct Baz
{
	int n;
};

@interface Bar : NSObject
{
	CGAffineTransform transform;
	CGAffineTransform* pointer;
	Baz baz;
}
@property CGAffineTransform transform;
@property CGAffineTransform* pointer;
@property Baz baz;
@end

@implementation Bar
@synthesize transform;
@synthesize pointer;
@synthesize baz;
@end

@interface Foo : NSObject
{
	Bar* bar;
}
@property (readonly) Bar* bar;
@end

@implementation Foo

@synthesize bar;

- (id)init
{
	if(self = [super init])
	{
		bar = [[Bar alloc] init];
		[bar
			addObserver: self
			forKeyPath: @"transform"
			options: NSKeyValueObservingOptionNew
			context: NULL
		];
		[bar
			addObserver: self
			forKeyPath: @"pointer"
			options: NSKeyValueObservingOptionNew
			context: NULL
		];
		[bar
			addObserver: self
			forKeyPath: @"baz"
			options: NSKeyValueObservingOptionNew
			context: NULL
		];
	}
	return self;
}

- (void)dealloc
{
	[bar removeObserver:self forKeyPath:@"baz"];
	[bar removeObserver:self forKeyPath:@"pointer"];
	[bar removeObserver:self forKeyPath:@"transform"];
	[bar release];
	[super dealloc];
}

- (void)observeValueForKeyPath:(NSString*)keyPath
                      ofObject:(id)object
                        change:(NSDictionary*)change
                       context:(void*)context
{
	id value = [change objectForKey:NSKeyValueChangeNewKey];
	NSLog(
		@"%@ %@ %s",
		keyPath, [value class], [value objCType]
	);
}

@end

int main(int argc, const char* argv[])
{
	NSAutoreleasePool* pool =
		[[NSAutoreleasePool alloc] init];
	CGAffineTransform transform = CGAffineTransformIdentity;
	Baz baz;
	Foo* foo = [[Foo alloc] init];
	foo.bar.transform = CGAffineTransformMakeRotation(1);
	foo.bar.pointer = &transform;
	foo.bar.baz = baz;
	[foo release];
	[pool drain];
    return 0;
}

Xcode 3.1.1の実行結果は以下の通り。

transform NSConcreteValue {CGAffineTransform=ffffff}
baz NSConcreteValue  {Baz=i}

やはりポインタは監視できていない
C互換構造体はフレームワーク定義のものもユーザ定義のものも監視できているが、value:withObjCType:のサポートが明言されていないので使って良いかは微妙。

あいまいが足りない

タグ: C++ Boost
#include <boost/bind.hpp>

#include <boost/lambda/bind.hpp>

を同時にインクルードして使おうとすると、何かと面倒な事態にぶち当たる。
代表的なのは、互いに同じ名前のプレースホルダを使うことによる

error C2872: '_1' : あいまいなシンボルです。

だが、これはまだエラーになってくれるだけまし。
むしろ「このエラーを期待してコンパイルしたのに通ってしまった時」がヤバイ。
「いつの間にかこの問題は解決されていたのか!」などと喜んではならない。

#include <iostream>
#include <boost/bind.hpp>
#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>
#include <boost/function.hpp>

void bar(int* n)
{
	*n = 2;
}

void baz(int* n)
{
	std::cout << *n << std::endl;
}

template <typename Function>
void foo(Function f)
{
	int n = 1;
	f(&n);
}

namespace {

void hoge()
{
	using namespace boost::lambda;
	foo(bind(&baz, (bind(&bar, _1), _1)));
}

} // unnamed

int main(int, char*[])
{
	hoge();
	return 0;
}

関数hogeは次のような処理が行われることを期待する。

int n = 1;
bar(&n); // n = 2
baz(&n); // n を出力

よって標準出力には「2」が出力されるはず。

ところが実際に出力される数字は「1」。
Boost 1.35でも1.36でも、このコードでは関数fooは呼ばれない。
何故か。

直接の原因は「グローバルの無名名前空間(という呼び方で良いのだろうか)の関数内で、修飾のない _1 を使っている」こと。
_1`anonymous-namespace'::_1boost::lambda::`anonymous-namespace'::_1 の2つが定義されており、 fuga のスコープでは using namespace boost::lambda をしても前者が優先される。
`anonymous-namespace'::_1 の関連名前空間は boost であり(ADL)、且つ bind の第1引数 &foo が「boost名前空間(Boost.Bind)では特殊化されているがboost::lambda名前空間(Boost.Lambad)では特殊化されていない関数ポインタ」であることから、 bindboost::bind が選ばれる。
bindboost::bind になるということは (bind(&foo, _1), _1) はラムダ式には成らず、ただのカンマ演算として処理されて (_1)
その結果

foo(bind(&baz, (bind(&bar, _1), _1)));

の行は

foo(bind(&baz, _1));

となり、barの呼び出しが消滅してしまうことになったのである。

Objective-C++ - RVO

タグ: Objective-C C++

Objective-Cのメソッドが戻り値としてC++の一時オブジェクトを返す時、RVOは適用されるか。
……いや、それ以前にC++のオブジェクトを返せるのか?
基本的にはただの関数と変わらないのだから、C++のオブジェクトくらい返せそうだが。

#import <Foundation/Foundation.h>

class Foo
{
public:
	Foo()
	{
		NSLog(@"default constructor");
	}
	
	Foo(int arg) :
	val(arg)
	{
		NSLog(@"constructor with %d", arg);
	}

	Foo(const Foo& rhs) :
	val(rhs.val)
	{
		NSLog(@"copy constructor");
	}
	
	~Foo()
	{
		NSLog(@"destructor");
	}
	
	int val;
};

@interface Bar : NSObject
- (Foo)rvo;
- (Foo)nrvo;
- (Foo)notRvo;
@end

@implementation Bar

- (Foo)rvo
{
	return Foo(123);
}

- (Foo)nrvo
{
	Foo foo;
	foo.val = 234;
	return foo;
}

- (Foo)notRvo
{
	static Foo foo(555);
	return foo;
}

@end

@interface Baz : Bar
@end

@implementation Baz

- (Foo)rvo
{
	return Foo(345);
}

- (Foo)nrvo
{
	Foo foo;
	foo.val = 456;
	return foo;
}

@end

void rvo(Bar* bar)
{
	Foo foo = [bar rvo];
	NSLog(@"%d", foo.val);
}

void nrvo(Bar* bar)
{
	Foo foo = [bar nrvo];
	NSLog(@"%d", foo.val);
}

void not_rvo(Bar* bar)
{
	Foo foo = [bar notRvo];
	NSLog(@"%d", foo.val);
}

int main (int argc, const char * argv[])
{
	NSAutoreleasePool* pool =
		[[NSAutoreleasePool alloc] init];

	Bar* bar = [[Bar alloc] init];
	NSLog(@"- bar RVO");
	rvo(bar);
	NSLog(@"- bar NRVO");
	nrvo(bar);
	NSLog(@"- bar not RVO");
	not_rvo(bar);
	[bar release];

	bar = [[Baz alloc] init];
	NSLog(@"- baz RVO");
	rvo(bar);
	NSLog(@"- baz NRVO");
	nrvo(bar);
	NSLog(@"- baz not RVO");
	not_rvo(bar);
	[bar release];

	[pool drain];
	return 0;
}
- bar RVO 
constructor with 123 
123 
destructor 
- bar NRVO 
default constructor 
234 
destructor 
- bar not RVO 
constructor with 555 
copy constructor 
555 
destructor 
- baz RVO 
constructor with 345 
345 
destructor 
- baz NRVO 
default constructor 
456 
destructor 
- baz not RVO 
copy constructor 
555 
destructor 
destructor

RVOもNRVOもコピーコンストラクタも、問題なく動作しているようだ。

Appendix

タグ

Blog内検索

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。