【高速化】ビット演算 0x02at TECH
【高速化】ビット演算 0x02 - 暇つぶし2ch75:デフォルトの名無しさん
06/10/31 03:09:00
>>73
もしもあなたが書き溜めたソースコードを持っているのなら…

76:デフォルトの名無しさん
06/11/15 19:13:21
ビット演算で絶対値を求めることってできますかね?
条件分岐をしないで絶対値を求めたいのですが…

77:デフォルトの名無しさん
06/11/15 20:26:02
>>76
このへん見てみたら?
URLリンク(www.thescripts.com)

78:デフォルトの名無しさん
06/11/15 21:53:55
int y=x>>31;
return (x^y)-y;
か。
今ならcmovのほうが速いだろうけど

79:デフォルトの名無しさん
06/11/15 22:56:58
ふーむ…
とりあえずリンク先を参考に試してみようと思います
ありがとうございました

80:デフォルトの名無しさん
06/11/26 15:29:11
age

81:デフォルトの名無しさん
06/12/02 22:52:42
age

82:デフォルトの名無しさん
06/12/03 07:55:42
とにかく徹底的にif文使いたくないんだけど、
根本的に排除する方法ってないんですか?
こういう場合はできるよってのがあったらそれも知りたいです。
もうビット演算のこと以外考えたくないんです。

83:デフォルトの名無しさん
06/12/03 08:40:06
>>82
論理回路にif演算器はない。

84:デフォルトの名無しさん
06/12/03 08:40:31
if(a){
 x;
} else {
 y;
}



switch(a){
default:
 x;
 break;
case 0:
 y;
}

85:デフォルトの名無しさん
06/12/03 08:50:26
じゃあ僕は条件分岐と一生付き合わなきゃいけないんですか?
一生、縁が切れないんですか??
もう勘弁しいてほしいんです。
ソース読みにくいのってみんなif文の所為じゃないですか。
この絶望のまま生きていたくない。

並列計算がうまくいかないのだってきっと条件分岐のせいですよ。
諸悪の根源と思っていますよ、もう。

ところで、論理シフトとかってあれは論理演算が関係してるんですか?

86:デフォルトの名無しさん
06/12/03 09:38:32
if(a>b){
 x=c;
} else {
 x=d;
}

x=(a>b)*c;
x+=!(a>b)*d;

こんな感じかな?
ビット演算じゃ無いけど


87:デフォルトの名無しさん
06/12/03 10:20:41
if(a){
 x;
} else {
 y;
}



n_if(a){
 x && a || y && !a;
}

88:デフォルトの名無しさん
06/12/04 17:34:01
平凡にジャンプテーブル
void f();
void g();
int hoge;

  before:
if (hoge != 0)
  f();
else
  g();

  after:
typedef (*func_t)();
func_t table[] = {f, g};
table[hoge != 0]();

89:・∀・)っ-○◎●新世紀ダンゴリオン ◆DanGorION6
06/12/04 22:59:51
関数コールのペナルティ>>>分岐予測ミスのペナルティ


d = a ? b : c;

とかでも使えば?組み込みのCMOV命令に展開してくれたりするし
SIMD系の命令セットは比較命令はマスク生成のことが多い


90:デフォルトの名無しさん
06/12/04 23:03:57
P4だと、テーブル参照方式はペナルティが信じられんほど凄い。
命令20ぐらいをズラスラ書いたのより、テーブル参照1つの方が遅かったりする。

91:デフォルトの名無しさん
06/12/07 00:04:36
最近それ経験した。
switchで振り分けた方が遥かに速かったわ。恐るべし分岐予測。

92:・∀・)っ-○◎●新世紀ダンゴリオン ◆DanGorION6
06/12/07 00:39:10
>>82はPS3かなんかの開発やらされてるゲームプログラマなんじゃね?

93:82
06/12/11 04:57:32
もうジャンプするのも嫌になりました。
if文なしのジャンプなしで何とかならないでしょうか??

94:デフォルトの名無しさん
06/12/11 18:38:36
てきとーに制限つけてその条件内で考えさせたいだけでしょ。

95:デフォルトの名無しさん
06/12/18 22:14:18
age

96:デフォルトの名無しさん
06/12/25 20:04:45
sub a, b
adc pc, a


97:デフォルトの名無しさん
06/12/30 23:15:58
あげ

98: 【大吉】
07/01/01 00:23:58
あけまして、おめでとうごzぁいます

99:デフォルトの名無しさん
07/01/01 13:31:16
要は皆さんパズル好きだと

100:デフォルトの名無しさん
07/01/03 13:42:06
プログラミング自体が、言語変わってもパーツの組合せのパズルに過ぎない訳で。

101:デフォルトの名無しさん
07/01/03 19:31:35
>>82
>根本的に排除する方法ってないんですか?
>こういう場合はできるよってのがあったらそれも知りたいです。

ビット演算以外の仕事は「引き受けない」


102:デフォルトの名無しさん
07/01/03 23:21:49
>82
まずプロセッサから設計した方がいいんじゃないか

103:デフォルトの名無しさん
07/01/04 00:46:05
>>93
cmp+jeの組み合わせがいやならsub+jneでどうだろうか。

104:デフォルトの名無しさん
07/01/06 15:01:25
Cです
int i;として
iが0以外なら1を、iが0なら0を返すビット演算は
i!=0以上にコンパクトにできるのでしょうか?
n = i!=0;と括弧つけてもやや読みづらいので。
(bool)iならば可読的なので喜んで使いたいのですが、Cなので残念ながら…

105:デフォルトの名無しさん
07/01/06 15:03:57
!!i
なんてどう?

106:デフォルトの名無しさん
07/01/06 21:00:27
typedef enum{false, true} bool;

(bool)i


107:デフォルトの名無しさん
07/01/06 22:58:09
問題は、Cではenum型にキャストした値がenum値に制限されるかどうかだね。

108:・∀・)っ-○◎●新世紀ダンゴリオン ◆DanGorION6
07/01/06 23:02:40
めんどくさい
#define TO_BOOL(x) ((x) != 0)

109:デフォルトの名無しさん
07/01/06 23:04:45
阿呆なマクロを使うくらいなら>105でいいじゃん。

110:デフォルトの名無しさん
07/01/06 23:07:38
>>108
C、C++の最適化について語るスレ
スレリンク(tech板)

団子ちゃん、↑こっちのスレの結果はどうなったの?
やっぱり、団子ちゃんが適当なこと吹いてただけなの?

111:デフォルトの名無しさん
07/01/07 07:00:18
っつーかどうしても1にしたい状況ってそんなないだろ
0/!0で充分だから


112:デフォルトの名無しさん
07/01/07 22:11:55
ビット演算でも高速化でもないな。

113:デフォルトの名無しさん
07/01/14 00:16:55
#define BITTOENNZANN(dayo) ((dayo)!=0)

これでビット演算だお^ω^

114:デフォルトの名無しさん
07/01/18 00:08:57
>>33
加算器ってこんな感じじゃない?(ちょっと冗長かも)

int ADD(int x, int y, int c) {
return (x | y | c) ?
(((x & 1) ^ (y & 1) ^ (c & 1))
| (ADD(x >> 1, y >> 1,
(( !(x & 1) & (y & 1) & (c & 1))
| ( (x & 1) & !(y & 1) & (c & 1))
| ( (x & 1) & (y & 1) & !(c & 1))
| ( (x & 1) & (y & 1) & (c & 1)))) << 1)) : 0;
}

誰か減算器↓


115:デフォルトの名無しさん
07/01/18 00:48:41
int ADD_(int x,int y){return x?ADD_((x&y)<<1,x^y):y;}
int ADD(int x,int y,int c){return ADD_((x&y)<<1|c,x^y);}
int SUB(int x,int y,int c){return ADD(x,~y,c^1);}

116:デフォルトの名無しさん
07/01/18 16:58:05
>>109
! がオーバーロードされてたら、二回も呼ばれることになるぜ。

117:デフォルトの名無しさん
07/01/19 01:20:26
オーバーロードまで考慮したら ! 二回より != の方が遅いことも
十分ありえるけどな。

118:デフォルトの名無しさん
07/01/19 14:36:23
64bitのビットを数えるのは外出?

119:デフォルトの名無しさん
07/01/19 18:41:42
>>118
ビットを数えるってのがよくあるpop関数のことなら死ぬほど既出。



120:デフォルトの名無しさん
07/01/23 07:38:25
あげ

121:デフォルトの名無しさん
07/01/23 10:19:53
レス4は絶対ここの住民だろ笑
スレリンク(tech板)l50

122:デフォルトの名無しさん
07/01/26 23:52:21
>>121
こいつのせいでビット操作のスレになってるじゃないか

123:デフォルトの名無しさん
07/01/29 12:22:02
ビット演算でbranch freeなmagic incrementは可能かね?

124:デフォルトの名無しさん
07/02/12 18:20:58
Bit Twiddling Hacks
URLリンク(graphics.stanford.edu)
こんなサイトが(英語だけど)
テンプレに入れる?

125:デフォルトの名無しさん
07/02/12 21:33:10
入れるのはいいけど、それまで続くんか?

126:デフォルトの名無しさん
07/02/12 22:46:32
コンパイル時には>>124をテンプレとしてオーバーライドします。

127:デフォルトの名無しさん
07/02/13 07:43:07
もうこのスレも息切れみたいだね。

128:デフォルトの名無しさん
07/02/13 23:14:23
だいたいビット演算ごときでときめいちゃうのは厨房までだろw
煽りぬきで

129:デフォルトの名無しさん
07/02/13 23:51:38
ていうか、パズルみたいなもんだろ。

さすがに、ネタ切れにて閉店でいいと思うよ。

130:デフォルトの名無しさん
07/02/15 15:02:08
よほど要求速度や省メモリがシビアな環境でない限りは妙な小細工はたいして必要ないもんね

131:デフォルトの名無しさん
07/02/15 15:47:08
int i = 20070215;

で、この i からそれぞれ 2007, 2, 15 って数字が欲しいんだけど
誰かカッコ良くビット演算使ってやってください。


132:デフォルトの名無しさん
07/02/15 15:50:34
>>131
実質的には除数固定で割り算を行うのと同じだから
割り算の話になるな。

133:デフォルトの名無しさん
07/02/15 16:48:06
0x20070215

134:デフォルトの名無しさん
07/02/15 16:53:01
>>131-133
それすごくもったいなくないか

たしか
日:1-31 (5bit)
月:1-12 (4bit)
年:00-99 (7bit)

で 16bit っつー表記があったな
FDとかHDのタイムスタンプとか

今なら年だけ
0000-9999 (14bit)
でも 23bit で余裕な訳だが



135:デフォルトの名無しさん
07/02/15 17:03:23
>>134
そんなところでビットをケチったってしょうがねぇべさ。
そのフォーマット(MS-DOSのFATだな)はタイムスタンプが2秒単位でしか記録できないしね。
#hour:5, minute:6, second:5

136:デフォルトの名無しさん
07/02/16 03:33:47
ねえ偉い人
10進数を3進数に変換するコードはJAVAでどう書きますか?

137:デフォルトの名無しさん
07/02/16 03:46:47
↑バカ

138:デフォルトの名無しさん
07/02/16 14:24:00
イマイチビット演算はよくわからん

139:デフォルトの名無しさん
07/02/16 15:18:45
ビット演算してると脳汁が出る

大抵は無意味だけど
オナニーとしてはナカナカそそる

140:デフォルトの名無しさん
07/02/16 15:28:21
ビット演算って1や0にするだけじゃん。

141:デフォルトの名無しさん
07/02/16 15:35:59
だが、それがいい。

142:デフォルトの名無しさん
07/02/16 15:55:53
3|17 2
3| 5 2
  1

10進数:17 -> 3進数:122

10進数から3進数への変換て、これであってる?

143:デフォルトの名無しさん
07/02/16 15:59:57
なんかboost::randomの使い方が良く分からないので
extern boost::mt19937 brand;
inline const float&n_rand(){
static float x;
*((unsigned int*)&x)=(brand()&0x7FFFFF)|0x3F000000;
return x;
}
とかやってる俺はkusobaka

144:デフォルトの名無しさん
07/02/16 20:57:54
うわっバカだ

staticいらないだろ。

145:デフォルトの名無しさん
07/02/16 23:56:47
bitマスクとかメンドクサイから言語レベルでbitの配列みたいに扱える
演算子があれば良いんだけどな。
STLやboostを使っても型変換が必要だし。



146:デフォルトの名無しさん
07/02/16 23:58:08
ビットフィールド?

147:デフォルトの名無しさん
07/02/17 00:00:30
static を除去するなら、戻り値は const float & ではなく float にすべきでもある。
ところで、乱数の範囲はそれでいいのか?
2進表現で0x3f800000 から 0x3fffffff にして、そこから 1.0f を引くと [0..1) になって使いやすいと思うが。

148:デフォルトの名無しさん
07/02/17 01:31:32
floatの表現がIEEEに合致するってのは保証されてるんだっけ?


149:デフォルトの名無しさん
07/02/17 01:54:26
うんにゃ、されてない

150:デフォルトの名無しさん
07/02/17 08:36:23
だが、それがいい

151:デフォルトの名無しさん
07/02/18 21:02:06
32bitのエンディアンの変換てどうすればいい?

