【高速化】ビット演算 0x02at TECH
【高速化】ビット演算 0x02 - 暇つぶし2ch262:デフォルトの名無しさん
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を止めない方がいい。

541:デフォルトの名無しさん
07/11/16 11:45:08
>>538
で、分母はいくらなの? 100の場合はいろいろ出てるよね。

542:デフォルトの名無しさん
07/11/16 11:46:27
汎用の除算は出来ないか?
例えば2~500まで定数だけ作って分岐させて使う
そのとき高速になるのか?

543:デフォルトの名無しさん
07/11/16 11:48:53
その分岐の為に時間を使ってしまうから無理だろうね
たとえば関数テーブルで分岐したとしても、キャッシュミスを起こすだろう。

544:518
07/11/16 11:50:14
>>542
できる。
それぐらいなら除数の逆数のテーブルを使って可能。分岐はさせないほうがいい。
ただ、16bit全域とかになると、テーブルの方が不利になるCPUが多い。

545:デフォルトの名無しさん
07/11/16 11:54:52
逆数で気づいたけど、浮動小数点の掛け算で計算すると鈍いの?

546:デフォルトの名無しさん
07/11/16 11:57:24
逆数の2進展開を持っていたらビット演算できそうだけど・・・どうだろ 速いのか?

547:デフォルトの名無しさん
07/11/16 12:00:46
たびたび連投すまんが、計算でループを使うなら、はじめに分岐させてもコストは同じようなものだな
2~1024までなら10回の分岐で決定する 10回程度のループを使うなら分岐させた方が良い

548:デフォルトの名無しさん
07/11/16 12:01:09
>>544
(A*x+B)のA,Bをテーブルにするの?

でも、たとえば 65535÷3はどうするの?A=21845にしたら、これでは無理だよね

549:デフォルトの名無しさん
07/11/16 12:10:41
x / n = (Ax + B ) >> C ってどうやって求めるの?

550:518
07/11/16 12:12:05
>>548
そうそう。Bは固定でいい。

16ビット範囲の X / Dなら、R = 4294967295 / D として、

X / D の値は (R * X + 65536) >> 32となる。

Dが複数あるなら、D→Rのテーブルを作ればOK

551:デフォルトの名無しさん
07/11/16 12:14:16
>>550
BCC5.5だけど、上のやつ計算できなかったよ

552:518
07/11/16 12:19:40
>>551

__asm{
mov eax, R
mul X
add eax, 010000h
adc edx, 0
mov eax, edx
}


553:デフォルトの名無しさん
07/11/16 13:04:33
>>550

Rが切り捨てなら汎用になるように
(R * X + R - 1 ) >> 32
でいいんじゃないの?


554:518
07/11/16 13:09:18
>>553
65536より、R - 1のがいい理由は何?

555:デフォルトの名無しさん
07/11/16 13:24:06
理由は、Xが16bitの範囲を超えて入力された時の誤差が多少でも減る事だな

556:518
07/11/16 13:36:17
>>555
誤差が許される場合はいいかもね。
そうでない場合は、素直に32ビットに拡張した方が良くないか?

557:デフォルトの名無しさん
07/11/16 14:03:01
ようするに
(A * x + A-1 ) >> B
として AのMSBが1になるように B を調整するって事だよね?

Bは常に32以上だから、実際には上位ワードだけを>>(B-32) するのだろうけど

558:518
07/11/16 17:10:53
>>557
いや、そうじゃなくて、余計なA - 1 という演算を使うのではなく、
550の式を32ビットに拡張すればいいってこと。

32ビット範囲の X / Dなら、R = ((1 << 64) - 1) / D として、
X / D の値は (R * X + (1 << 32)) >> 64となる。


559:デフォルトの名無しさん
07/11/17 04:25:26
>>530
ルネサスのマニュアルによるとシフト演算と割り算に迷ったら割り算の方が大抵速いみたいなことが書いてあったけど

560:デフォルトの名無しさん
07/11/17 07:26:50
>>558 さすがに64bit掛算はまだ普及してないだろ

561:デフォルトの名無しさん
07/11/17 07:28:20
>>559 SHが特殊で固定シフト命令が1,2,4,8みたいな飛び飛びのシフトしか1命令で出来なかったりするからじゃないの?

562:デフォルトの名無しさん
07/11/17 12:16:14
でも、仕事で使用するとしたら、普通に割り算したほうがソースとして見やすいよね。
2で割るのを1ビットシフトするぐらいはいいけど、あえて複雑な演算にするほど処理能力を求められないでしょ?普通の開発は。

でも、このような議論って技術者としては面白いし、ある意味大切だよね。

563:デフォルトの名無しさん
07/11/17 12:40:03
>>560
アルゴリズム上の話で、実際に64bit乗算をするわけではないと思う。

元ネタはこれじゃね?
URLリンク(www.emit.jp)

564:デフォルトの名無しさん
07/11/17 13:51:33
>>560
コンパイラがやってくれることもしばしば。
まぁ尤も、コンパイラのアセンブリ出力を見たときに「割り算がない」って悩まないためにも
知識はあったほうがいいのだけれどね。

