No Such Blog or Diary

«Prev || 1 | 2 | 3 |...| 1170 | 1171 | 1172 |...| 1256 | 1257 | 1258 || Next»

f(f(x)) = -x となる実関数 f を求めよ

複素関数であれば f(x) = ix で f(f(x)) = -x となって簡単(虚軸を経由して回転すりゃいい).今は実関数しばりなので,とりあえず区間単位のシフトと反転を組み合わせる.適当な l > 0 に対して

f(x) = 0        if x = 0
       x+l      if x ∈ ( 2nl, (2n+1)l ]
       -(x-l)   if x ∈ ( (2n+1)l, (2n+2)l ]
       x-l      if x ∈ [ -(2n+1)l, -2nl )
       -(x+l)   if x ∈ [ -(2n+2)l, -(2n+1)l )
                        (n = 0, 1, ...)

イメージとしては実軸の半分を虚軸の代わりにして90度回転.f^m(x) = -x (m > 2) に用意に拡張可能.

そして今日の記録は 127keys/min.

今日は

110程度で.速く打とうとすると qwerty になってしまうためここから伸びない… あと,o と e,t と n,c と r がよく逆さまになってしまう(混線してるらしい)

とりあえず

94まで記録更新.ほんの少しずつ速くなってるような.

Dvorak配列

おもむろにキーボードの配列を Dvorak にしてみた.しかし,キー配置は覚えたけどタイピングスピードが 80keys/min しかでない.しばらくプログラムが書けないような…

マリブ

とりあえず飲めん.マリブミルクにして一杯飲んだが私には合わん.ということでダウン.

剰余の最適化

2^n で割ったあまりを求めるには 2^n -1 との AND をとる方が一般には速い.んで,コンパイラもそこらへんがわかっているので AND 演算に置き換えてくれるのだが… 以下の二つのプログラム

int main(int argc, char *argv[])
{
    int k = 0;
    for(int i = 0; i < 100000000; i++){
        k = k % 4;
    }
    return k;
}

int main(int argc, char *argv[])
{
    int k = 0;
    for(int i = 0; i < 100000000; i++){
        k = k % 4U;
    }
    return k;
}

では後者のほうが3倍くらい速くなる(倍率は環境によるかもしれないけど).両者のアセンブリコードを比べると

	xorl	%edx, %edx
	movl	$99999999, %ecx
	jmp	L6
	.p2align 4,,7
L5:
	andl	$-4, %eax
	subl	%eax, %edx
	decl	%ecx
	movl	%edx, %eax
	js	L10
L6:
	testl	%edx, %edx
	movl	%edx, %eax
	jns	L5
	leal	3(%edx), %eax
	andl	$-4, %eax
	subl	%eax, %edx
	decl	%ecx
	movl	%edx, %eax
	jns	L6
L10:
	leave
	ret

	xorl	%ecx, %ecx
	movl	$99999999, %edx
	.p2align 4,,15
L5:
	movl	%ecx, %eax
	andl	$3, %eax
	decl	%edx
	movl	%eax, %ecx
	jns	L5
	leave
	ret

のようになっており(gcc3.4.4),後者のほうが分岐が無いし速いのは当たり前.とりあえず問題点は「符号付の剰余は負数のときにめんどくさい」という点にある.その面倒な処理が分岐を必要として遅くなってしまうと.

ということで,負数なんて知らんという場合には明示的に符号なしであることを指定しておくべし.

«Prev || 1 | 2 | 3 |...| 1170 | 1171 | 1172 |...| 1256 | 1257 | 1258 || Next»
Search
Feeds

Page Top