152:150
07/02/18 21:13:28
ごめん、よく考えたら大したことなかった。
これでOKだ。
x = ( ( x >> 8 ) & 0x00ff00ff ) | ( ( x << 8 ) & 0xff00ff00 );
x = ( ( x >> 16 ) & 0x0000ffff ) | ( ( x << 16 ) & 0xffff0000 );

153:デフォルトの名無しさん
07/02/19 09:11:59
単に
x = (x & 0x000000ff) << 24 | (x & 0x0000ff00) << 8
| (x & 0x00ff0000) >> 8 | (x & 0xff000000) >> 24;
と書いては何かまずいの?

152の方法だと1行目で算出したxを2行目で使っているので
1行目の処理と2行目の処理の並列性が無いし、マスク用の
定数が4バイトの2つ、3バイトの1つ、2バイトの1つで、
どのCPUを想定しているのかは知らないけど、普通は
上の方法のマスク定数より長いコードになるのでは。

24回のshiftが16回のshiftより時間がかかる状況なら
上の方法は好ましくないし、エンディアン変換のビット長が
64bitなら152の方法のほうが良いように思うが。


154:デフォルトの名無しさん
07/02/19 18:34:24
普通に共用体でやった方がエレガントで早いと思いますが。。

155:デフォルトの名無しさん
07/02/19 21:49:23
正直これでいいや。
URLリンク(msdn2.microsoft.com)(VS.80).aspx

156:デフォルトの名無しさん
07/02/20 21:52:40
>>155
?


157:デフォルトの名無しさん
07/03/01 22:52:20
あげ

158:デフォルトの名無しさん
07/03/21 06:17:18
任意のビット数のシフトやローテートてなんで1クロックで実行できねーの?
連続した場合ね。

159:デフォルトの名無しさん
07/03/22 00:34:10
1024bitとか?

160:デフォルトの名無しさん
07/03/22 08:22:35
そもそも1クロックで実行っていつの時代のどのCPUの話だよ
30年前の8bit時代から頭の中進歩してないオジサマ丸出しだねw

しかも昔の8bitマイコンだって命令サイクルと実クロックは別物だしね

161:デフォルトの名無しさん
07/03/22 21:47:22
なんか言いたいんだろうけど、何を言いたいのかさっぱりわからん。

知ったか厨の典型だな。(w

162:デフォルトの名無しさん
07/04/07 02:22:12
あげ

163:デフォルトの名無しさん
07/04/29 08:20:14
a

164:デフォルトの名無しさん
07/04/29 10:38:15
1Bit CPUの可能性について語れないのは素人。

165:デフォルトの名無しさん
07/04/29 10:44:47
cmos 4000 シリーズの事か?

166:デフォルトの名無しさん
07/04/29 10:52:16
MC14500 か

167:デフォルトの名無しさん
07/04/29 12:29:58
コネクションマシンか?


168:デフォルトの名無しさん
07/04/29 18:46:24
バイトの縛りがうざいんだよ

169:デフォルトの名無しさん
07/04/30 02:15:38
22時以降はダメとか?

170:デフォルトの名無しさん
07/04/30 07:39:02
ざぶんとん

171:デフォルトの名無しさん
07/05/03 20:17:24
>どっちかのbitが立ってることを確認するために
>if(hoge & 0x000000C0)
>みたいな書き方出来ると思うのですが
>両方のbitが立ってることを確認したければ
>if(hoge & 0x000000C0 == 0x000000C0)
>って書くしか方法ないですか?

以下から正しいものを選べ

1) if(hoge & 0x000000C0 & 0x000000C0)
2) if((hoge & 0x000000C0) & 0x000000C0)
3) if(!((hoge & 0x000000C0) ^ 0x000000C0))
4) if((hoge & 0x00000080) && (hoge & 0x00000040))
5) if(~(hoge | ~0x000000C0))
6) if(~(~hoge | ~0x000000C0))


172:デフォルトの名無しさん
07/05/03 20:20:41
(hoge & 0x000000C0) == 0x000000C0 が一番速いだろう。

173:デフォルトの名無しさん
07/05/03 20:30:47
#include <stdio.h>

#define MASK 0x0000C0C0

int bittesta(int hoge)
{
if((hoge & MASK) == MASK){
return 1;
}else{
return 0;
}
}

int bittestb(int hoge)
{
if(!((hoge & MASK) ^ MASK)){
return 1;
}else{
return 0;
}
}

int main(int ac, char **av)
{
int hoge = 1234;
bittesta(hoge);
bittestb(hoge);
return 0;
}

174:デフォルトの名無しさん
07/05/03 20:31:55
_bittesta:
pushl %ebp
movl %esp, %ebp
subl $4, %esp
movl 8(%ebp), %eax
andl $49344, %eax
cmpl $49344, %eax
jne L10
movl $1, -4(%ebp)
jmp L9
L10:
movl $0, -4(%ebp)
L9:
movl -4(%ebp), %eax
leave
ret
_bittestb:
pushl %ebp
movl %esp, %ebp
subl $4, %esp
movl 8(%ebp), %eax
andl $49344, %eax
cmpl $49344, %eax
jne L13
movl $1, -4(%ebp)
jmp L12
L13:
movl $0, -4(%ebp)
L12:
movl -4(%ebp), %eax
leave
ret

175:デフォルトの名無しさん
07/05/03 20:34:17
>>172 が正解なんだけど
いまどきのコンパイラは
>>171 (3) で書いても
最適化されて >>172 になってるんだね

176:デフォルトの名無しさん
07/05/03 22:06:56
ど素人です。質問があります。

例えば1か0が格納される変数(Aと仮定)のスイッチ切り替えの場合

【例①】
if(A == 1)
{
A = 0;
}
else
{
A = 1;
}

【例②】
A = A ^ (0 + 1);

この場合早いのはやはり例②なのでしょうか?

177:デフォルトの名無しさん
07/05/03 22:13:48
A ^= 1;

が速い。まあ、例2と同じだあな。

178:デフォルトの名無しさん
07/05/03 22:18:35
>>177
有難うございました。

179:デフォルトの名無しさん
07/05/03 22:24:42
SUBR #n    Acc = n-Acc を持ってるCPUだと
A = 1-A 

のが速かったりするぞ


180:デフォルトの名無しさん
07/05/04 00:48:43
>>177,179
いや、今回は1と0で設定されてるけどほんとは3と5かもしれないだろ
そういう場合ってやっぱA ^= 1;とかA = 1-Aより

A ^= (3 + 5);のほうが正解なんじゃないか?

1と0ならA = 1-Aとかでもいいんだけどな

181:・∀・)っ-○◎●
07/05/04 00:52:14

A ^= 8;
????????????????????????????


Aには1か0が格納されるって最初の条件で確定してるんだが

182:180
07/05/04 00:53:56
>>181
汎用性を高めるって意味だよ

183:・∀・)っ-○◎●
07/05/04 00:55:14
いや8はおかしいだろ常識的に考えて

184:180
07/05/04 00:55:36
A変数に1か0だけの設定なら

A ^= 1;でいいと思うが

A変数に3か5が入ってる設定だと

A ^= 5;じゃダメだろ?

だったらどちらにでも応用できる

A ^= (1 + 0);
A ^= (5 + 3);

がいいんじゃないかって話をしたかっただけだ。

185:・∀・)っ-○◎●
07/05/04 00:56:41
8じゃ最下位ビットはトグルできません><

186:180
07/05/04 00:59:14
じゃあ7だこの野郎

187:・∀・)っ-○◎●
07/05/04 00:59:43
ちなみに俺の回答は
A = ~A;

188:デフォルトの名無しさん
07/05/04 01:01:02
工エエェェ(´д`)ェェエエ工

189:180
07/05/04 01:01:45
俺は今赤面しながら画面に張り付いてるwwwwwwwwww
確かに8じゃ無理だったwwwwwwwww

190:・∀・)っ-○◎●
07/05/04 01:24:45
>>187だと「1」にならないね。
仮に全ビット使う場合の話。
信号制御用の1ビットレジスタをこれで操作してたような。


0か1かならこっちのほうが素直か
A = !A;

191:デフォルトの名無しさん
07/05/04 01:59:07
3 と 5 のトグルなら A ^= 6; だな。
要するに A ^= (3 ^ 5);

192:デフォルトの名無しさん
07/05/04 08:32:25
拡張して 0,1,2 のトグル a=(a+1) % 3 とか 0~9 での循環a=(a+1) % 10とかになると途端に難しくなるな



193:デフォルトの名無しさん
07/05/04 08:50:20
WORD wに0x0001が含まれていて0x0010が含まれてない、の結果をBOOL bに納める式は
どう書くと一番短いですか?

194:デフォルトの名無しさん
07/05/04 08:52:03
b = (w & 0x0011) == 0x0001;

195:デフォルトの名無しさん
07/05/04 08:59:54
if ((w && 0x0001) == 0x0001)
{
if ((w && 0x0010) != 0x0010)
{
b = TRUE;
}
else
{
b = FALSE;
}
}

196:デフォルトの名無しさん
07/05/04 09:05:23
>>194
ありがとん

197:デフォルトの名無しさん
07/05/04 09:17:53
a:= a +1;
a:= (a+ (a shr 2) ) and 3;

これだと 1,2,3の循環になるな

198:デフォルトの名無しさん
07/05/04 12:09:44
A ^= (3 ^ 5);

199:デフォルトの名無しさん
07/05/04 12:19:48
1001
1000
0000
0001
0011
0010
0110
0100
0101
0111


200:デフォルトの名無しさん
07/05/04 12:21:58
       ヾ  /    < 仮面ライダー555が>
      ,. -ヤ'''カー、   /Y⌒Y⌒Y⌒Y⌒Yヾ
ー―ァ  /r⌒|:::|⌒ヾ
  _ノ オ{(  |0|  )} オオオォォォォ!!!!!
    __,ヽ,ヾ,_|V|,_ノ、/ ,r-,,=
   ,゛==ゝ_ViV_ノ~i/ 〃 `ー―-、
   /  /⌒`//´⌒c/^^^ ))))))))))
,,―イ  {ー''"~{ {~゛`ー`/'`'~/ー--―'
))   ,./ゝ_/∧ゝ_ノ  ノ
ー''"  |ロ  ロ    |
人,_,人,_,人,_,人,_,人,_,
<適当な番号をゲット!!>

201:デフォルトの名無しさん
07/05/04 15:08:21
あまり適当な番号には見えない件について

202:デフォルトの名無しさん
07/05/04 16:12:03
0xC8

203:デフォルトの名無しさん
07/05/04 16:43:42
丁度256円になります。

204:デフォルトの名無しさん
07/05/04 16:47:10
ポイントはお付きしますか?

205:デフォルトの名無しさん
07/05/04 16:50:33
いいえ、彼はペンです。

206:デフォルトの名無しさん
07/05/05 02:12:41
char v;
if(v){ ..... }

vのビット列が [10000000] と [00000001]
ではやっぱり前者の方が早いんだろうか

207:デフォルトの名無しさん
07/05/05 02:21:08
最適化や前後のループや分岐予測によるだろ…常識的に考えて…

208:デフォルトの名無しさん
07/05/05 02:37:55
嫌な答え方だな

209:デフォルトの名無しさん
07/05/05 03:18:03
感じないわ。

210:デフォルトの名無しさん
07/05/05 03:39:36
痛くないわ。


211:デフォルトの名無しさん
07/05/05 11:01:09
五寸釘はイヤだろ・・・・常考

212:デフォルトの名無しさん
07/05/05 11:21:15
ごっすんごっすん五寸釘ー

213:デフォルトの名無しさん
07/05/05 12:16:52
そっちかよクソ

214:デフォルトの名無しさん
07/05/06 17:55:55
あいーん


215:デフォルトの名無しさん
07/05/14 21:23:54
効率的では無いけど少々トリッキーなJavaのコード。数列の解説は面倒なので略。

float[] p = {
0.000f, 0.000f, 1.000f, 5.373f, 0.000f, 0.998f, 4.989f, 0.000f, 1.075f, 5.000f, 0.000f, 0.000f,
0.000f, 5.373f, 0.998f, 4.865f, 4.865f, 0.951f, 4.970f, 2.370f, 1.160f, 5.000f, 1.326f, 0.000f,
0.000f, 4.989f, 1.075f, 2.370f, 4.970f, 1.160f, 3.700f, 3.700f, 0.179f, 4.473f, 2.598f, 0.000f,
0.000f, 5.000f, 0.000f, 1.326f, 5.000f, 0.000f, 2.598f, 4.473f, 0.000f, 3.536f, 3.536f, 0.000f,
};
float[] q = new float[384];
int i,j,k;
for(i=0;i<8;i++) {
k = (((i>>>2)^(i>>>1)^i)&1)*12;
for(j=0;j<16;j++) {
q[i*48+j*3+0] = ((i&1)==0)?p[(j^k)*3+0]:-p[(j^k)*3+0];
q[i*48+j*3+1] = ((i&2)==0)?p[(j^k)*3+1]:-p[(j^k)*3+1];
q[i*48+j*3+2] = ((i&4)==0)?p[(j^k)*3+2]:-p[(j^k)*3+2];
}}
for(i=0;i<32;i++) {
for(j=0;j<12;j++) { System.out.printf("%+6.3ff,",q[i*12+j]); }
System.out.print("\n");
}