565:デフォルトの名無しさん
07/11/17 13:57:31
Y = (R * X ) >> 64 って事は 、R = 2^64 / D って事だろ?
Dが16bitの範囲なら Rは 48bitって事になるぞ。 64bitモードに以降しないと効率悪いぞ

566:デフォルトの名無しさん
07/11/17 14:00:28
もともと
D=100の場合

1 : ( x * 4294967200 + 65536) >> 32
2 : ( x * 4294967200 + 4294967199 >> 32
のどっちが 大きな x までまともに計算出来るかって問題でしょ?

567:デフォルトの名無しさん
07/11/17 14:01:49
違うか
1 : ( x * 42949672 + 65536 ) >> 32
2 : ( x * 42949672 + 42949671 ) >> 32

568:デフォルトの名無しさん
07/11/17 15:24:56
BCCで出来ないんだけど・・・CPUのせいかもしれない
内部で32+24ビット程度しか保持していない気がする

569:デフォルトの名無しさん
07/11/17 15:33:51
>>518がちゃんとうごくぱそこんってあるの?
テストプログラム作ったけど上位1ビットの値は壊れているようだ

#include <iostream>
using namespace std;

main(){
int n;
for(n=50;n<=64;n++)
cout<<n<<" "<<(unsigned int)((1<<n)>>(n-1))<<endl;
}

570:デフォルトの名無しさん
07/11/17 15:43:45
これっていくつになりますか?
1になるはずですよね?

cout << (unsigned int) ( ((1<<64)-2) >> 63 );


571:デフォルトの名無しさん
07/11/17 17:43:47
>>570
-1を unsigned にキャストしてるんだからUINT_MAXになると思う。

572:デフォルトの名無しさん
07/11/17 18:06:10
符号付整数の右シフトが論理シフトになるか算術シフトになるかは処理系定義

573:ヽ・´∀`・,,)っ━━━━━━┓
07/11/17 19:18:14
>>569
unsigned __int64かunsigned long longでおk

574:ヽ・´∀`・,,)っ━━━━━━┓
07/11/17 19:20:40
>>570
なんで普通のコンピュータで使えるビット数越えたシフト使うんだ。
1 << 64なんてオーバーフローで0になること確定じゃないか。

575:デフォルトの名無しさん
07/11/17 20:42:48
~0ULLでおk

576:デフォルトの名無しさん
07/11/17 23:58:43
>>569

>>563のコードと同じだからそっちでやってみればいいんじゃないか。

577:デフォルトの名無しさん
07/11/18 07:54:51
#include <iostream>
using namespace std;

main(){
unsigned int n;
for(n=60;n<64;n++)
cout<<n<<" "<<(unsigned int)(((1<<n)-2)>>(n-1))<<endl;
cout<<63<<" "<<(unsigned int) ( ((1<<63)-2) >> 62 );
}

63の値が変わるのはなぜ?

578:デフォルトの名無しさん
07/11/18 08:34:36
>>577
サイズを超えるシフトは未定義。

579:デフォルトの名無しさん
07/11/18 22:48:23
ARMは割り算使うと糞遅いから困るな。

580:デフォルトの名無しさん
07/12/03 22:55:09
age

581:デフォルトの名無しさん
07/12/03 23:13:14
32bitパソコンだと、16*16しか値は保証されないよね
a + b * 65536 などと表示して、32bit以上を表現したら
ハードウェア搭載の除算よりビット演算のほうが速い?
除算が現れたらintを16bit数に変換して計算する

582:デフォルトの名無しさん
07/12/04 05:02:29
X = 65536 、R = 1/Xとすると

(a+bX) / (c+dX) = (b+aR) / (d+cR)であり、

1/(1+R) のテイラー展開は、 1 - R + R^2 - ・・・+(-R)^n+ ・・・
Rの巾は非常に小さいため2乗までを採用すると、

(a+bX) / (c+dX) = ( (b+aR)/d ) * 1/(1 + cR/d)
=( (b+aR)/d ) * (1 - cR/d + (cR/d)^2 )
=1/(X^3 * d^3) * (a + bX ) * (c^2 -cdX + d^2X^2 ) となる

これで32bit除法を高速化出来るか?

583:582
07/12/04 05:12:33
32bit内で処理しようとすると大変だ 普通にCPUに任せた方が楽そう

584:デフォルトの名無しさん
07/12/16 20:25:38
BOOL bResultの値が 0 か -1
if (bResult == 0 || bResult == -1)

じゃなくて、一発で調べる方法はないですか?

585:デフォルトの名無しさん
07/12/16 20:42:35
BOOLなのに何故数値と比較してるんだ?

586:デフォルトの名無しさん
07/12/16 21:10:40
GetMessageじゃね?

587:デフォルトの名無しさん
07/12/16 21:30:22
BOOLは偽==0、真==0以外じゃなかったか?
定義を調べた方が良さそう。

588:デフォルトの名無しさん
07/12/16 22:05:41
世の中には変な使い方する椰子がいるのよ。MSとかw

URLリンク(msdn.microsoft.com)

589:デフォルトの名無しさん
07/12/16 22:08:46
if(bResult^0==-1)

590:デフォルトの名無しさん
07/12/16 22:37:38
x^0=x

591:デフォルトの名無しさん
07/12/16 22:42:19
if (((((uint32_t)bResult) + 1) >> 1) == 0)

同じ3演算だけど-1をロードしないだけ早いかも?
uint32_tがいいかどうかはよくわからない。

592:デフォルトの名無しさん
07/12/17 00:16:01
-1か0、限定なんだからそのまま書いたほうが分かりやすいような。

593:デフォルトの名無しさん
07/12/17 00:26:58
>>588
( ・д⊂ヽ゛

594:デフォルトの名無しさん
07/12/17 00:29:32
>>588
>警告 GetMessage 関数は、0 以外の値、0、-1 のいずれかを返します。したがって、次のようなコードは避けてください。



そもそも…

595:デフォルトの名無しさん
07/12/17 00:30:54
まー継ぎ接ぎだからな

596:デフォルトの名無しさん
07/12/17 00:39:34
>>591
右シフト・条件分岐より、比較・条件分岐の方が速くない?

if (((uint32_t)bResult + 1) <= 1)

597:デフォルトの名無しさん
07/12/17 00:50:04
>>596
マシン語レベルでは結局0比較に変換されるから同じ程度じゃないかな。
でもCレベルではそっちの方が短くていいと思う。

598:デフォルトの名無しさん
07/12/17 01:17:11
>>597
ちょっと前まで主流だった某CPUではシフトは加減算の
8倍遅かったし、それ以外のCPUでも演算器の関係で
シフトの方が並列化されにくいかも、とかそういう話。

599:デフォルトの名無しさん
07/12/17 01:19:21
で、何億回呼ぶのよ

600:デフォルトの名無しさん
07/12/17 02:05:25
シフトのほうが速いと思ってたのに・・・

601:デフォルトの名無しさん
07/12/17 03:12:30
>>599
そんなこと言うならこのスレの意義って一体なんなのさ。

確かにWindows APIをそんなアホみたいに呼ぶ事はないだろうが、
こんな風に一般化してみれば、それなりに使い道はあるだろ。

_Bool bounds_check(int n, int lower, int upper)
{
 return (unsigned)(n - lower) < (unsigned)(upper - lower);
}

>>600
加減算よりシフトの方が速いCPUなんてあるのかな?
演算の頻度からいっても普通は加減算を最速に設計すると思うけど。
x86系を数種類しか触った事ないから、他にはあるのかも知れないが。

602:デフォルトの名無しさん
07/12/17 04:47:19
ハードウェアの構造上加減算よりシフトの方が圧倒的に単純なんだよ
小さい加算器を作ったことがあればわかるはず
クロック数が一緒ってことはあるかもしれんが、
シフトの方が遅いってことはまずないだろう

603:ヽ・´∀`・,,)っ━━━━━━┓
07/12/17 05:39:05
ARMだと全命令にプレディケーション使えるからCレベルの単純な分岐は直列化できるよ
分岐は極端に遅いなんていうのはCellプログラマだけにしてください。


604:デフォルトの名無しさん
07/12/17 07:41:05
>>602
このケースは1bitだからその通りだけど
x86の8086-286までは、2bit以上のシフトは遅かったんだよ。
最初は直接bit数指定のインストラクションすらなかったし。

605:デフォルトの名無しさん
07/12/17 13:11:19
URLリンク(answers.google.com)

606:デフォルトの名無しさん
07/12/17 13:13:10
>>603
単純な分岐なら、if文使ってコンパイラに任せた方が速いね。
絶対値求める時とか、NULLならreturnするとか、分岐コストかからなくていい。

607:デフォルトの名無しさん
07/12/17 14:37:02
むしろif文にbool型しかとらないJava/C#が異端なんじゃねーの?
俺もbool型オンリーの方が好きだが、スクリプト言語してるとそうじゃない方が多い気がする。

608:デフォルトの名無しさん
07/12/17 18:27:51
ifの選択肢にTrueとFalse以外なんてあり得るの?

609:デフォルトの名無しさん
07/12/17 18:33:36
if(666){//実行されます。}

610:デフォルトの名無しさん
07/12/17 19:02:56
コメントに括弧閉じ書いて意味あんの

611:デフォルトの名無しさん
07/12/17 21:34:17
if (GetMessage(...) <= 0)

で充分でね?

612:デフォルトの名無しさん
07/12/17 21:49:47
>>602
シフタってのはデータセレクタの塊だから多ビットのシフトは
シリコンの面積を喰うのよ

613:デフォルトの名無しさん
07/12/17 23:54:21
>>611
-1以外の負の値が未定義

614:デフォルトの名無しさん
07/12/17 23:54:34
シフタのないプロセッサには出会ったことが無いけどね。

615:デフォルトの名無しさん
07/12/17 23:58:16
if (bResult == 0 || bResult == -1)



if (((uint32_t)bResult + 1) <= 1)

と同じコードになったぞ。
gcc賢いな。
ちなにみRISCでどうなるか見たかったので団子の嫌いなCELLのgccでコンパイルしたw
ちなみにCELL(SPE)もヒントブランチあるから。
むしろARMのプリディケーションいまいちだと思うけど。

616:ヽ・´∀`・,,)っ━━━━━━┓
07/12/18 00:11:17
知ってるが