216:215の出力結果(1/2)
07/05/14 21:26:12
+0.000f,+0.000f,+1.000f,+5.373f,+0.000f,+0.998f,+4.989f,+0.000f,+1.075f,+5.000f,+0.000f,+0.000f,
+0.000f,+5.373f,+0.998f,+4.865f,+4.865f,+0.951f,+4.970f,+2.370f,+1.160f,+5.000f,+1.326f,+0.000f,
+0.000f,+4.989f,+1.075f,+2.370f,+4.970f,+1.160f,+3.700f,+3.700f,+0.179f,+4.473f,+2.598f,+0.000f,
+0.000f,+5.000f,+0.000f,+1.326f,+5.000f,+0.000f,+2.598f,+4.473f,+0.000f,+3.536f,+3.536f,+0.000f,
-0.000f,+5.000f,+0.000f,-1.326f,+5.000f,+0.000f,-2.598f,+4.473f,+0.000f,-3.536f,+3.536f,+0.000f,
-0.000f,+4.989f,+1.075f,-2.370f,+4.970f,+1.160f,-3.700f,+3.700f,+0.179f,-4.473f,+2.598f,+0.000f,
-0.000f,+5.373f,+0.998f,-4.865f,+4.865f,+0.951f,-4.970f,+2.370f,+1.160f,-5.000f,+1.326f,+0.000f,
-0.000f,+0.000f,+1.000f,-5.373f,+0.000f,+0.998f,-4.989f,+0.000f,+1.075f,-5.000f,+0.000f,+0.000f,
+0.000f,-5.000f,+0.000f,+1.326f,-5.000f,+0.000f,+2.598f,-4.473f,+0.000f,+3.536f,-3.536f,+0.000f,
+0.000f,-4.989f,+1.075f,+2.370f,-4.970f,+1.160f,+3.700f,-3.700f,+0.179f,+4.473f,-2.598f,+0.000f,
+0.000f,-5.373f,+0.998f,+4.865f,-4.865f,+0.951f,+4.970f,-2.370f,+1.160f,+5.000f,-1.326f,+0.000f,
+0.000f,-0.000f,+1.000f,+5.373f,-0.000f,+0.998f,+4.989f,-0.000f,+1.075f,+5.000f,-0.000f,+0.000f,
-0.000f,-0.000f,+1.000f,-5.373f,-0.000f,+0.998f,-4.989f,-0.000f,+1.075f,-5.000f,-0.000f,+0.000f,
-0.000f,-5.373f,+0.998f,-4.865f,-4.865f,+0.951f,-4.970f,-2.370f,+1.160f,-5.000f,-1.326f,+0.000f,
-0.000f,-4.989f,+1.075f,-2.370f,-4.970f,+1.160f,-3.700f,-3.700f,+0.179f,-4.473f,-2.598f,+0.000f,
-0.000f,-5.000f,+0.000f,-1.326f,-5.000f,+0.000f,-2.598f,-4.473f,+0.000f,-3.536f,-3.536f,+0.000f,

217:215の出力結果(2/2)
07/05/14 21:27:16
+0.000f,+5.000f,-0.000f,+1.326f,+5.000f,-0.000f,+2.598f,+4.473f,-0.000f,+3.536f,+3.536f,-0.000f,
+0.000f,+4.989f,-1.075f,+2.370f,+4.970f,-1.160f,+3.700f,+3.700f,-0.179f,+4.473f,+2.598f,-0.000f,
+0.000f,+5.373f,-0.998f,+4.865f,+4.865f,-0.951f,+4.970f,+2.370f,-1.160f,+5.000f,+1.326f,-0.000f,
+0.000f,+0.000f,-1.000f,+5.373f,+0.000f,-0.998f,+4.989f,+0.000f,-1.075f,+5.000f,+0.000f,-0.000f,
-0.000f,+0.000f,-1.000f,-5.373f,+0.000f,-0.998f,-4.989f,+0.000f,-1.075f,-5.000f,+0.000f,-0.000f,
-0.000f,+5.373f,-0.998f,-4.865f,+4.865f,-0.951f,-4.970f,+2.370f,-1.160f,-5.000f,+1.326f,-0.000f,
-0.000f,+4.989f,-1.075f,-2.370f,+4.970f,-1.160f,-3.700f,+3.700f,-0.179f,-4.473f,+2.598f,-0.000f,
-0.000f,+5.000f,-0.000f,-1.326f,+5.000f,-0.000f,-2.598f,+4.473f,-0.000f,-3.536f,+3.536f,-0.000f,
+0.000f,-0.000f,-1.000f,+5.373f,-0.000f,-0.998f,+4.989f,-0.000f,-1.075f,+5.000f,-0.000f,-0.000f,
+0.000f,-5.373f,-0.998f,+4.865f,-4.865f,-0.951f,+4.970f,-2.370f,-1.160f,+5.000f,-1.326f,-0.000f,
+0.000f,-4.989f,-1.075f,+2.370f,-4.970f,-1.160f,+3.700f,-3.700f,-0.179f,+4.473f,-2.598f,-0.000f,
+0.000f,-5.000f,-0.000f,+1.326f,-5.000f,-0.000f,+2.598f,-4.473f,-0.000f,+3.536f,-3.536f,-0.000f,
-0.000f,-5.000f,-0.000f,-1.326f,-5.000f,-0.000f,-2.598f,-4.473f,-0.000f,-3.536f,-3.536f,-0.000f,
-0.000f,-4.989f,-1.075f,-2.370f,-4.970f,-1.160f,-3.700f,-3.700f,-0.179f,-4.473f,-2.598f,-0.000f,
-0.000f,-5.373f,-0.998f,-4.865f,-4.865f,-0.951f,-4.970f,-2.370f,-1.160f,-5.000f,-1.326f,-0.000f,
-0.000f,-0.000f,-1.000f,-5.373f,-0.000f,-0.998f,-4.989f,-0.000f,-1.075f,-5.000f,-0.000f,-0.000f,

218:デフォルトの名無しさん
07/05/14 21:53:43
誰かエスパーしてくれ

219:デフォルトの名無しさん
07/05/14 23:11:47
新手の荒らしだろ、スルーよろ。

220:デフォルトの名無しさん
07/05/15 00:22:46
k = (((i>>>2)^(i>>>1)^i)&1)*12;

k = ((i>>>2)&4)*12;
と等価じゃない?

221:デフォルトの名無しさん
07/05/15 00:24:00
k = (((i>>>2)^(i>>>1)^i)&1)*12;

k = ((i>>>2)&1)*12;
と等価


222:デフォルトの名無しさん
07/05/15 00:25:45
おいおい、不等号3つって……

223:デフォルトの名無しさん
07/05/15 00:56:43
System.out.printfって何だよ
オブジェクト指向すげえよ

224:デフォルトの名無しさん
07/05/15 02:01:14
>>>220-221
^は排他的論理和、>>>は符号無し右シフト、&は論理積なので、
k=(((i>>>2)^(i>>>1)^i)&1)*12はi=1,2,4,7の時にk=12、i=0,3,5,6の時にk=0となる。
全然等価じゃねーぞ。

225:215
07/05/15 03:58:02
エスパー困難なコードですが、一番意図の分かりにくい部分だけ解説。

k = (((i>>>2)^(i>>>1)^i)&1)*12;
上の文は、iのパリティがevenであればk=0、oddであればk=12とする処理を行う部分ですが
iの値域が0~7に限られるため、パリティの計算は下3bitに対してのみ行っています。
k = (Integer.bitCount(i)&1)*12; とする手もありますが、今回は先のように書きました。

p[0]~p[15]を4x4の行列と見た場合に、q[]にその値をコピーする
for(j=0;j<16;j++) { q[j] = p[j^k]; }
の処理はkの値によって以下のような振る舞いの変化をします。
k=0:そのまま、k=3:列を逆順に入れ替え、k=12:行を逆順、k=15:行・列ともに逆順

226:デフォルトの名無しさん
07/05/15 04:07:12
そこまで式が込み入ってたら、テーブルの方が速くないかな。
まあ、環境によるとは思うが。

227:デフォルトの名無しさん
07/05/20 08:13:37
あげ

228:デフォルトの名無しさん
07/05/22 07:41:36
ある変数の中でビットが必ず一つだけ立っているとき
そのビットの位置(左右どちらからでもよい)を求めたいのですが
↓のNTZやNLZを求めるアルゴリズムを使うのよりも高速にできませんか?
URLリンク(www.nminoru.jp)
立っているビットの数が一つという条件があるので
何か工夫できないか考えたんですけど思いつきません。

229:デフォルトの名無しさん
07/05/22 08:06:11
どっかで聞いたような質問だな・・・

230:デフォルトの名無しさん
07/05/22 08:07:19
memcpyよりも高速にコピーできる高速memcpyを作りたいのですが
何か参考になる方法ってありますか?

231:デフォルトの名無しさん
07/05/22 08:18:56
>>230
memcpyより高速な手法が存在するとしたら、世の中のmemcpyはその高速
な手法を使うんじゃない?


232:デフォルトの名無しさん
07/05/22 08:24:56
>>230
ビット単位で転送するという話でもない限り、スレ違い。

233:デフォルトの名無しさん
07/05/22 08:26:58
>>231
いいえ。

234:デフォルトの名無しさん
07/05/22 08:31:37
前スレのログってどこかにある?

235:デフォルトの名無しさん
07/05/22 08:35:42
あ、あったあった。
URLリンク(p2.chbox.jp)
ここの377に似たような質問があるね。

236:デフォルトの名無しさん
07/05/22 08:39:30
>>228
ビット位置を持って回ることを検討したか?

>>230
つ [ゼロコピー]

237:デフォルトの名無しさん
07/05/22 09:05:14
ビット位置を持って回るのは難しいと思いました。
ビットはこんな風に複数のビットが立ってる変数から取り出してます。
UInt32 bits;
...
while(bits)
{
UInt32 bit = bits&(-bits);
UInt32 bit_position = get_bit_position(bit);
...
}
で、このget_bit_position()の部分を作りたいのですが・・

238:デフォルトの名無しさん
07/05/22 09:12:52
ちょっと>>235を読んできます

239:デフォルトの名無しさん
07/05/22 10:16:01
とりあえず>>235の430でやってみます。
みなさんありがとうございました。

240:デフォルトの名無しさん
07/05/23 15:19:02
24xx32~24xx512 までのシリアルEE-PROMというのは
pageというのを持っていてページサイズ内なら一度に書き込みが出来ます
ページサイズは8~256まで2のべき乗で、ROMタイプによって異なります。
今、EE_write(adr , size, dt[] ) という関数があって、この関数はページサイズを認識しません。
そこでこのラッパを作りたいのです
pagesize, ADR, SIZE , *p

if( (ADR ^ (ADR + SIZE -1)) & (0xFFFFu-(pagesize-1) ) ){ 一度に書ける }

分割しなければいけない場合
ADR ~ (ADR | (pagesize-1) ) が最初に書く領域 

というふうに考えたのだけど、ループが格好良く書けないの。

241:デフォルトの名無しさん
07/05/23 16:43:01
自己レス
結局こうやった

while(( (ADR ^ (ADR+SIZE-1)) & (0xFFFFU-(pagesize-1)) ) ){
 ct = (ADR | (pagesize-1))+1 -ADR;
 EE_write(ADR, ct , p);
 p  += ct;
 ADR += ct;
 SIZE -= ct;
}
EE_write(ADR, SIZE , p );


242:デフォルトの名無しさん
07/05/24 05:19:07
格好良いかどうかは主観だという良い例。

243:デフォルトの名無しさん
07/05/25 17:20:07
>>241
普通に書くとこんな感じ?

    unsigned tail = adr + size;
    unsigned ct = pagesize - adr % pagesize;

    while (adr + ct < tail) {
        EE_write(adr, ct, dt);
        dt += ct;
        adr += ct;
        ct = pagesize
    }
    if ((ct = tail - adr) != 0)
        EE_write(adr, ct, dt);

>>241って、SIZEに 0 を指定されると大変なことになりそうだな。


244:デフォルトの名無しさん
07/05/27 15:33:15
汚いJavaコードコンテストの会場はこちらですか?

245:デフォルトの名無しさん
07/05/27 15:35:13
いいえ、ここはJavaを知らない244が居るスレです。

246:デフォルトの名無しさん
07/05/27 22:25:32
面白くない 失せろ

247:デフォルトの名無しさん
07/05/27 23:15:48
エンディアンの変換を共用体でやるのってどうやるんですか?

248:デフォルトの名無しさん
07/05/27 23:26:39
バイトオーダーは詳しくないが
int, int って並びなら、
1, 2, 3, 4, 5, 6, 7, 8 が
4, 3, 2, 1, 8, 7, 6, 5 ってなるだけで
8, 7, 6, 5, 4, 3, 2, 1 にはならないのでは?

249:・∀・)っ-○◎●
07/05/27 23:31:17
こうですかわかりません><

typedef union {
  uint32_t wd;
  uint8_t bt[4];
} HogeType;