Cellのスカラ性能が
気に食わない

617:ヽ・´∀`・,,)っ━━━━━━┓
07/12/18 00:45:11
分岐ヒントもBranchの15クロックくらい前くらいに入れないと駄目じゃなかったっけ
しかも二重に使うとハングする致命的なバグ持ちだから始末に困る

618:デフォルトの名無しさん
07/12/18 00:47:47
if (bResult == 0 || bResult == -1) こんなん対して食わないだろ゜

619:ヽ・´∀`・,,)っ━━━━━━┓
07/12/18 00:52:15
SSE4.1のXMMに対する比較命令が加わったから4条件同時判定とかも便利そうだね

620:デフォルトの名無しさん
07/12/18 08:10:08
ダンゴさんが連投するとスレが引き締まるな

621:デフォルトの名無しさん
07/12/18 11:30:40
ダンゴage

622:デフォルトの名無しさん
07/12/18 20:46:31
test

623:デフォルトの名無しさん
07/12/21 07:08:36
test

624:デフォルトの名無しさん
07/12/21 07:18:07
URLリンク(www.nicovideo.jp)

625:デフォルトの名無しさん
07/12/30 10:37:00
年末あげ

626:デフォルトの名無しさん
08/01/03 18:36:52
URLリンク(itl.jisakuita.net)

ダンゴさんすげえな

627:デフォルトの名無しさん
08/01/09 19:20:08
sge


628:デフォルトの名無しさん
08/01/14 22:47:23
V(・∀・)V


629:デフォルトの名無しさん
08/01/21 23:54:19
あげ

630:デフォルトの名無しさん
08/01/22 00:09:06
以下の2つの値があったとします。
x1 = 0xFF842144
x2 = 0x5400FF33

ユーザからの入力u1、u2が入力された場合
考えられるケースは以下の4つになると思います。
・u1=x1、u2=x2一致
・u1=x1一致
・u2=x2一致
・どちらとも一致しない

最低3回比較しないとどのケースか判断できないって
思い込んでるのですが
何かいいアイディアくれる人いませんか?


631:デフォルトの名無しさん
08/01/22 00:46:32
愚問だと思いますが。。

しかし、そんあ80年代前半のBASICの論理式みたいなアナクロな発想をするって
今日日奇特な人だね。

632:デフォルトの名無しさん
08/01/22 00:50:58
u1がx1と一致するケースに
・u1=x1一致、u2=x2一致
・u1=x1一致、u2=x2不一致
がある
u1がx1と一致しないケースに
・u1=x1不一致、u2=x2一致
・u1=x1不一致、u2=x2不一致
がある

つまり4通り
比較は最大2回

633:デフォルトの名無しさん
08/01/22 01:21:29
その比較を10^12回通りくらい計算するつもりなら最適化もあり

634:デフォルトの名無しさん
08/01/22 01:30:35
あらかじめ
p = x1 XOR x2
の値を取得しておく
q1 = p XOR u1
q2 = p XOR u2
を得る

635:ヽ・´∀`・,,)っ━━━━━━┓
08/01/22 01:30:56
SSE4のptest使えば一回で済む

636:デフォルトの名無しさん
08/01/22 01:54:14
>>634
得た後はどうすればいいのw?
q1とq2をどうやって使うの?

637:デフォルトの名無しさん
08/01/22 02:56:20
>>632
>・u1=x1一致、u2=x2一致
あんた馬鹿?

638:デフォルトの名無しさん
08/01/22 11:10:15
>>635
無理だろ,あれは and と andnot だから.pcmpeqd の方が良さげ

639:デフォルトの名無しさん
08/01/22 11:49:49
632ってこういうことだろ?

if( u1 == x1 ) {
if( u2 == x2 ) {
//ryouhou
} else {
//u1 nomi
}
} else {// not
if( u2 == x2 ) {
//u2 nomi
} else {
//ryouhou itti sinai
}
}

どこも間違ってるように思えないんだが。


640:デフォルトの名無しさん
08/01/22 12:34:57
しかし、BY(文脈読めない)な奴が多いな。

ここがどういうスレかを考えれば、>>630が何を聞きたいか
多少説明不足でもだいたい分かるだろ普通w

641:デフォルトの名無しさん
08/01/22 13:13:10
ほうほう。それでそれで?

642:デフォルトの名無しさん
08/01/22 18:32:50
int a[] = {両方一致, 片方一致, 片方一致, 一致しない};
b1 = (u1 == x1)
b2 = (u2 == x2)
return a[(b1 << 1) | b2];

643:642
08/01/22 18:33:45
× int a[] = {両方一致, 片方一致, 片方一致, 一致しない};
○ int a[] = {一致しない, 片方一致, 片方一致, 両方一致};

644:デフォルトの名無しさん
08/01/23 10:32:39
ゼロフラグでレジスタに0,1をセットする命令があるならソレが効率的だね。

それがないと、減算して、さらに1引いてキャリーを出してローテートしなくちゃいけない
アキュムレータが2個しかないCPUなら
AccA := u1-x1-1;
RotWithC(AccB);
AccA := AccA+x1+1-x2-1;
RotWithC(AccB);
AccB := AccB and 3;

結局、そのあたり何が効率的かはアセンブラで見ないといけないけど
アセンブラで出来る高速化は、リニアにしか効かないから、そんなに意味ないんだよね


645:デフォルトの名無しさん
08/01/23 20:55:34
全面的に同意.ただ2倍位速くなることもあるから最後の手としては有効.まぁ今は可能 intrinsic 使うけど.

646:デフォルトの名無しさん
08/01/23 21:06:35
割り算を掛け算とビットシフトに置き換える計算式求めるプログラムできた

#include <iostream>
using namespace std;
main(){
unsigned int N,n,k;
for(N=2; N<65000 ; N++){
for(n=0; (1<<n)<N ; n++); n+=15;
double X=(pow(2,n)/N);
unsigned int Y=(unsigned int)X;
unsigned int d=0;
if(X-Y<=Y+1-X)d=(unsigned int)(pow(2,n)- (N-1)*Y)-1; else Y++;
printf("x /%5d = ( x * %5d + %5d ) >> %2d",N,Y,d,n);
for(k=1; k<(1<<16) ; k++) if(k/N != ((k*Y+d)>>n))break;
if(k==(1<<16))printf(" OK\n"); else printf(" ERR\n");
}}

647:646
08/01/24 15:42:18
64bit機か、内部で64bitまで計算結果を保持しているなら
32bitの割り算も出来るけど646は16bit同士です

648:デフォルトの名無しさん
08/01/24 15:52:26
GCC の中見りゃあるんじゃね?

649:デフォルトの名無しさん
08/01/24 17:46:02
>>648
gcc のカオス・スパゲッティ状態を知らぬようだな。

勧めるならせめて Small-C くらいにしとけ。
このルーチンなら 工学社から出ていた
Small-C ハンドブックにもちゃんと説明されていたんだし。


650:デフォルトの名無しさん
08/02/04 20:42:37
ハッカーの楽しみ買ってきました~
これから読みますノシ


651:デフォルトの名無しさん
08/02/05 23:53:51
Hacker's Delight やっと届いた

652:ヽ・´∀`・,,)っ━━━━━━┓
08/02/06 01:12:31
俺もアレ訳本出る前ネットショップで買ったわ

653:デフォルトの名無しさん
08/02/22 06:50:56
a

654:デフォルトの名無しさん
08/02/28 07:49:51
a

655:デフォルトの名無しさん
08/03/01 13:50:55
a << 1

656:デフォルトの名無しさん
08/03/05 07:05:43
a

657:デフォルトの名無しさん
08/03/11 07:43:25
あげ

658:デフォルトの名無しさん
08/03/24 22:44:22
あげ

659:デフォルトの名無しさん
08/03/30 21:00:53
あげ

660:デフォルトの名無しさん
08/03/30 21:42:47
なにこのスレきもい。
でも懐かしい。

661:デフォルトの名無しさん
08/04/06 18:17:38
    |
    |
   / ̄ ̄ ̄ ̄ ̄ ̄
  <⌒/ヽ-、___
/<_/____/


662:デフォルトの名無しさん
08/04/06 18:41:01
ダンゴさんを称えるスレというわけではありませんが、まあ、KY。

663:デフォルトの名無しさん
08/04/06 19:46:30
GCAの作者のページにビット演算が載ってたけど今いちわからん

664:デフォルトの名無しさん
08/04/07 17:04:46
ViViの作者のページにもビット演算が載ってたけどだいたい理解した
URLリンク(vivi.dyndns.org)


665:デフォルトの名無しさん
08/04/07 19:44:18
>配列による状態表現よりも処理が高速になる場合が多い
この表現は凶悪だな。何故なら、高速にならなかった場合にはかなり遅くなる可能性があるからだ。

666:デフォルトの名無しさん
08/04/17 06:42:52
age

667:デフォルトの名無しさん
08/05/01 06:01:45
age


668:デフォルトの名無しさん
08/05/01 08:02:29
燃料がないな

669:デフォルトの名無しさん
08/05/01 08:50:52
16bitカラーで 5:5:5 とか 5:6:5 とか の時代なら色々やったけどな