HogeType a, b;
a.wd = src;
b.bt[0] = a.bt[3];
b.bt[1] = a.bt[2];
b.bt[2] = a.bt[1];
b.bt[3] = a.bt[0];
dest = b.wd;


250:デフォルトの名無しさん
07/05/28 00:21:29
ヤツはダンゴさんじゃない

251:デフォルトの名無しさん
07/05/28 00:52:56
共用体って、本当はそういう風に使っちゃダメなんだよな。
規格違反。
まあ、そう使えないコンパイラはないと思うけど。

252:デフォルトの名無しさん
07/05/28 08:09:58
おいおい共用体をそういう風に使わずにほかにどんな用途があるって言うんだアホかw

253:デフォルトの名無しさん
07/05/28 10:29:21
使ってはいけない理由があるからそう決められているんだろ。
その理由が皆目検討つかないが。

254:240
07/05/28 10:38:09
>>243
ありがとう。参考になった。
でも、そのままだと最後の書き込みサイズが正しくなかったよ。

255:デフォルトの名無しさん
07/05/28 15:48:22
>>252,>>253
共用体のメンバのうち T 型の a というメンバに値が格納されているときは
U(!= T) 型の b というメンバの値は T 型の a に依存し、U 型の値としては
不正と見なされるため b を通してのアクセスは未定義の動作となる。


ではなぜ共用体が存在するのかというと、おそらく原始的なポリモーフィズムの
実現の為。

ある変数が複数通りの型(ここでは T と U とする)の値を受け入れる可能性が
あるとき、構造体のような、型の異なる複数の変数を用意するのは非効率のため
単一の変数で複数の型を扱える共用体を使う。

もっとも、C++では T 型と U 型の基本クラス V 型を定義して、V 型の参照として
T 型にも U 型にも(もちろん V 型にも)正規にアクセスできるので、共用体は
不要になってしまった(のだろう、たぶん)。

256:デフォルトの名無しさん
07/05/28 17:15:17
共用体はこういうことのためにある。

enum Variant_Type {
  VARIANT_INT,
  VARIANT_DOUBLE,
  VARIANT_CHAR,
  VARIANT_STRING
};
struct Variant {
  union {
    int i;
    double d;
    char c;
    char *s;
  } value;
  enum Variant_Type type;
};

/* var->type で分岐して、その内容を表示する関数 */
void Variant_show(const struct Variant *var) { ... }

int main(void) {
  Variant var;

  var.type = VARIANT_INT;
  var.value.i = 4;
  Variant_show(&var);

  var.type = VARIANT_STRING;
  var.value.s = "hoge";
  Variant_show(&var);
}

257:デフォルトの名無しさん
07/05/28 22:18:41
>>255
> もっとも、C++では T 型と U 型の基本クラス V 型を定義して、V 型の参照として
> T 型にも U 型にも(もちろん V 型にも)正規にアクセスできるので、共用体は
> 不要になってしまった(のだろう、たぶん)。

不要になってないだろ。

基本クラス云々で各種のデータを扱う処理は正規にできるようになったけど、
複数の型を同一の領域に割り付けるのは union でないとできない。

まあ、そんな機会はめったとないが。

258:デフォルトの名無しさん
07/05/28 22:22:43
普通わざわざそんな面倒なことしないと思いますけどねw
それで何の御利益があると思って書いてるんだろうか?
不思議な発想だとしか言いようがない

っていうか、それ多態じゃなくて多重定義でしょ?w

259:デフォルトの名無しさん
07/05/28 22:29:27


260:デフォルトの名無しさん
07/05/28 22:31:52
258は>>255-256宛てね

261:デフォルトの名無しさん
07/05/28 22:35:30
型がクラスだったりする可能性を考えると
共用体よりplacement newのほうが良いと思う。

262:デフォルトの名無しさん
07/05/28 22:36:54
バリアント型とか知らないのかな。
そして、それが内部的にどうなってるかとか、
そこでのコスト意識とかに至っては、全く考えた事ないんだろうね。

263:デフォルトの名無しさん
07/05/28 22:38:44
>>261
共用体に入れられるのはそもそも POD 型だけだが、
ポインタで保持しておくことなら可能だな。

264:デフォルトの名無しさん
07/05/28 22:54:29
>>262
> バリアント型とか知らないのかな。

C言語でそんなもん使う機会があまりないこととか知らないのかな。(w

265:デフォルトの名無しさん
07/05/28 22:59:44
いや、煽り抜きでそういう発想はちょっとないよね。

266:デフォルトの名無しさん
07/05/28 23:06:16
Cだとバリアント型はにっくきCOMの象徴のひとつだからトラウマが・・・w

267:デフォルトの名無しさん
07/05/28 23:11:53
皆がどのレスについてレスしてるのか分からなくなってきた。
つーかビット演算スレでなぜ共用体…。

「そういう発想」というのは共用体をvariantとして使う発想ということかしら。

268:webmaster@気まぐれアナスイ
07/05/28 23:11:54
   { >>>>>>>>985 }
    ζ
     !(+Φ_Φ)つ√ζ
    +⊂. + 〆∂   {Ж}
    "〆∂∂
   〆〆
  .:"


269:デフォルトの名無しさん
07/05/28 23:15:15
コピペ君って馬鹿だな、まで読んだ。

270:デフォルトの名無しさん
07/05/28 23:38:38
>>256
でも共用体って記述した順番にメモリに保存されるかについて
仕様では未定義ですよね

271:デフォルトの名無しさん
07/05/28 23:40:46
>>270
当たり前だろ。

つか struct の仕様と混同してないか?

272:デフォルトの名無しさん
07/05/28 23:43:42
>>270
これはひどい

273:デフォルトの名無しさん
07/05/28 23:45:43
コンパイラコンパイラ触ってるなら、
このくらい常識だろ?

274:デフォルトの名無しさん
07/05/28 23:46:54
という批判と、このスレでの質問だという事を考えると、>>249 は

typedef union {
  uint32_t *pW;
  uint8_t *pB;
} HogeType;

HogeType a;
uint8_t w;
a.pW = &src;
a.pB[0] ^= a.pB[3];
a.pB[1] ^= a.pB[2];
a.pB[2] ^= a.pB[1];
a.pB[3] ^= a.pB[0];
a.pB[0] ^= a.pB[3];
a.pB[1] ^= a.pB[2];

みたいなのが希望って事か?

275:デフォルトの名無しさん
07/05/28 23:49:33
それは二重に規格違反してて、
おかしくなるコンパイラもあるらしいよ。
俺はそういうの見た事無いけど。

276:デフォルトの名無しさん
07/05/29 00:13:33
おかしくなるコンパイラがあるのではなく、動作が保証されないということ。
そういうコンパイラが現実にあるのかと言われても、んなこと知らん。
だが、顧客に「正常に動作することが保証されている」プログラムを提供するためには
仕様上未定義とされる書き方をしてはいけないし、意識せずしてしまったらバグとして扱われて然り。

277:デフォルトの名無しさん
07/05/29 00:20:53
参考までに>>274の規格違反している点を簡単に指摘してください

278:デフォルトの名無しさん
07/05/29 00:32:45
規格違反していても、多分 >>249 がおかしくなる処理系はないんじゃね?
逆に、規格通り書いてもおかしくなることもある。
規格違反はそれはそれで重要だけど、
実際の処理系でどうなのかという方が時に重要な事もある。
ま、コメントとか残しておいて、
移植時にすぐ検索できるようにしておくべきではあるが。

279:デフォルトの名無しさん
07/05/29 00:44:32
>>277
共用体の pW メンバに代入した場合、
pW の値しか正当性が保証されない。
そのため、pW に代入したすぐ後に pB を参照したとき、
規格ではその動作を保証しない。

uint32_t * と uint8_t * のアドレス表現が等しいという保証は無い。
この間のキャストで何らかの変換作業が生じる場合には、
このコードは正しく動かない。

そもそもアドレス演算は、配列要素へのポインタでしか保証されない
(配列風の参照では p[4] と *(p + 4) は等価で、
 ここには p + 4 というアドレス演算が生じる)。
ここが原因で >>274 のようなことをすると
おかしくなる処理系があるという風に聞いている。
(「ハッカーのたしなみ」 の 87 ページを参照)

280:デフォルトの名無しさん
07/05/29 01:08:03
ハッカーのたしなみ に一致する日本語のページ 約 104 件
ハッカーのたのしみ に一致する日本語のページ 約 26,800 件

281:デフォルトの名無しさん
07/05/29 01:15:26
すまんよ。まちがえた。

282:デフォルトの名無しさん
07/05/29 10:36:39
そもそもCの言語仕様で「未定義」な理由は、最初のバイトが最上位か最下位かはエンディアン依存だから。
逆にいうとハードに強く依存する標準仕様はあってはならない。

もちろん環境が特定できる場合なら、エンディアンの違いを理解して使うぶんにはまったく問題ない。
むしろ同一アーキテクチャでならコンパイラのABIレベルではこういう部分も互換性が保障されてないと駄目。
そもそもエンディアンなんて標準仕様外のものを扱うのに、標準仕様を持ち出すほうがおかしいと思うがね
構造体などのデータアラインメントやABIの互換性は言語の規格じゃなくて
各CPUやOSのメーカー、コンパイラメーカーなど同士の取り決めで決まる。
つーか、暗黙の共通仕様や独自仕様にたよらないとTCP/IPすら扱えないぜ。

283:デフォルトの名無しさん
07/05/29 10:52:02
構造体のアラインメントはC仕様では未定義だが、アラインメント不整合だと例外を起こすアーキもある。
データレイアウトを実装者で取り決める独自仕様が認められないなら、Cは危険な言語だな逆にいえば。

「仕様では未定義」は逆にいえば実装では各環境のABIに従ってきめていいということ。


284:デフォルトの名無しさん
07/05/29 11:17:39
>>282-283
仕様上未定義を「未定義の動作」と混同していないか。
Cは移植性を高めるため、特定の環境に依存するような仕様はほとんど盛り込まれておらず
よって指摘の通り構造体のメモリ上でのレイアウトも定義されていない。

だが、メンバに正しくアクセスできることは保証されている。

285:デフォルトの名無しさん
07/05/29 11:25:40
実は未定義ではなく実装依存という罠

286:デフォルトの名無しさん
07/05/29 11:38:48
エンディアンの変換はほぼ間違いなくできるがリトルからビッグかビッグからリトルかはエンディアン依存ってことだろ。

逆に>>349が意図しない動きをするコード吐くコンパイラって存在するなら教えてほしい。
変態のCellですら>>349が正しく動くことはABIレベルで保証されてる。
各型のレイアウトを厳密に定義してるからな。

287:デフォルトの名無しさん
07/05/29 11:43:14
共用体で  ビットフィールド を使えば、マシになるかい?

288:デフォルトの名無しさん
07/05/29 12:21:19
>>286
>>276
そして話題はループする。

ABIはCの言語仕様における実装依存の箇所を定めて厳密化するものなので
たとえABIの隙をかいくぐって自分の予期した挙動をさせることができたとしても
それは立派な規格違反。

あと、もし>>282さんと同一人物なら
>そもそもCの言語仕様で「未定義」な理由は、最初のバイトが最上位か最下位かはエンディアン依存だから。
これのソースを頼む。探しているんだが、見つからない(汗

289:デフォルトの名無しさん
07/05/29 12:27:18
規格にないものを扱うのに規格内のルールを持ち出す馬鹿。
windows.hを使うのも規格違反だとか言い出しそうだな

290:デフォルトの名無しさん
07/05/29 12:34:19
厳密にはそうだな。ハンドルをポインタ型とかメチャクチャしたMSは糞。
ちなみに、規格にないものを付け加えるのではなく、規格に抜けているを補うのがABI。
本来は規格に矛盾しないABIを定めなければならない。

ところでここはビット演算についてかたるスレなのか?

291:デフォルトの名無しさん
07/05/29 12:56:10
ミドルエンディアンのこともたまには思い出してやってください

292:デフォルトの名無しさん
07/05/29 13:13:17
GUIがなくてstdioで画面入出力するようなアプリのほうが品質低いと見なすがなうちの顧客は。

「定義するな」なら違反になるが単に未定義のものに一定の動作保証をするだけなら違反じゃない。
何のために#pragmaが規格にあると思ってる。
処理系依存の拡張を、やっていいよと保証すらしてるのが規格だ。

ちなみにunion使った型変換はWindowsでは日常茶飯事だな。ULONG_INTEGERとか。
ここの住人がよく使うであろうMMXやSSEなんかはC用APIなんか、まさに共用体を使った型変換のオンパレード。
それでもパフォーマンスを求める客の「信頼」を得るためにすすんで使うものだ。

ANSI/ISO規格が絶対的に信頼されてて規格外のものは信頼されてないなんて独善的な言い分にすぎん。
getsみたいな危険な関数が野放しにされてるのはなんだね。
極論、信頼性の確保という面ではVC2005のセキュアCRT関数のほうが標準関数よりまとも。

ちなみにポインタをHANDLEという型にtypedefできるのは規定の動作。なんら問題ない。

293:デフォルトの名無しさん
07/05/29 13:37:27
きもちわるいなあ

294:デフォルトの名無しさん
07/05/29 14:40:40
エチケット袋持ってきましょうか?

295:デフォルトの名無しさん
07/05/29 15:10:33
いえ結構。そのまま吐きます

296:デフォルトの名無しさん
07/05/29 15:14:49
キッシュを食うのとエチケット袋を使うのはガキ。

297:デフォルトの名無しさん
07/05/29 17:55:34
「規格違反のプログラム」 は、
特定の環境では動くことが保証されてるかもしれないけど、
全ての環境で動く保証が無い。
だから、そのプログラムが特定の環境でのみ使用される事が決まってるなら、
規格違反でもその環境でちゃんと動作する事が保証されていれば問題ない。
ただ、色んな環境で使われるプログラムであれば、規格通りに作らないといけない。

つまりは要件次第の問題であって、常にどちらかでないといけないみたいな事を言うのは愚。

>>292
gets の使用は規格で推奨されていない。
未だ存在しているのは単に互換性のため。
セキュアCRT関数は安全だが、
GCC でコンパイルしたいような場合には
#if 使って GCC でも大丈夫なようにする必要がある。

あと、ハンドルで問題とされているのは、
ハンドルの値は別にアドレスではないのに
ポインタに入れるようにしている点。
ただ、これは int にしてしまうと安全性が低くなるし、
環境依存という程ちゃんと動かなくなる環境もないしで、
いい hack だと思う。

298:デフォルトの名無しさん
07/05/29 18:53:41
話は逸れるが、ハンドルも全てがアドレス値(ポインタ)でないとは限らない。
ドラッグ&ドロップの処理などでGlobalAllocでメモリ確保したものを
HDROP型へキャストしてやるという事例がある。

ふうんと言われればそれまでのことだけど。

299:デフォルトの名無しさん
07/05/29 18:56:05
それをいうなら、そもそもポインタ(というより左辺値)だってアドレス値とは限らないでしょ?

300:デフォルトの名無しさん
07/05/29 19:02:00
プログラムごとに論理的なアドレス空間を持ってるんじゃないの?
昔、物理的なアドレスを使えば一意だろうと思って使ったら、見事に失敗した。

301:デフォルトの名無しさん
07/05/29 19:09:48
>ハンドルの値は別にアドレスではないのに
#ハンドルの値は別にアドレスとは限らないのに

とするか。

302:デフォルトの名無しさん
07/05/29 19:13:49
まあ、メンバ関数ポインタなんかは
確かにメモリアドレス以上の情報を持ってることもあるけど、
C++ における「アドレス」ってのは、
そういう情報も含むんじゃないのかな。多分。

303:デフォルトの名無しさん
07/05/29 20:07:37
きょうび、1つのCPUでも「アドレス」が3種類くらいあって当たり前だしなぁ


304:デフォルトの名無しさん
07/05/29 20:27:53
Cはアドレスの概念を抽象化したから、Cにはアドレスという概念はないと。
どっかで見た。

305:デフォルトの名無しさん
07/05/29 20:36:02
ところがどっこい&演算子の読み方は・・・

306:デフォルトの名無しさん
07/05/29 21:00:16
アドレス演算子だな。

307:デフォルトの名無しさん
07/05/29 21:24:50
えっ?reference operatorじゃないの?
とか思ったけどそれはC++の話でしたねすいません

308:デフォルトの名無しさん
07/05/29 21:53:21
ANSI C: address operator
別名: reference operator

309:・∀・)っ-○◎●
07/05/30 01:32:06
よーしだんごやさんが燃料投下するぞー
「共用体を使った型変換は、保証されないとむしろ違反」

uint32とuint8[4]の完全なアドレス共用が保証できなければ

・各パートの先頭アドレスの一致
・char型(=1バイト)配列のデータ連続性
という規格で保証された動作に違反することになる。

断言する。
バイトオーダさえ一致すれば、共用体を使ったビット列の直接変換は保証できる。



つーか、規格にない動きまで保証されると規格【違反】なら、
Cコンパイラは現実のアーキテクチャ向けに実装された時点で違反を抱えることになり
空想の産物でなければならないことになるね。

規格外と規格違反を混同してるんじゃないの。
規格にない機能を実装したり独自の制約・動作保証をしたらいけないなんて規約は
規格に存在しない。

310:・∀・)っ-○◎●
07/05/30 01:35:52
RubyはCで書かれてるけどオブジェクトは共用体を巧みに使うことでで実装されてるね。
それでもさまざまなプラットフォームに移植されてるけどwwww

311:デフォルトの名無しさん
07/05/30 01:47:03
最適化でどうなるかとかちゃんと考えてるか?

312:・∀・)っ-○◎●
07/05/30 01:59:18
まあ、パーシャルリード・ライトはモダンアーキテクチャでは遅いから速度面でのメリットないし
バイトオーダーの変換に共用体を持ち出すこと自体は俺としても感心しない。
HDの洗礼受けた人間ならこんな厨コードになるだろう

uint32 bswap(uint32 n) {
n = (n >> 16 | n << 16);
return ((n >> 8) & 0x00FF00FF) | ((n << 8) & ~0x00FF00FF);
}

こんなコードを書く間にもx86なら即値が使えるとか、
PowerPCならAND-NOT命令があるから定数ロードは1個だけでいいとか
アーキの特性を考えながら組む。
速くなるか遅くなるかも実装依存。それがビット演算厨の愉しみ。



書いた後で、「PPCとx86なら組み込みのBSWAPで十分な気もしてきた」とか思うのもまた一興。

313:デフォルトの名無しさん
07/05/30 02:07:16
んじゃ、燃料投下。
--
template<typename Type> static inline void endian(Type & val) {
union foo {Type t; char c[sizeof(Type)];} bar = {val};
std::reverse(bar.c, bar.c + sizeof(bar));
val = bar.t;
}

314:・∀・)っ-○◎●
07/05/30 02:11:59
x86のeaxレジスタは下位半分はaxレジスタであり、ahとalでもある
レジスタそのものが共用体なんですよ。


315:デフォルトの名無しさん
07/05/30 02:18:15
>>313
template<> static inline void endian<int>(int & val) {
union foo {int t; char c[sizeof(int)];} bar = {val};
char tmp = bar.c[0]; bar.c[0] = bar.c[3]; bar.c[3] = tmp;
tmp = bar.c[1]; bar.c[1] = bar.c[2]; bar.c[2] = tmp;
val = bar.t;
}
--
これくらいの特殊化しておかないとw
ついでに言うと、これをどう最適化するかがコンパイラの腕の見せ所。

316:・∀・)っ-○◎●
07/05/30 02:21:07
若本・・・じゃなかった、CellのSPEで実行

#include <algorithm>
#include <stdio.h>
template<typename Type> static inline void endian(Type & val) {
union foo {Type t; char c[sizeof(Type)];} bar = {val};
std::reverse(bar.c, bar.c + sizeof(bar));
val = bar.t;
}
int main()
{
unsigned int i = 0x12345678;
endian(i);
printf("0x%0X\n", i);
return 0;
}

[root@ps3 age]# spu-gcc test.cpp
[root@ps3 age]# ./a.out
0x78563412

317:デフォルトの名無しさん
07/05/30 02:33:39
>>309
混同も何も、そもそも「規格外」とか「規格違反」とかいう用語は規格にあるのか?

318:デフォルトの名無しさん
07/05/30 02:35:52
%0X って意味ねー。
%08X っしょ。

319:・∀・)っ-○◎●
07/05/30 03:08:16
64bitから8ビットだけを取り出して操作するってAESとかCamelliaではありがちな処理なんだよな。
よく最適化されたコードは、MMレジスタからpextrwで16ビットをeaxに転送した後、al, ahを使ってテーブル参照する。

320:デフォルトの名無しさん
07/05/30 08:24:42
気色の悪いHN付ける奴の行動パターンやそこから透けて見えるパーソナリティっていうのは、
どいつもこいつもどうしてこう画一的・類型的で凡庸なんだろうなw

恐らく本人の自己イメージはその正反対なんだろうけどさ。

321:デフォルトの名無しさん
07/05/30 08:41:04
凡庸乙

322:デフォルトの名無しさん
07/05/30 08:48:32
>>320
あなたのその発言もまた 画一的・類型的で凡庸 な事に気付いてての発言だとすれば あなたは勇気がある。
気付いてないなら・・・・・

323:デフォルトの名無しさん
07/05/30 08:56:16
人間なんてみんな一緒だろ。
ハッキリいってイルカよりもマグロの方が頭いいです。
人類の知能は一億年遅れてる。

324:デフォルトの名無しさん
07/05/30 14:10:27
【高速化】ビット演算 0x02


325:デフォルトの名無しさん
07/05/30 20:38:32
俺のアナルも高速化されそうです

326:デフォルトの名無しさん
07/05/31 01:08:47
俺様の射精は低速化されましたが何か?

327:デフォルトの名無しさん
07/05/31 01:34:42
さらに角度までorz....

328:デフォルトの名無しさん
07/05/31 04:34:03
自分の精液を味わって飲んでみましたクセになりそうです

329:デフォルトの名無しさん
07/05/31 09:31:52
【下ネタ化】ビッチ猥談

330:デフォルトの名無しさん
07/06/01 01:04:55
>>328
なんか体調によって味とか変わってくるらしいね。調子がいいときはどんな味がするん?

331:デフォルトの名無しさん
07/06/01 01:06:15
ごめん、sage 忘れた。

332:デフォルトの名無しさん
07/06/01 14:45:44
ごめん、ぬるぽ忘れた。

333:デフォルトの名無しさん
07/06/01 15:11:37
ぬるぽの話題は参照の話題について直接的ないし間接的に関係のあるスレッドでしか出す事は許さん。

334:デフォルトの名無しさん
07/06/01 15:23:11
>>329
それを言うなら「低俗化」では?

335:デフォルトの名無しさん
07/06/01 17:57:17
風俗化

336:デフォルトの名無しさん
07/06/01 18:11:47
Jデッ化

337:デフォルトの名無しさん
07/06/01 18:35:50
つーかおまいらこんなことしてていいの化

338:デフォルトの名無しさん
07/06/01 23:16:16
ばか

339:デフォルトの名無しさん
07/06/02 12:18:51
珍しく最近妙にスレが伸びてると思ったら、こう言う内容だったの化

340:デフォルトの名無しさん
07/06/03 02:25:37
なんじゃゴラァ、おまいらバカ化

341:デフォルトの名無しさん
07/06/03 04:24:42
あ?

342:デフォルトの名無しさん
07/06/19 21:59:45
0000 0001 0011 0010 0110 0111 0101 0100
1100 1101 1111 1110 1010 1011 1001 1000

ってどんな意味のあるビット列ですか?
教えてください。

343:デフォルトの名無しさん
07/06/19 22:04:20
パイオニアだかボイジャーだかのレコード盤に記録されてる奴?

344:デフォルトの名無しさん
07/06/19 22:17:46
Gray Codeだな