670:ヽ・´∀`・,,)っ━━━━━━┓
08/05/01 18:55:25
AltiVecにも16bitカラー用の演算があったな

671:デフォルトの名無しさん
08/05/09 19:08:22
こちらのスレから誘導されて参りました。よろしくお願いします。

スレ立てるまでもない質問はここで 第91刷
スレリンク(tech板:171番)

以下の条件で、32bit値のハミングウェイトが素数か否かを判定する
出来るだけ高速な方法を探しています

・入力はランダム
・(最悪ではなく)平均速度が速いことが望ましい
・0、1は素数ではない(偽になって欲しい)
・ハミングウェイトそのものの値は必要ない
・64bit拡張などは必要ない。32bit決め打ちで良い
・外部メモリはあまり使いたくない

皆様のお知恵を貸していただけませんでしょうか

672:デフォルトの名無しさん
08/05/09 19:25:44
一応、今はこんな感じです
ベタな実装で恥ずかしいですが…

int hw_is_prime(unsigned long x)
{
  x = ( (x & 0xAAAAAAAA) >> 1 ) + (x & 0x55555555) ;
  x = ( (x & 0xCCCCCCCC) >> 2 ) + (x & 0x33333333) ;
  x = ( (x & 0xF0F0F0F0) >> 4 ) + (x & 0x0F0F0F0F) ;
  x = ( (x & 0xFF00FF00) >> 8 ) + (x & 0x00FF00FF) ;
  x = ( (x & 0xFFFF0000) >> 16) + (x & 0x0000FFFF) ;

  return (1 << x) & 0xA08A28AC;
}


673:デフォルトの名無しさん
08/05/09 21:56:14
1 << 32 の結果って決まってたっけ

674:デフォルトの名無しさん
08/05/12 10:32:41
処理系定義かな。0ビットシフトになる場合と32ビットシフトになる場合が一般的だと思う。

675:デフォルトの名無しさん
08/05/12 18:51:02
まぁ 8bit, 16bit, 32bit が int の場合と、
64bit が int の場合では結果は明らかに異なるよな


676:デフォルトの名無しさん
08/05/12 20:19:59
8bitがintになることってありえるっけ

677:デフォルトの名無しさん
08/05/12 20:51:31
規格は一応-32767~32767だからないんじゃね?

678:ヽ・´∀`・,,)っ━━━━━━┓
08/05/12 21:34:45
1ビットマシンとか4ビットマシンとかってCでプログラミング可能なの?

679:デフォルトの名無しさん
08/05/12 21:44:21
CHAR_BIT >= 8 だけど、
別に変数1つをレジスタ1つで扱えないといけないわけじゃないし
問題ないんじゃね?

680:デフォルトの名無しさん
08/05/12 21:47:55
ダンゴさんのカキコでスレが加熱したな

681:ヽ・´∀`・,,)っ━━━━━━┓
08/05/12 21:59:19
レス番飛んでるな

682:デフォルトの名無しさん
08/05/13 11:50:54
ダとかンとかゴとか入ると飛ぶんだよな。


683:デフォルトの名無しさん
08/05/13 11:56:23
実は見えてる

684:デフォルトの名無しさん
08/05/13 12:39:16
ダンゴって名前を嫌がるのは、
体型が肉団子だからだよな。


685:ヽ・´∀`・,,)っ-○◎●
08/05/13 12:47:46
だんごはこれだろ

━━━┓がどうみたらだんごに見えるねん

あたまわるいんとちゃうか

686:ヽ・´∀`・,,)っ鹵~<巛巛巛
08/05/13 12:50:40
虫除けのようなものだよ

687:デフォルトの名無しさん
08/05/13 14:33:31
ダンゴさんってどんな仕事してるの?


688:デフォルトの名無しさん
08/05/13 16:51:03
名無しさんの書き込みでスレがヒートアップしたな。

689:デフォルトの名無しさん
08/05/13 18:15:31
他愛もない雑談だけどな。
と、だけ書くのもなんだから、ちょこっとマジレス。

ANSI C での int の定義は処理系依存で、CPUのレジスタ幅によるらしい。
なので、Z80 なら 8bit の筈だけど、
大体のZ80 C処理系では char=8bit, int=16bit と扱う。
なんで int は 16bit より大きいという誤解があるんだろうなぁ。
その昔は char=7bit なんで処理系もあったというので、
油断は出来ないように思うんだよ。


690:デフォルトの名無しさん
08/05/13 18:38:03
INT_MINは-32767以下、INT_MAXは+32767以上じゃないといけないと決まってる
昔の話は知らん

691:ヽ・´∀`・,,)っ━━━━━━┓
08/05/13 19:01:17
1ビットCPUは実際にあった
URLリンク(www.d1.dion.ne.jp)

692:デフォルトの名無しさん
08/05/13 21:12:11
昔はやりたい放題だったかも知れないが、
今は規格に準拠した処理系であれば int >= 16 bits なのは真理。
あと、int のサイズの定義は CPU のレジスタ幅にして欲しそうな定義ではあるけど、
そう断言している訳じゃない。
実際最近でも 64-bit マシンで int = 32-bit のことがある。

693: ◆0uxK91AxII
08/05/14 01:14:15
>>689
>その昔は char=7bit なんで処理系もあったというので、
無い。

694: ◆0uxK91AxII
08/05/14 01:21:20
ごめん、間違い。

695:デフォルトの名無しさん
08/05/14 03:04:09
uartと間違えたんだな

696:デフォルトの名無しさん
08/05/14 23:42:41
ハネウェルの昔のマシンとかは 6bit 単位のマシンとかがあったから、
それとの勘違いだろ。(7bit があったかどうかは知らん。)

まあ単位が 6bit なのは uart と同じ理由だが。

697:デフォルトの名無しさん
08/05/15 02:07:52
>>691
それはCPUと言うよりリレーの置き換えみたいなもの
Connection Machineのはまともな1bit CPUだけどbit sliceだから何bitにでも
化ける