345:デフォルトの名無しさん
07/06/19 23:13:20
entity GRAY_CODE_COUNTER is
generic( N : integer := 4 );
port( CK, RESET : in std_logic;
Y : out std_logic_vector(N-1 downto 0));
end GRAY_CODE_COUNTER;
architecture BEHAVIOR of GRAY_CODE_COUNTER is
signal GRAY, COUNT : std_logic_vector(N-1 downto 0);
begin
process ( RESET, CK ) begin
if ( RESET = '1' ) then
COUNT <= (others => '0');
elsif ( CK'event and CK = '1' ) then
COUNT <= GRAY;
end if;
end process;
process (COUNT)
variable BIN : std_logic_vector(N-1 downto 0);
begin
BIN(N-1) := COUNT(N-1);
for I in N-2 downto 0 loop
BIN(I) := BIN(I+1) xor COUNT(I);
end loop;
BIN := BIN + 1;
GRAY(N-1) <= BIN(N-1);
for I in N-2 downto 0 loop
GRAY(I) <= BIN(I+1) xor BIN(I);
end loop;
end process;
Y <= COUNT;
end BEHAVIOR;

346:デフォルトの名無しさん
07/06/19 23:15:55
ううまま うままう うまう うままう

347:デフォルトの名無しさん
07/06/20 12:26:09
>>342
たとえば、機械類なんかの位置あわせの目的で センサーを配置する時に
4入力あれば16箇所の位置を特定できるわけだけど
同時に2つのセンサーが変化するようになってると巧くゆかない。
そこで移動につれて、一つしかセンサーが変化しないような配置方法を考えたのがそのコード。


348:デフォルトの名無しさん
07/06/20 14:21:11
要するに>>342
01 02 03 04 05 06 07 08
09 10 11 12 13 14 15 16
って意味

349:デフォルトの名無しさん
07/06/20 18:58:03
>>347-348が理解できない

350:デフォルトの名無しさん
07/06/20 19:07:00
ばっかー

351:デフォルトの名無しさん
07/06/20 19:09:51
2ビットのグレイコードは、2相エンコーダと呼ばれてる。 機械式のマウスなんかで使われている。
 00 01 11 10 この順番で動けば 順方向 逆方向なら 00 10 11 01 と動くので区別出来る

2進数 00 01 10 11 でいいじゃないと思うだろうけど これだと一度に2ビット変化する箇所が2度出来る
センサーの取りつけに物凄い精度が要求される事になり安価なマウスに採用出来ない


352:デフォルトの名無しさん
07/06/21 00:53:52
ハミング距離でぐぐるといいよ

353:デフォルトの名無しさん
07/06/21 01:35:52
上位ビットから順に加算して途中でやめても、下位ビットの影響がそれより上に及ばない、っていう利点もある。

354:デフォルトの名無しさん
07/06/21 01:46:36
>>353
それ、具体的に教えて。


355:デフォルトの名無しさん
07/06/21 23:48:28
56の余りを求めるビットマスクはどのように書けばいいのでしょうか?

356:デフォルトの名無しさん
07/06/21 23:55:04
商か剰余を求めるビット演算を生成する CGI か何かを昔見かけたような気が・・・。
どこだっけかな・・・。

357:デフォルトの名無しさん
07/06/22 01:08:45
56の余りってなにさ?

358:デフォルトの名無しさん
07/06/22 01:17:06
x % 56でも計算したいんじゃね?

359:デフォルトの名無しさん
07/06/22 07:26:57
x % 56だと 2のベキ乗じゃないからビット演算1発では出来ないな
URLリンク(www.tensyo.com)
ここの後ろの方にビットマスクと繰り返し演算で剰余を求める方法がある

360:デフォルトの名無しさん
07/06/22 07:35:52
定数での除算って、こんなに繰り返し必要だったっけ?
3、4回の演算で書けたような気が・・・って、俺の記憶違いか?

361:デフォルトの名無しさん
07/06/22 07:37:37
それ、もしかしたら、2のべき乗での除算?

362:デフォルトの名無しさん
07/06/22 07:40:38
いや、それなら1回でいけるし。

あれ? 乗算だっけ?

363:デフォルトの名無しさん
07/06/22 07:42:31
ああ、何か乗算だった気もしてきた。スマン。

364:デフォルトの名無しさん
07/06/22 07:50:41
2^N>=b となるNを求める(2^N == 1<<N) ・・・・・ N=6 2^N=64
B=2^N-b ・・・・・・ 64 -56 = 8
C=2^N-1 ・・・・・・ 64 - 1 = 63
while(a>=2*b){ B *(a>>N) + a&C };

while(a >=56*2 ){ 8 *(a>>6) + a&63 };

while(a >=56*2 ){ ( (a>>6) <<3 ) + a&63 };

1ループで3ビット改善するから 32bitなら 最大10回ちょっとのループか

365:デフォルトの名無しさん
07/06/22 08:00:17
56*73 =4088 で 2^12-8 だから
a = ( (a>>12)<<3 ) + a & 4095; を 前段でやれば改善するんじゃないかな 

366:デフォルトの名無しさん
07/06/22 09:49:41
最近のコンパイラは定数の割り算は掛け算に置き換えるね。
56で割るロジックをコンパイルしたら、-1840700269を掛けた後に
ビットシフトと足し算をしていた。それ以上追っかけるのはパス。

367:デフォルトの名無しさん
07/06/22 09:51:15
インテルのコンパイラで a=a%56 の出力はこんな感じ(aはunsigned int)。
LARGE_INTEGER li;
li.QuadPart = UInt32x32To64(a>>3,0x24924925);
int d = li.HighPart;
a -= ((d<<3)-d)<<3;

aがsigned intの場合は、もう少し複雑。

368:デフォルトの名無しさん
07/06/22 10:11:46
なるほど、>366の数値が0x92492493だからシフト量が違う同じビットパターンなのか。

369:デフォルトの名無しさん
07/06/22 10:17:29
でもまあPCのCPUみたいに掛算が高速だったらって前提だな。
1チップとかだと 掛算はビットサイズに応じたサイクル数かかるし
掛け算持ってないCPUもあるし

370:デフォルトの名無しさん
07/06/22 10:21:39
大丈夫、そういうCPUは割り算も遅い。

371:デフォルトの名無しさん
07/06/22 10:26:29
a = ( (a>>18)<<3 ) + a & ((1<<18)-1);
a = ( (a>>12)<<3 ) + a & 4095;
a = ( (a>>9)<<3 ) + a & 511
a = ( (a>>6) <<3 ) + a & 63;
a = ( (a>>6) <<3 ) + a & 63;
while(a>=56) a-=56;

これならどうだろ?

372:デフォルトの名無しさん
07/06/22 10:34:31
演算子の数が20を超えてるな。
素直にdiv使った方が速いかもしれない。

373:デフォルトの名無しさん
07/06/22 10:45:50
もうちょっとバランスをうまく取れば、1行減らせるかもな

374:デフォルトの名無しさん
07/06/22 11:08:06
結局 3bit 単位だからなあ

最初は
a = ( (a>>15)&(-7) ) + a & ((1<<18)-1);

a = ( (a>>12)&(-7)) + a & ((1<<15)-1);
のどっちかで、どっちも32->18.4bit
次は
a = ( (a>>6)&(-7) ) + a & 511  でも12.5bit
a = ( (a>>9)&(-7) ) + a & 4095; でも12.5bit

あとは3ビットづつしか落とせない。 無理

375:デフォルトの名無しさん
07/06/22 11:17:53
あ、
a = ( (a>>18)<<3 ) + a & ((1<<18)-1);
a = ( (a>>12)<<3 ) + a & 4095;
a = ( (a>>6) <<3 ) + a & 63;
a = ( (a>>6) <<3 ) + a & 63;
while(a>=56) a-=56;
とやれば、最後の while はせいぜい3回のループでいいか


376:デフォルトの名無しさん
07/06/22 11:26:49
>>372
div 命令は、持っていてもbit数のサイクルかかるのが殆どだよ。 だから >>366-367 のような最適化がされるんだし

377:デフォルトの名無しさん
07/06/22 11:33:21
ただ PC の場合はレイテンシがかかるだけだから、divを使った方が速いかもしれないな。


378:デフォルトの名無しさん
07/06/22 11:37:09
>>367
ここまでしても idiv より速いのか・・・。

379:デフォルトの名無しさん
07/06/22 11:48:18
Pentium II およびPentium III プロセッサの実行ユニット

整数乗算は レイテンシ4、スループット1/ サイクル
除算は浮動小数点ユニットで行われ
FDIV 命令 レイテンシ: 単精度17 サイクル、倍精度36 サイクル、拡張精度56 サイクル

だから、桁違いにレイテンシが大きい。


380:デフォルトの名無しさん
07/06/22 11:50:39
浮動小数点ユニットで行われるのか?!

381:デフォルトの名無しさん
07/06/22 11:58:11
だって 整数乗算ユニットってのはブロック図にあるが、 整数除算ユニットってのはどこにも無いだろ?

除算ってのはコストのわりに利用頻度が少ないから、どうせ浮動小数点ユニットもってるからそっちで計算させてるのさ
仮に、整数演算ユニットで除算をしたとしても、結局32サイクルはかかるし、その間加減算比較ユニットの一つが潰れてしまうからな

382:デフォルトの名無しさん
07/06/22 12:14:11
そうだったのか・・・。
そら遅いわな。

383:デフォルトの名無しさん
07/06/22 12:27:02
>>381
これ以上はスレ違いになるがつっこませてくれ。
浮動小数点ユニットがIEEE754(だったっけ)で処理する場合、単精度で23ビット、倍精度で52ビットの精度だろ。
被序数が32ビット整数ならともかく、64ビット整数の除算は精度の問題上アウトだぞ。

384:デフォルトの名無しさん
07/06/22 12:34:23
>>383
Intel 系の浮動小数点ユニットは
拡張倍精度(80ビット/仮数部64ビット)で行われてるから大丈夫。

385:デフォルトの名無しさん
07/06/22 12:44:20
>>384
まじか!と思って何年も開いていない重たいバインダーを紐解いてみたら、たしかにそう書かれているな。
しかも本当は63ビット精度なのに、ケチりビットをケチらない荒技で対処してるし・・・。
そのうえx87コプロに限ればつねに拡張倍精度で計算されることになってたりして、もうね、馬(ry。

386:デフォルトの名無しさん
07/06/22 13:02:46
56 = 7*2^3 だから

x % 56 = (x % 7)<<3 + (x & 7)

x/7 を round(2^32/7 )>>32 で近似したのが >>367


387:デフォルトの名無しさん
07/06/22 13:07:24
しかし、1/7って面白いなぁ。10進だけでなく16進でも綺麗な循環小数になるんだな。

388:デフォルトの名無しさん
07/06/22 13:08:10
もしかして >>375 のような事しても idiv 使うより速いって事はありえるのか?

389:デフォルトの名無しさん
07/06/22 16:51:54
>>388
実際に速度を比較してみれば?

Cの場合、&より+の方が優先順位が高いので、
>>375の&演算には括弧が必要だね。

390:デフォルトの名無しさん
07/06/22 17:06:59
そうだね。

391:デフォルトの名無しさん
07/06/22 18:03:24
やってみた。

function getRDTSC: int64;
asm   DW  $310F //RDTSC
end;
var ww:Integer;
procedure TForm1.Button1Click(Sender: TObject);
const CNT=100000;
var t1,t2,t3:int64;
i,a:Integer;
begin
t1:=getRDTSC;
 for i := 1 to CNT do begin
  a := i;
  a := ((a shr 15) and 7) + (a and ((1 shl 18) - 1));
  a := ((a shr 9) and 7) + (a and 4095);
  a := ((a shr 3) and 7) + (a and 63);
  a := ((a shr 3) and 7) + (a and 63);
  while a >= 56 do a := a - 56;
  ww:=a; {mod と同じになるように}
 end;
t2:=getRDTSC;
 for i := 1 to CNT do ww:=i mod 56;{ローカル変数に代入すると最適化で消えるので}
t3:=getRDTSC;
Memo1.Lines.Add(format('T2-T1 %10d',[t2-t1]));
Memo1.Lines.Add(format('T3-T2 %10d',[t3-t2]));
end;
---------------
T2-T1 1610740
T3-T2 4317497
間違いでなければ mod 命令より速い

392:デフォルトの名無しさん
07/06/22 18:06:18
そうだね。

393:デフォルトの名無しさん
07/06/22 18:09:15
上の and 7 は  and -8 の間違いだった

394:デフォルトの名無しさん
07/06/22 18:33:37
でも、掛算を使うのはさらに半分だった。

for i := 1 to CNT do
begin
a := i shr 3;
asm
   mov eax,$24924925;
   IMUL a;
   mov a,EDX;
end;
ww := i - ((a * 7) shl 3);
// if ww<> (i mod 56) then Memo1.Lines.Add( 'Err');
end;
t4 := getRDTSC;
T2-T1 169613675
T3-T2 436034967
T4-T3 86040347


395:デフォルトの名無しさん
07/06/22 18:40:43
 結局 idiv : ビット演算 : 掛算の 重さは およそ 5 : 2 : 1 だった。

ビット演算 思ったよりガンバレるな。

396:デフォルトの名無しさん
07/06/22 19:24:47
これを高級言語で書いたら他の人に白い目で見られるだけならまだいいんだけど
ひどい場合は書き直しすら命じられまする(´・ω・`)

397:デフォルトの名無しさん
07/06/22 19:44:35
そうだね。

398:デフォルトの名無しさん
07/06/22 20:36:07
>>396
高級言語の目的の一つが可読性の向上だからね。
コメントで解説いれても却下される場合すらあると思うよ。


399:デフォルトの名無しさん
07/06/22 20:48:20
除算命令がないCPUなら有効だろうけど
x % 60 が欲しい時とか、いちいち変換が大変だよな

400:デフォルトの名無しさん
07/06/22 21:47:03
導出は機械的なプロセスだから、スクリプトみたいなのでサクッと求めるといいと思う。
可能なら、最適化の一環としてコンパイラに組み込むのがベストだが。

401:デフォルトの名無しさん
07/06/22 23:23:02
だから、掛け算化はgccでもやってるって。

402:デフォルトの名無しさん
07/06/23 00:18:01
>>401
ほんとにやってる?やらない場合も多いけど
絶対さぼってる

403:デフォルトの名無しさん
07/06/23 01:26:20
昔のx86みたいにALUしかないCPUはそういう風にやってたのかぁ、勉強になりました。

404:デフォルトの名無しさん
07/06/23 01:29:46
>>403
定数割り算の掛け算化が行われない例があれば、逆に教えて欲しい。
まさか、最適化オプションを指定しないとしてくれないなんて言わないよね。

405:デフォルトの名無しさん
07/06/23 01:31:50
>>404
深く考えず単純に引き算かと
今考えると空恐ろしいやり方だw

406:デフォルトの名無しさん
07/06/25 10:58:28
>404は>402宛てなんだろうなぁ。それはいいけど、>405は何を言いたいのだろう……

407:デフォルトの名無しさん
07/06/25 19:13:34
きっと8086には除算命令が無いと思ってるんだろう。

408:デフォルトの名無しさん
07/06/25 19:57:27
Pen3では除算を浮動小数点ユニットでされるというのを見て、
浮動小数点ユニットが無い時には除算も無かったと思ったのかな

除算そのものはシフト減算比較の繰り返しで出来るから
サイクル数さえ必要なだけかければマイクロプログラム方式ならそうコストかからない
掛け算と変わらない。

409:405
07/06/26 07:50:34
>>406
あ、ほんとだね
>>407,408
んにゃ、引き算の連続で商余求めてたのかなと

410:デフォルトの名無しさん
07/06/26 08:23:37
これは固定での剰余だから高速化出来るのであって
変数での剰余になると、結局コードで書いても加え戻し法(復元法)とかになるので
除算命令使った方がやっぱり速い。

411:デフォルトの名無しさん
07/06/28 00:42:51
DSP(やCell)では逆数をニュートン法で求めるのが定番

412:デフォルトの名無しさん
07/07/08 16:40:57
8086で除算命令使うとCPUの方で乗算とシフト命令に解釈しなおす訳?
ということは除算命令自体はマクロになるのかな

413:デフォルトの名無しさん
07/07/08 18:16:20
は?

414:デフォルトの名無しさん
07/07/08 19:57:33
除算命令に出くわして、せっせとメモリ中のコードを書き換える、けなげな86の姿を想像した・・・

415:デフォルトの名無しさん
07/07/11 22:50:58
言う事聞かない奴隷なんかいらない

416:デフォルトの名無しさん
07/07/21 07:45:05
>>412
マイクロプログラムで処理してるんだろ
>8086のマイクロコードは、命令長が21ビットで、プログラムサイズは504ステップであった


417:デフォルトの名無しさん
07/07/21 10:07:54
そろそろダンゴさんに〆てもらうか。

418:デフォルトの名無しさん
07/07/21 21:50:22
うむ

419:デフォルトの名無しさん
07/08/03 07:04:32


420:デフォルトの名無しさん
07/08/03 11:40:01
ダゴンを深淵から呼びだしては駄目だ

421:だんごの輪島
07/08/03 12:15:43
ん?

422:デフォルトの名無しさん
07/08/03 21:06:03
は?

423:デフォルトの名無しさん
07/08/12 09:53:59


424:デフォルトの名無しさん
07/08/12 10:01:53
ビッチ演算

425:デフォルトの名無しさん
07/08/12 14:27:31
ビット大佐

426:デフォルトの名無しさん
07/08/14 10:07:39
age

427:デフォルトの名無しさん
07/08/14 11:48:05


428:デフォルトの名無しさん
07/08/16 20:39:50


429:デフォルトの名無しさん
07/08/18 23:05:50
あgw

430:デフォルトの名無しさん
07/08/18 23:09:42
ぬるぽ

431:デフォルトの名無しさん
07/08/20 01:29:30
ちょっとスレの趣旨と違うと思うんだけど、適当なところが無かったので、
アドバイス頼む。

アドレスのアライメントをチェックするためにポインタをintにキャストして
&でビットテストしてる。

extern char *p;
if(((int)p & 3) == 0){
//32bit境界にある処理…
}

だけどアドレスをintにキャストするのは64bit時代的に行儀悪いみたい。

でもアドレスをビットテストしたいという状況は普通にあると思うんで、
こういう場合C系的にはどう書くのが上手な作法なの?

432:デフォルトの名無しさん
07/08/20 01:38:30
>>431
Linux界隈じゃ unsigned long へのキャストが一般的とされてるが
個人的には嫌い

433:デフォルトの名無しさん
07/08/20 01:40:50
intptr_t / uintptr_t を使えばいいんじゃない?

434:デフォルトの名無しさん
07/08/20 08:48:31
下位ビットだけ入ればいいので、charでもいい

435:デフォルトの名無しさん
07/08/20 23:58:10
さすがにそれはありえないだろ?

436:デフォルトの名無しさん
07/08/21 00:11:51
なぜそう思うの?

437:デフォルトの名無しさん
07/08/21 00:33:14
バイトオーダー

438:デフォルトの名無しさん
07/08/21 00:37:00
バイトオーダーは関係ないかと

439:・∀・)っ-○◎●
07/08/21 00:52:14
WindowsならUINT_PTRにキャスト


440:デフォルトの名無しさん
07/08/21 01:00:01
ダンゴさんがピシっと〆めたな。

441:・∀・)っ-○◎●
07/08/21 01:19:06
うんこうんこうんk

442:デフォルトの名無しさん
07/09/09 23:01:40


443:デフォルトの名無しさん
07/09/09 23:35:23


444:デフォルトの名無しさん
07/09/09 23:37:25


445:デフォルトの名無しさん
07/09/09 23:45:20


446:デフォルトの名無しさん
07/09/16 06:34:05


447:デフォルトの名無しさん
07/09/19 12:28:31


448:デフォルトの名無しさん
07/09/19 12:32:11


449:デフォルトの名無しさん
07/09/19 13:50:16


450:デフォルトの名無しさん
07/09/19 23:03:56


451:デフォルトの名無しさん
07/09/19 23:56:29


452:デフォルトの名無しさん
07/09/20 00:04:43


453:デフォルトの名無しさん
07/09/20 18:42:49
>>450-452
ガ

454:デフォルトの名無しさん
07/09/22 00:43:27
スレリンク(tech板:555番)
これもっと簡単にならないかな?

455:デフォルトの名無しさん
07/09/22 07:06:58
>>454
--------------------
int my_fputwc(wint_t c, FILE *fp)
{ wint_t r = fputwc(c, fp);
return (r == WEOF) ? EOF : r;
}

int wtbl[0x10000];
void dokkade_jikkou(void ) {
int i;
for (i = 0; i < 0x10000; i++)
wtbl[i] = i;
wtbl[0xffff] = EOF;
}
int my_fputwc(wint_t c, FILE *fp) return wtbl[fputwc(c, fp);]; }

みたいなこと(WEOF(wint_tの0xffff)をEOF(intの-1)に変換)
をもっとスマートに行う方法ないですかね。
---------これで何の不満があるんだ?-----------
wtbl[0xffff] = EOF;
for (i = 0; i < 0xffff; i++)
wtbl[i] = i;
}
--------------------


456:デフォルトの名無しさん
07/09/27 20:24:00
age

457:デフォルトの名無しさん
07/09/29 23:03:31
int rotate_0_9(int a){a++;return(a+(((a+6)>>4)+(((a+6)>>4)<<1))<<1)&15;}
or
int rotate_0_9(int a){a++;return(a+((a+6)>>4)*6)&15;}

引数が0~8の時1を加算し、引数が9の時0を返す。

458:デフォルトの名無しさん
07/09/29 23:17:24
return ++a%9;

459:デフォルトの名無しさん
07/09/29 23:39:43
% はビット演算じゃないだろう

460:デフォルトの名無しさん
07/09/29 23:58:36
int rotate_0_9(int a){return a<9?a+1:0;}

461:デフォルトの名無しさん
07/09/30 00:06:34
DAA

462:デフォルトの名無しさん
07/09/30 00:15:35
>>457
>>458
>>460
どれが速い?

463:デフォルトの名無しさん
07/09/30 00:20:18
実測あるのみ

464:デフォルトの名無しさん
07/09/30 00:34:05
試してみた!
cl /O2 rot9.c
rot9
rotate_0_9_457_1 1873 msec
rotate_0_9_457_2 1272 msec
rotate_0_9_458 4016 msec
rotate_0_9_460 641 msec
>>460が圧倒的だった(俺もそう思ってた)

ソースに続く


465:デフォルトの名無しさん
07/09/30 00:34:50
>>464のソース (VC6SP4)
----------------------------
#include <windows.h>
#include <stdio.h>
int rotate_0_9_457_1(int a){a++;return(a+(((a+6)>>4)+(((a+6)>>4)<<1))<<1)&15;}
int rotate_0_9_457_2(int a){a++;return(a+((a+6)>>4)*6)&15;}
int rotate_0_9_458(int a){return ++a%9;}
int rotate_0_9_460(int a){return a<9?a+1:0;}
//#define COUNT_TIMES 0x7fffffff
#define COUNT_TIMES 0x7ffffff
#define TEST(func) \
dwTime = GetTickCount(); \
for(i = 0, count = 0; count < COUNT_TIMES ; count++) { \
i=func(i); \
} \
printf( # func " %d msec\n", GetTickCount() - dwTime);
main() {
int i, count;
DWORD dwTime;
SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS);
Sleep(100);
TEST(rotate_0_9_457_1)
Sleep(100);
TEST(rotate_0_9_457_2)
Sleep(100);
TEST(rotate_0_9_458)
Sleep(100);
TEST(rotate_0_9_460)
return 0;
}
----------------------------


466:デフォルトの名無しさん
07/09/30 00:38:34
printf( # func " %d msec (i:%d)\n", GetTickCount() - dwTime, i);
と変更して計算結果も表示してみたら>>457の最初の式の結果がおかしい事に
気付いたんだけど。

rotate_0_9_457_1 1862 msec (i:0)
rotate_0_9_457_2 1272 msec (i:7)
rotate_0_9_458 3986 msec (i:7)
rotate_0_9_460 671 msec (i:7)

467:デフォルトの名無しさん
07/09/30 00:40:00
int rotate_0_9_467(int a){
static int t[10]={1,2,3,4,5,6,7,8,9,0};
return t[a];
}
表引き。
これもやってみてくれ。

468:デフォルトの名無しさん
07/09/30 00:49:01
>>457
やってみるよ。

457_1のiの推移
0 2 6 14 4 10 12 0 2 6 14 4 10 12 0 2 6 14 4 10 12 0 2 6 14
無茶苦茶だった。

469:デフォルトの名無しさん
07/09/30 00:55:09
rotate_0_9_457_1 1893 msec (i:0)
rotate_0_9_457_2 1272 msec (i:7)
rotate_0_9_458 3996 msec (i:7)
rotate_0_9_460 661 msec (i:7)
rotate_0_9_467 621 msec (i:7)

テーブル引きのがわずかに速いね。
>>460>>467が微差だったんでカウンタ倍にしてみた。
#define COUNT_TIMES 0xfffffffに変更。

rotate_0_9_457_1 3535 msec (i:2)
rotate_0_9_457_2 2553 msec (i:5)
rotate_0_9_458 7991 msec (i:5)
rotate_0_9_460 1332 msec (i:5)
rotate_0_9_467 1202 msec (i:5)

計ったPCはThinkPad X31 (PenM1.6G Banias) XPSP2

470:デフォルトの名無しさん
07/09/30 00:57:00
あと>>458は0~8の繰り返しで条件が違うんで
int rotate_0_9_458(int a){return ++a%10;}
に修正してる

471:デフォルトの名無しさん
07/09/30 01:13:29
_rotate_0_9_457_2 PROC NEAR
; 13 : int rotate_0_9_457_2(int a){a++;return(a+((a+6)>>4)*6)&15;}

mov ecx, DWORD PTR _a$[esp-4]
inc ecx
lea eax, DWORD PTR [ecx+6]
sar eax, 4
lea eax, DWORD PTR [eax+eax*2]
lea eax, DWORD PTR [ecx+eax*2]
and eax, 15
ret 0
_rotate_0_9_457_2 ENDP
掛け算消えるんだね

_rotate_0_9_458 PROC NEAR
; 14 : int rotate_0_9_458(int a){return ++a%10;}
mov eax, DWORD PTR _a$[esp-4]
mov ecx, 10
inc eax
cdq
idiv ecx
mov eax, edx
ret 0
_rotate_0_9_458 ENDP
見るからに遅そうな


472:デフォルトの名無しさん
07/09/30 01:16:44
_rotate_0_9_460 PROC NEAR
; 15 : int rotate_0_9_460(int a){return a<9?a+1:0;}
mov eax, DWORD PTR _a$[esp-4]
cmp eax, 9
jge SHORT $L53312
inc eax
ret 0
$L53312:
xor eax, eax
ret 0
_rotate_0_9_460 ENDP
普通だね

_rotate_0_9_467 PROC NEAR ; COMDAT
mov eax, DWORD PTR _a$[esp-4]
mov eax, DWORD PTR _?t@?1??rotate_0_9_467@@9@9[eax*4]
ret 0
_rotate_0_9_467 ENDP
短いね
この短さがテーブル参照のオーバーヘッドを相殺してる?
けどaが10以上だったら脂肪

473:デフォルトの名無しさん
07/09/30 01:27:47
まあ表引きはキャッシュから外れた時にペナルティがあるから
平均的には>460がいいんだろうな。

474:デフォルトの名無しさん
07/09/30 02:05:05
>>473
確かに、別の環境だと逆転してたり。

#Celeron 430@2.4G XPSP2
rotate_0_9_457_1 1750 msec (i:2)
rotate_0_9_457_2 1359 msec (i:5)
rotate_0_9_458 2969 msec (i:5)
rotate_0_9_460 719 msec (i:5)
rotate_0_9_467 860 msec (i:5)

#Core2Duo 4300@3.2G XPSP2
rotate_0_9_457_1 1281 msec (i:2)
rotate_0_9_457_2 1000 msec (i:5)
rotate_0_9_458 2172 msec (i:5)
rotate_0_9_460 516 msec (i:5)
rotate_0_9_467 656 msec (i:5)


475:デフォルトの名無しさん
07/09/30 04:40:29
%は割り算があるから遅いってことか。0~9ではなく0~2^n-1の場合にかぎり使えばいいかな。
でも実際の仕事では0~99のローテートでも%で書いたりするなあ。

476:デフォルトの名無しさん
07/09/30 08:29:40
剰余は定数除算よりも更に遅い。

477:デフォルトの名無しさん
07/09/30 09:14:40
その剰余をビット演算でなんとか...

478:デフォルトの名無しさん
07/09/30 10:11:46
このスレの355から、剰余をビット演算でする方法が書かれているよ。

入力が必ず0~9なら
a=((a+7)&15)-6;  // 0~8 が 1~9 9が-6

(aの符号拡張か 4bitの算術右シフト結果)のビット反転と and


479:457
07/09/30 23:43:50
ふぬぅ、やっぱ分岐しない上にテーブルも使わない奴は遅いな。

480:デフォルトの名無しさん
07/09/30 23:45:02
逆に考えて、分岐する上にテーブルも使う奴は・・・


すまん、逆に遅くなりそうだ。

481:デフォルトの名無しさん
07/10/01 16:44:48
modも内部的には分岐してるだろ。RISCならよくわかる。

482:デフォルトの名無しさん
07/10/01 17:41:59
え~(*o*) それは2のn乗の場合とそうでないので分けてるとか?

483:ヽ・´∀`・,,)っ━━━━━━┓
07/10/04 02:56:19
剰余 = 披除数 - (除数 * 商)


一般的には商と剰余は同時に求めることが可能

484:デフォルトの名無しさん
07/10/21 17:07:33
age

485:デフォルトの名無しさん
07/10/21 18:36:55
剰余のビット演算への変換ならこのページにあるよ。
URLリンク(www.tensyo.com)

縛りを入れるともっと高速化出来そう…


486:デフォルトの名無しさん
07/10/23 00:23:05
ある変数の値が

2018か2019
4049か4050
であるか判別する方法は4回比較するしか
ないかな?

487:デフォルトの名無しさん
07/10/23 00:49:07
愚直な方法だけど比較2回には減らしてみた。
bool check(int value) {
const int mask = ~1;
if( (value & mask) == 2018 || ((value + 1) & mask) == 4050 ) return true;
return false;
}

488:デフォルトの名無しさん
07/10/23 01:56:04
テストしてないけど。
bool check(int value) {
const int mask = ~1;
if (((abs(value - 3034) + 1) & mask) == 1016) return true;
return false;
}


489:デフォルトの名無しさん
07/10/23 09:11:06
AND も加算も比較=減算も、演算量は同じ、ってこと考えたら、どっちも減ってない。
比較4回に比べてリーダビリティは下がってる。

490:デフォルトの名無しさん
07/10/23 09:53:31
switch (value) {
case 2018: case 2019: case 4049: case 4050:
  doit();
}


491:デフォルトの名無しさん
07/10/23 11:06:26
if (v == 2018 || v == 2019 || v == 4049 || v == 4050) return 1;
return 0;
0m48.123s
0m2.250s

const int mask = ~1;
if ((v & mask) == 2018 || ((v + 1) & mask) == 4050) return 1;
return 0;
0m53.281s
0m2.278s

const int mask = ~1;
if (((abs (v - 3034) + 1) & mask) == 1016) return 1;
return 0;
0m52.661s
0m2.167s

switch (v) {
case 2018: case 2019: case 4049: case 4050:
return 1;
}
return 0;
0m46.065s
0m2.087s

if (v < 2018 || (v > 2019 && (unsigned int) (v - 4049) > 1)) return 0;
return 1;
0m45.938s
0m2.086s

いろいろ測ってみた
コンパイラやマシンによって違うと思うけど

492:デフォルトの名無しさん
07/10/23 11:25:06
4回比較より下の2つのが短いのが不思議ですね。
入力が多数回で、4つの値が均等にバラつくという条件にしたら、最後まで演算しない4回比較
がイイかと思えますが。

493:デフォルトの名無しさん
07/10/23 11:26:33
>>489
可読性も考慮するの?このスレで?

494:デフォルトの名無しさん
07/10/23 11:29:15
ちなみに最後の一個はswitchバージョンのアセンブル出力をCに直したもの

495:デフォルトの名無しさん
07/10/23 12:45:37
iccで試してみた。
# icc -xP -O3 -ip
# icc 10.0
上から、0.3, 0.23, 0.33, 0.3, 0.22[sec/(10000 * 10000call)]だった。
どうやらswitchで書いても一番上と同じような出力になるようだ。
gccでも試してみた。
# gcc -O3 -funroll-loops
# gcc 3.4.6
こちらは、0.16, 0.22, 0.27, 0.17, 0.22[sec/(10000 * 10000call)]だった。
なんでこんなに速いんだ?w

496:デフォルトの名無しさん
07/10/23 21:35:27
>>495
アセンブリコードで比較してみると分かるんじゃね?

497:デフォルトの名無しさん
07/10/23 23:12:05
俺には>>486
if(v==2018||v==2019){
}else if(v==4049||v==4050){
}else{
}
って条件に読めるんだが

498:デフォルトの名無しさん
07/10/23 23:17:57
俺も俺も

499:デフォルトの名無しさん
07/10/24 00:23:34
>>486
日本語でおk

やっと言う側に回れたか

500:デフォルトの名無しさん
07/10/24 01:05:28
>>497
いや、今日きちんとみかか村に出撃して
糞仕様について問い詰めてきたけど

case 2018: case 2019: case 4049: case 4050:

で正しい

どうもみんなありがとう

501:デフォルトの名無しさん
07/11/02 19:56:43
>491
>if (((abs (v - 3034) + 1) & mask) == 1016) return 1;
ここら辺の数値の導き方教えてください
どいった関係で3034とか出すの?ど素人ですんません

502:デフォルトの名無しさん
07/11/02 20:15:08
>>501
2018+4050=2019+4049=3034+3034

v = [2018 or 2019 or 4049 or 4050] の時
abs(v - 3034) = [1015 or 1016]
abs (v - 3034) + 1 = [1016 or 1017]
mask=0xfffffffeより奇数はそれを超えない偶数に変換される。
(abs (v - 3034) + 1) & mask = 1016


503:デフォルトの名無しさん
07/11/02 21:44:43
>502
ものっそい感動しました
久しぶりに成長した気がする
この括り方すげー

504:デフォルトの名無しさん
07/11/03 20:48:03
もはや逆方向にソースから動作仕様を求めることはほぼ不可能だな

505:デフォルトの名無しさん
07/11/04 06:35:34
かっこいい BIN→BCD は?

506:デフォルトの名無しさん
07/11/04 08:47:47
速さなら、00h,01h,02h・・・を表に持ち、binで表引き。 <99のチェックは必要。
サイズなら、((bin/16)<<4) | (bin%16) ・・・バイト版。 <99のチェックは必要。
ワードは、/100の商と余りに分けて、上のを呼び、合成。
自分で書いたのはこんな当たり前の奴だなあ・・・

507:デフォルトの名無しさん
07/11/10 16:03:38
しばらく前はメモリアクセスがからむテーブル参照の方が重いって話だったけど、
また状況変った?




508:デフォルトの名無しさん
07/11/10 16:47:46
キャッシュの容量
メモリアクセス速度とキャッシュアクセス速度の比率
によって変わるからなあ
細かくいいだすとキャッシュ方式も絡むし
結局「場合による」んじゃねえの

509:デフォルトの名無しさん
07/11/10 17:28:19
一般論としては、キャッシュに載っている(=頻繁に呼ばれる)ならテーブルの方が速いんじゃないかね。
ただ、この場合の「一般」というのは、分岐が含まれる(=分岐ミスの可能性がある)という前提。

例えば上の((bin/16)<<4) | (bin%16) の場合だと
依存関係が2箇所あって、その部分は同時実行は出来ないけど
キャッシュアクセスに要する数クロック程度の時間と比べてどちらが速いかはわからんね。

テーブルジャンプ(ほぼ同じ値が続く場合以外)は糞だけど。

510:デフォルトの名無しさん
07/11/10 17:37:19
掛けたり割ったりすることにものすごい抵抗感がある

511:デフォルトの名無しさん
07/11/10 18:06:01
いや、この場合に限れば、まず間違いなく最適化でシフトやアンドになるよ。

512:506
07/11/11 02:32:03
今のチップで乗除算持ってないほうが珍しいよね。俺が書いたのは3MHzの8085だったから、
キャッシュ云々の話はなし。/100だけは除算ルーチン使わないとだめだった。

513:デフォルトの名無しさん
07/11/11 13:44:02
ARMは現役のチップだけど除算命令なかったような

514:デフォルトの名無しさん
07/11/14 11:40:49
x/100 は 掛け算があるなら
655*( x + x/2048 + x/16384)/ 65536


515:デフォルトの名無しさん
07/11/14 14:14:26
その掛け算とシフトの計算量なら、100=64hだから、分母の<<2と<<5と<<6を引いたほうが・・・

516:デフォルトの名無しさん
07/11/14 15:57:51
y = (655*x)>>16 で概算して

while ( x-y*100>=100 ) y++;

ならせいぜいループ1回だろ

517:デフォルトの名無しさん
07/11/14 18:05:59
最低でもx<6557202(≒(1<<32)/655)が言えなければ。

518:デフォルトの名無しさん
07/11/14 18:34:29
>>512

(42949672*x+65536)>>32

519:デフォルトの名無しさん
07/11/15 07:36:11
シフト演算子がアンカーになってしまう(w
>>514-516 は、たぶん数学的には同等なような気がする。

>>518 それ、どういう原理なの? 32シフトしたら全部なくなっちゃうような気が・・・

520:デフォルトの名無しさん
07/11/15 08:53:19
32bitレジスタ持ってるような16bit以上のCPUを想定してるんだろ

x386なら32x32bit掛け算の結果が2つのレジスタに判られるから 32bitシフトは上位のレジスタを採用するだけになる。

521:デフォルトの名無しさん
07/11/15 11:57:03
&gt;&gt;32
>>32

522:デフォルトの名無しさん
07/11/15 12:18:01
>>512
>>‍32

523:デフォルトの名無しさん
07/11/15 12:22:04
>>521
>>522
何が言いたいのか意味不明だ。

524:デフォルトの名無しさん
07/11/15 12:29:42
>>523


525:デフォルトの名無しさん
07/11/15 12:42:20
これでどうだ

x >> 32

526:デフォルトの名無しさん
07/11/15 12:44:23
俺他人だけど >>‍523 色が違うだろって言いたいんじゃないのかな?


527:デフォルトの名無しさん
07/11/15 13:11:18
>>523
こうすればいいのよ(たぶん)

528:527
07/11/15 13:12:44
>>‍527
吊ってくるorz


529:518
07/11/15 16:36:17
>>520
あたり。
あと、>>518のxは0~65535の範囲である必要がある。


530:デフォルトの名無しさん
07/11/15 16:54:12
多少ステップ数がかかるように見えても、まだハードウエア除算は普通の命令20個分以上に重いからな
1/100 は1/10のルーチンを2度呼んでたな。

1/10は1/2/5 だから1ビットシフトしてから5で割る
65536/5=13107.2 だから13107を係数に使うと誤差は16bitの範囲で1
だけど1ビットシフトしてるから、15bitの範囲になってるから 最大誤差は0.5なんでOK
という事で、最大誤差の0.5を足して

x = x / 2
x = (13107*x+ 6553) / 2^16

を2度繰り返す


531:デフォルトの名無しさん
07/11/16 01:35:07
>>518 や、>>530 は余りも一緒に求まるの?

532:デフォルトの名無しさん
07/11/16 08:46:49
この話は掛け算が高速ならという話だから
余りは後から y=x/N を求めた後 x-N*y で求めればいい

余りだけが必要なら355付近から話題が出てる

533:デフォルトの名無しさん
07/11/16 09:53:08
実測で、ハードウェアまたはCの除算を上回るルーチン作れるの?うpして
動かしてみる辛さ

534:デフォルトの名無しさん
07/11/16 10:26:25
どっかのスレでやってたでしょ。
パソコンの除算命令はレイテンシが大きいから連続して実行させるととても重くなる。
ただ整数ユニットでは実行されないから、その間に他の命令を入れられるならOK


あ、このスレか、>>367-379

535:デフォルトの名無しさん
07/11/16 10:59:28
int型の除算で標準のものより速いものは作れるのか作れないのか?

536:デフォルトの名無しさん
07/11/16 11:03:08
分母が固定なら可能。 変数なら無理。 

537:デフォルトの名無しさん
07/11/16 11:04:47
まてよ。分子が固定な場合、ニュートン法である程度いけるかな・・・・まあ無理か

538:デフォルトの名無しさん
07/11/16 11:23:21
分母が固定ならif文などで分岐すれば、総合的には速度が上げられるのか?
作ってくれ

539:デフォルトの名無しさん
07/11/16 11:26:26
経験上、演算や比較文より代入に時間がかかる気がする
たぶんレジスタ動作 + 演算より、メモリ動作は遅いんだろう

540:518
07/11/16 11:39:24
>>535
ループの中で定数(変数でも変わらなければOK)で除算するのは、
置き換えた方が高速化できるし、それを実際に使っている。

ピクセル操作のような回数の多いループでは劇的な効果がある。

>>539
それは毎回キャッシュから外れた場合の話。
オンキャッシュなら少しでもCPUを止めない方がいい。


次ページ
最新レス表示
レスジャンプ
類似スレ一覧
スレッドの検索
話題のニュース
おまかせリスト
オプション
しおりを挟む
スレッドに書込
スレッドの一覧
暇つぶし2ch