698:デフォルトの名無しさん
08/05/28 00:29:01
あげ

699:デフォルトの名無しさん
08/05/30 00:17:23
11100111

こんなビットがあったとき、0が4と5ビット目に
存在するってどうやって調べるのが効率いいのかな?

個数はわかるけど位置はどうすりゃいいんだろう

700:デフォルトの名無しさん
08/05/30 00:34:24
Hacker's Delight 嫁

701:デフォルトの名無しさん
08/05/30 02:40:11
>>699
11100111 and 00011000


702:デフォルトの名無しさん
08/05/30 02:41:22
8bitなら256個のテーブル持てば最速じゃね? 16bit以上なら、シフトして端のbitの0/1と
シフト回数で判別。

703:デフォルトの名無しさん
08/05/30 02:50:48
>>699
ループ

704:デフォルトの名無しさん
08/05/30 09:37:40
>>703
>>701

aビット目とbビット目が動的に変わるなら、マスク作ってandとった方が良いかもしれない。

705:デフォルトの名無しさん
08/05/30 09:47:01
>>699
問題文は正確に


706:デフォルトの名無しさん
08/05/30 11:48:47
>>699
4、5ビット目というのは変わりうるのよね?
あと個数が2個というのも変わりうるのよね?


707:デフォルトの名無しさん
08/05/30 11:51:01
>>699
ああ、あと、いつもがそんな風に左右対称とは限らないのよね?

708:デフォルトの名無しさん
08/05/30 12:36:25

一番下の0のビットだけを1にするのなら

y := ( not x ) and ( x +1)

で出来るから、ビットが1の個数が判る命令BitCount があるんなら
BitCount( y-1 ) で求まるよ

で x:= x or y; として一番下の0だったビットを1にしてから $FF になるまで繰り返せばいい

709:デフォルトの名無しさん
08/06/11 00:25:23
>>708
それって並列にできないですかね
無理ですよね.....

710:デフォルトの名無しさん
08/06/11 00:30:28
bit演算で128、64、32bitを扱う場合
みんなどんなふうに宣言しますか?
C/C++でのバターな方法が解りません

711:デフォルトの名無しさん
08/06/11 00:34:46
まずトラを数匹用意します。

712:デフォルトの名無しさん
08/06/11 00:41:57
あるプログラムで実際にあったコード。
普通ループではカウンタを++していくと思うけど、
(iを1,2,3・・・と加算)
一回処理するごとに左に1ビットシフトしていた。
(iを1,2,4,8・・・とシフト)


普通こういうコード書きます?仕事で。

713:デフォルトの名無しさん
08/06/11 00:49:43
>>712
1989年ぐらいに見た記憶があるw



714:デフォルトの名無しさん
08/06/11 01:15:51
グレイコードを扱うような貧弱なCPUに対するコードなら在り得る。

715:デフォルトの名無しさん
08/06/11 01:26:18
1ビットずつスキャンしていく場合には使う。

716:デフォルトの名無しさん
08/06/11 01:27:14
>>712
普通にあるし、速度面だけでなく、その方が可読性があるものもある。

717:デフォルトの名無しさん
08/06/11 01:28:54
終了条件でいつも悩むんだけどね。

718:デフォルトの名無しさん
08/06/11 07:07:30
for( bit=1 ; bit ; bit<<=1 ) cnt += ( ( data & bit) >0 );

こういうの?

719:デフォルトの名無しさん
08/06/12 22:51:52
アセンブラで1~8回のループをシフト+キャリーでやることはあったな。

720:デフォルトの名無しさん
08/06/12 23:56:44
もしかしたらループ回数が32かいを超えたら・・・
どうするの?

721:デフォルトの名無しさん
08/06/13 08:21:14
>>720
普通にカウントしろよw

722:デフォルトの名無しさん
08/06/13 11:54:06
正直別にどうでもいい
泣くしかない

723:デフォルトの名無しさん
08/06/25 13:20:16
0xC89664
の1バイト目・2バイト目の値を求める方法をお願いします。

724:デフォルトの名無しさん
08/06/25 13:24:45
>>723
貴方の小人は頭から食べるのですか? お尻から食べるのですか?
URLリンク(www.aozora.gr.jp)


725:デフォルトの名無しさん
08/06/25 19:29:14
囲碁(9路盤)のbitboardを作ろうとしています。
9x9なのでSSE2使えば128ビットレジスタ一個に収まるのでかなりの高速化が出来ると思っています。

囲碁のルールに上下左右を全て囲まれた石の塊は盤から取り除かれるというのがありますが、
これを高速に行うにはどうしたらよいでしょうか。

問題はSSE2は128ビットを一塊としたシフトが行えないことで、これのせいでどうしたらよいかわからなくなっています。
よろしくお願いします。


726:デフォルトの名無しさん
08/06/25 19:48:23
モンテカルロ木の実験ですか?

727:デフォルトの名無しさん
08/06/25 20:02:15
>>726
そうです。
モンテカルロはスピード命らしいので、SSEを使えないかと思っています。



728:デフォルトの名無しさん
08/06/25 21:11:08
左シフトなら paddq である程度代用出来るだろ

729:デフォルトの名無しさん
08/06/25 21:49:09
paddqって64ビットの境目で切れ目が出来てしまいませんか。

730:デフォルトの名無しさん
08/06/25 21:53:24
128ビット丸々だとバイト単位の命令しかないからねぇ。
x64環境を使っていいのならビット単位をやめてバイト単位にして
16本のXMMレジスタを9本使って9x9にした方がいいんじゃないかな?

731:デフォルトの名無しさん
08/06/25 22:23:24
それならビット単位でshort[9]でもよさそうですが、
バイト単位にしたほうが有利なんですか?



732:デフォルトの名無しさん
08/06/25 23:18:33
ビット単位で操作できないから困ってたんじゃなかったの?

733:デフォルトの名無しさん
08/06/26 06:48:29
レジスタを9本も使うなら32ビットのレジスタでも9x9の盤は収まってしまいます。
その場合、ビット単位の操作は可能です。

x64でレジスタが16本あったとしても通常のレジスタを9本も占めるというのは考えにくいですが、
XMMレジスタなら9本使っても支障ないということでしょうか?


734:デフォルトの名無しさん
08/06/26 09:01:44
>>729
最大9bitしかシフトしないでしょ? なら 境界にデータを置かなければいいでしょ

あるいは16bitを1列にしてレジスタ2つにしたらどう?

735:デフォルトの名無しさん
08/06/26 10:08:36
>>733
x64で汎用レジスタが増えたとはいえ9本も使えばループや分岐に支障が出ると思うよ。
その点XMMレジスタなら浮動小数点演算しなければ基本的に空いてる。

736:725
08/06/26 19:15:01
725です。

すいません。
皆さんにレスしていただいておいて申し訳ないのですが、
高速化について調べていたらGPGPUというのが見つかりました。

グラボに計算をさせるというものなのですが、上手くツボにはまれば
CPUの何十倍もの速度がでるそうです。

囲碁がはたしてグラボに計算させるのに向いてるのかどうかわかりませんが、
SSEは一旦忘れて、GPGPUについて調べてみようと思います。
グラボも3~4万だせば結構いいのが買えるみたいです。

とりあえずGPGPUスレとCUDAスレにいって雰囲気つかんできます。

皆さんのレスには感謝しています。
失礼しました。


737:デフォルトの名無しさん
08/06/26 19:47:50
そっち行ってもいいならFPGAっていうテもあるかもしれん。


738:デフォルトの名無しさん
08/06/26 21:47:07
5年ほど前にFPGAでオセロの石を返す部分を作ったが
普通にCPUで計算するより遅かった


739:デフォルトの名無しさん
08/06/26 22:43:05
>>736
CUDAするなら前もって、GPUに計算させたい部分
設計しておけ
わしは今日から3日でモンテカルロをCUDAで解けるように
勉強する

740:725
08/06/27 00:03:02
>>739
どもです。

ところで最新ハイエンドGPUはピーク性能1TFLOPS超えるらしいですね。
HDDもテラバイトの物が出てるし、時代はもうテラなんですねぇ。

741:デフォルトの名無しさん
08/06/27 00:18:19
>>740
Radeon HD3870とGeforce9800GTXもってるけど
両方とも労せず2000スレッド以上生成して並列に計算できるよ

742:デフォルトの名無しさん
08/06/27 00:32:16
>>725
一命令ではできないが,シフトしたいビット数を n として n/8 と n%8
とに分けてシフト命令使って後で合成すれば可能

743:デフォルトの名無しさん
08/06/27 04:00:39
>>738
enumの様に贅沢にintを丸々一つ石に配分した方が良かったかもしれないね。

744:デフォルトの名無しさん
08/06/27 07:18:19
ベクトル演算を利用するなら 閉曲線の内側か外側の判定で巻付判定法を応用するといいように思うな

ビット演算じゃないけど

745:デフォルトの名無しさん
08/07/11 01:01:51
あげ

746:デフォルトの名無しさん
08/07/20 15:56:27


747:デフォルトの名無しさん
08/07/20 20:41:05
今どきビット演算で高速化とかw

748:デフォルトの名無しさん
08/07/20 23:07:22
プログラミングマニュアル1・基本仕様ガイド

・式

ってとこに詳しく書いてるだろ...読みもしないで不思議とか言うな

749:デフォルトの名無しさん
08/07/20 23:07:59
誤爆すいません

750:デフォルトの名無しさん
08/07/22 10:17:23
こやつめ!

751:デフォルトの名無しさん
08/08/01 03:07:44
2^a を渡されたときaを求める方法で何かいい物はありませんか?
なるべくループやlogを使わない物がいいです

752:750
08/08/01 03:26:58
>>751
追記、1≦a≦9

753:デフォルトの名無しさん
08/08/01 03:27:44
>>752
自分の名前間違えた>>750じゃなくて>>751

754:デフォルトの名無しさん
08/08/01 04:04:46
513個の配列持って、その中に1~9を入れておく。[1]=なし、[2]=1、[3]=なし、[4]=2、・・・
[512]=9 演算はこれが最速。


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