■掲示板に戻る■ ■過去ログ倉庫めにゅーに戻る■
ちょっとしたテクニークスレッド
1 名前: 名無しさん@お腹いっぱい。 投稿日: 2000/08/21(月) 15:53
if( hogehoge == 1 )

if( 1 == hogehoge )
と書くと、イコールが一個しかなかったときエラーに
なってくれる。

#罵倒をおそれずかきこめー


2 名前: >1 投稿日: 2000/08/21(月) 16:02
その話題ふると 恐い人がやってくるのでsageですぅ


3 名前: 名無しさん@お腹いっぱい。 投稿日: 2000/08/21(月) 17:42
(define (dbg x . s) (for-each display s) (display x) (newline) x)


4 名前: 名無しさん@お腹いっぱい。 投稿日: 2000/08/21(月) 17:43
つーか、1(最初の文章)に
>#罵倒をおそれずかきこめー
だけ書いて
2に内容書けばよかったのに・・・


struct hoge {
  char *ptr;
  char str[1];
};
C++だと使いにくいが…


5 名前: 名無しさん@お腹いっぱい。 投稿日: 2000/08/21(月) 18:26
VC++だと
struct hoge{
 char *ptr;
 char str[0];
}
が出きるから、それに慣れてたせいでgccに移植するときに泣いたことが…


6 名前: 名無しさん@お腹いっぱい。 投稿日: 2000/08/21(月) 21:48
>4,5
それって何に使うんですか?純粋に知りたいです。


7 名前: 4 投稿日: 2000/08/21(月) 22:09
つい、例にポインタをいれてしまったので、わかりにくいか。

例えば、文字列のリスト構造を実現する場合に
リストを実現する構造体と、文字列を記憶する配列分の
2回、mallocを呼ぶ必要がある。
ところが、4の形式、つまり構造体の最後のメンバにchar[1]があると、
 p = malloc(sizeof(struct hoge)+strlen(s));
 strcpy(p->str, s);
という技が使える。
利点はmallocの呼び出し回数が減らせるため、
記憶領域的にも速度的にも有利になる。

もちろん、charに限らず、
「不定長の領域を本体とは別に確保する必要がある場合」に、
使う事が出来る。


8 名前: 投稿日: 2000/08/21(月) 23:41
誰も上げないので
あげ


9 名前: >6 投稿日: 2000/08/22(火) 00:02
構造体の最後のメンバが可変長のデータを持っている(指しているのではない)
の時に使います。
とくに、生成から消滅までの間固定長だけど、モノによってデータサイズが違う
ときに有効です。


10 名前: 名無しさん@お腹いっぱい。 投稿日: 2000/08/22(火) 01:50
Shift-JIS 漢字第一バイトの判定

if ( ((c >= 0x81) && (c <= 0x9F)) || ((c >= 0xE0) && (c <= 0xFC)) )

のかわりに

if ( (c >= 0x81) && ( (c <= 0x9F) || ((c >= 0xE0) && (c <= 0xFC)) ) )

の方が、多くの場合速度が速いコードが作れ、オーバーヘッドもほとんどない。
括弧が多いのは、今書いたからなんで、かんべん。




11 名前: このスレおもしろいかも 投稿日: 2000/08/22(火) 02:00
//1と2を入れ替える
i := (i - 1) * (-1) + 2;
{
if i = 1 then
 i := 2
eles
 i := 1;
}
2つもコメントを入れてしまった俺は根性なし・・・



12 名前: 名無しさん@お腹いっぱい。 投稿日: 2000/08/22(火) 02:03
<10
2つ以上の範囲の判定なら、いつでも使えそうですね。



13 名前: 名無しさん@お腹いっぱい。 投稿日: 2000/08/22(火) 10:13
VBでCombo boxにリストを追加したい時、普通は
Combo1.AddItem リスト項目
とやる。
が、この項目がうん百件とある場合(データベースから拾ってくる等)
AddItemでは偉く時間がかかってしまう。
そこで、APIを使うと速度が向上する。
こんな感じだ。
あらかじめ、Option Explicitで以下のように宣言しておく。

Private Declare Function SendMessage Lib "user32" _
Alias "SendMessageA" _
(ByVal hwnd As Long, _
ByVal wMsg As Long, _
ByVal wParam As Long, _
ByVal lParam As Any) As Long

で、実際の処理部分は、
自分の場合DBにオラクルを使ったので、

Dim ret As Long
Dim cbHwnd As Long
Dim cbitem As String
Dim SQL_TEXT As String

cbHwnd = Combo1.hwnd
Combo1.Clear

SQL_TEXT = "select hoge from TB_hoge "
SQL_TEXT = SQL_TEXT & "where code = 'hoge'"
SQL_TEXT = SQL_TEXT & " ORDER BY hoge"
Set OraDs = OraDatabase.CreateDynaset(SQL_TEXT, ORADYN_READONLY)

OraDs.MoveFirst
Do Until OraDs.EOF
cbitem = OraDs![hoge] & vbNullString
ret = SendMessage(cbHwnd, CB_ADDSTRING, 0, cbitem)
OraDs.MoveNext
Loop

といった感じになる。
かなりスピードアップするハズ。
お試しアレ。
sendmessageは奥深いよ……。



14 名前: 名無しさん@お腹いっぱい。 投稿日: 2000/08/22(火) 11:22
常識かもしらんけど。

#define SWAP(a,b) (a^=b,b^=a,a^=b)


15 名前: >11 投稿日: 2000/08/22(火) 11:26
i = (1+2) - i;
でええんとちゃうの?
BASIC時代にはしょっちゅう使ったテクだが。


16 名前: 名無しさん@お腹いっぱい。 投稿日: 2000/08/22(火) 11:40
>15
つーか、それって3-i


17 名前: 名無しさん@お腹いっぱい。 投稿日: 2000/08/22(火) 12:21
有名かもしれんが、

printf("%0*d\n", 4, 123 );





18 名前: 6 投稿日: 2000/08/22(火) 12:26
>7, 9
なるほど〜。
WinAPIでパレットいじるときのあれみたいなものですね〜。
どうもありがとうございました。


19 名前: >13 投稿日: 2000/08/22(火) 13:42
それ以前に
COMBOやMSFLEXGRIDなんかは

Combo1.Visible = False

処理

Combo1.Visible = True

とするとオーバーヘッドが発生するはずなのになぜかかなりの高速化になる。


20 名前: 名無しさん@お腹いっぱい。 投稿日: 2000/08/22(火) 15:07
LD BC,DEを実現する
PUSH DE
POP BC



21 名前: 名無しさん@お腹いっぱい。 投稿日: 2000/08/22(火) 16:13
ALの符号をAHに拡張する
CBW


22 名前: >20 投稿日: 2000/08/22(火) 17:56
mov b, d
mov c, e
でいいと思うんだけど。なぜにスタックを使う?
メモリを介さない分、速いだろうとおもうのですが。


23 名前: 20 投稿日: 2000/08/22(火) 18:30
>>22
??言われてみれば、そうだな……。Z80の話だからなあ。
よく覚えてねえや。
じゃあ、これでどうだ
XCHG BC DE を実現する
PUSH BC
PUSH DE
POP BC
POP DE


24 名前: 名無しさん@お腹いっぱい。 投稿日: 2000/08/22(火) 20:06
inline int IsShiftJIS(unsigned char c)
{
 if(c>=0x81)
 {
  if(c<=0x9F)
   return 1;
  else
  {
   c += 0x20;
   if(c <= 0x1C)
    return 1;
  }
 }
 return 0;
}

こう言うのはやっぱり無駄な努力なんでしょうか。



25 名前: !=22 投稿日: 2000/08/22(火) 20:09
どうだ、って、それもaを使って6回LDする方が速いんじゃねーの?


26 名前: 20 投稿日: 2000/08/22(火) 21:08
>>25
かな?
まあ、アキュムレータを使わないでも済む方法、ってことで一つ……。
どっちが早いかは、今手元に資料が無いから分かんないよ。


27 名前: !=22,25 投稿日: 2000/08/26(土) 04:58
8ビット汎用レジスタ間LDは全部4クロック、PUSH/POPは11+10クロック
だから、スタックは使わない方が基本的に速い。
23のはAレジスタ使わないなら
PUSH BC
LD B,D
LD C,E
POP DE
あたりで妥協かな。


28 名前: 名無しさん@お腹いっぱい。 投稿日: 2000/10/31(火) 19:12
ageてみよう


29 名前: 名無しさん@お腹いっぱい。 投稿日: 2000/10/31(火) 19:23
>>14
逆の意味で常識。
SWAP(x, x);
とした場合、何が起こる?



30 名前: 名無しさん@お腹いっぱい。 投稿日: 2000/10/31(火) 19:34
0と1を入れ替え。

int a = 0;
a = 1 - a;

すげーだろー。


31 名前: 名無しさん@お腹いっぱい。 投稿日: 2000/10/31(火) 19:48
>30
a^=1; でええやん。




32 名前: 名無しさん@お腹いっぱい。 投稿日: 2000/10/31(火) 21:37
人差し指と薬指で広げておいて、中指を膣口に忍ばせ、
更に親指はクリトリスを責める!



33 名前: 名無しさん@お腹いっぱい。 投稿日: 2000/10/31(火) 21:39
0からN-1までをなめるとき、
for (int i = N - 1; i >= 0; --i) {
...
}
みたいに判定を0で行うとほんの少し速くなるかも
#こんなこと気にしながらプログラム書きたくないけど・・・


34 名前: ミトコンドリ子 投稿日: 2000/10/31(火) 21:52
アタシはこっちの書き方のほうが好きよ。
for ( int i=N ; --i >= 0 ; ) {...}
Nの表記が長いときに -1 が紛らわしくならないからよ。

0比較のため、というよりはインデックス逆巡回を書くときの
イディオムよね。


35 名前: 名無しさん@お腹いっぱい。 投稿日: 2000/10/31(火) 22:05
>>33,>>34
境界判定のための比較が要らなくなるか、
って、アセンブラなら減産して0だった時点でZeroフラグ立つよね。

Cって、
オプティマイズされたオブジェクトなら、意外な方法で高速にしたりするんで、意味無し!




36 名前: 33 投稿日: 2000/10/31(火) 22:10
>>34
>for ( int i=N ; --i >= 0 ; ) {...}
あ、、、きれい・・・いただきます:-)

>0比較のため、というよりはインデックス逆巡回を書くときの
>イディオムよね。
んーでも、比較すべき数値をレジスタにロードしなくて良い分
速いかなぁと・・・CPUによりけりですけど。
おまじないのように上記のようにがんばって書いてました。
「もうちょっと速くなりますように」とお祈りしながら・・・


37 名前: 33 投稿日: 2000/10/31(火) 22:19
>>35
>Cって、
>オプティマイズされたオブジェクトなら、意外な方法で高速にしたりするんで、意味無し!
いや、先の例で、Nが変数のときには
for (int i=0; i < N; ++i) {...}
で、比較部分がほんのちょこっとだけ最適化あまくなるようなきがしません?
まあ、目に見えて速くなるわけではないですが、
藁にもすがりたいときにはおまじないとしてやってます。。。
だめっすかねぇ・・・


38 名前: 名無しさん@お腹いっぱい。 投稿日: 2000/10/31(火) 23:33
for ( int i=N ; --i >= 0 ; ) {...}  って
for ( int i=N ; i-- ; ) {...} でも可?


39 名前: 名無しさん@お腹いっぱい。 投稿日: 2000/10/31(火) 23:41
x+=(button==RIGHT)-(button==LEFT);
y+=(button==UP)-(button==DOWN);
(;´Д`)


40 名前: 名無しさん@お腹いっぱい。 投稿日: 2000/11/01(水) 00:01
すんません
ここの人はアセンブラとかにも詳しいのかな?
便乗質問させてください。

for(int i=N; --i;){}

int i=N;
while(i--){}
ではforの方が早くなるんですか?

最適化のあまりよろしく無いコンパイラ(あまり最適化に頼るのもなんなので)
普通程度の最適化がなされるコンパイラ(今時のコンパイラならそのぐらい基本的みたいな)

の両方のケースで教えてください。



41 名前: 名無しさん@お腹いっぱい。 投稿日: 2000/11/01(水) 00:12
>>40
何故自分で確かめない?


42 名前: 名無しさん@お腹いっぱい。 投稿日: 2000/11/01(水) 00:35
x=y=z=0;
(;´Д`)


43 名前: 名無しさん@お腹いっぱい。 投稿日: 2000/11/01(水) 00:40
>>40
ループ回数違うような・・・
あと、iが0になったかどうかだけで判定してますが
Nが負で渡ってきちゃったときとか不安・・・
iのスコープも違ってるし・・・

スピードは同じっぽそう。逆アセンブルして確かめよう。


44 名前: 名無しさん@お腹いっぱい。 投稿日: 2000/11/01(水) 00:46
自分の目で確かめろ。
アゲてるやつはみんな白痴。



45 名前: 名無しさん@お腹いっぱい。 投稿日: 2000/11/01(水) 01:24
他人を白痴呼ばわりするのって楽しい?


46 名前: 名無しさん@お腹いっぱい。 投稿日: 2000/11/01(水) 02:15
>>45
あなたは、そんなこと聞いてどうするの?


47 名前: 名無しさん@お腹いっぱい。 投稿日: 2000/11/01(水) 02:29
int a,b,c;
....;
if(int d=a-b)
{
d+=...;
c+=d;
}
(;´Д`)


48 名前: 名無しさん@お腹いっぱい。 投稿日: 2000/11/01(水) 05:39
何これ?>47


49 名前: 名無しさん@お腹いっぱい。 投稿日: 2000/11/01(水) 13:04
>>45
たのしぃでぇ〜す。

酔っぱらい関数きぼん。


50 名前: 名無しさん@お腹いっぱい。 投稿日: 2000/11/01(水) 15:12
ここおもろい!!わしもかきこ!!

nビットのマスク生成

(1 << n) - 1;


51 名前: 名無しさん@お腹いっぱい。 投稿日: 2000/11/01(水) 23:09
あらら、sageばっかり・・・
あげちゃえ!


52 名前: 名無しさん@お腹いっぱい。 投稿日: 2000/11/02(木) 00:07
mvi a,0
ではなく
xra a
とすると1バイトで済む

メモリを0(等)で埋める歳にはpushを使うと速い

dadで16bitの引き算をするには…
bcとdeをxchgしたい時には…
は当たり前の事か


53 名前: 名無しさん@お腹いっぱい。 投稿日: 2000/11/02(木) 00:26
bool light0;
…;
(light0?Enable:Disable)(LIGHTING);
(;´Д`)


54 名前: 名無しさん@お腹いっぱい。 投稿日: 2000/11/02(木) 00:35
CMP AL,0Ah
SBB AL,69h
DAS

5バイトの1桁16進バイナリ−ASCII文字変換。
有名だねー。



55 名前: 名無しさん@お腹いっぱい。 投稿日: 2000/11/02(木) 00:46
CLEAR ,&HBFFFしないでGVRAMにアクセスするルーチンをC000以前に置くには
文字列変数に入れてVARPTR()の値を参考に絶対アドレスの部分を書き換える

って何の話だ


56 名前: 名無しさん@お腹いっぱい。 投稿日: 2000/11/02(木) 03:03

SJIS2JIS PROC
     sub al,71h
     and al,3Fh
     stc
     rcl al,1
     cmp ah,7Fh
     cmc
     sbb ah,1Fh
     cmp ah,7Fh
     jc @skp
     inc ax
     sub ah,7Fh-21h
@skp:
     xchg al,ah
     ret
SJIS2JIS ENDP



57 名前: 名無しさん@お腹いっぱい。 投稿日: 2000/11/02(木) 04:17
typedef unsigned char BYTE;
typedef struct { BYTE stuff[100]; } BYTE100;

*(BYTE100*)px = *(BYTE100*)py; //memcpy(px,py,100)と同じ?



58 名前: 名無しさん@お腹いっぱい。 投稿日: 2000/11/02(木) 05:05
>>56
よかったらJIS2SJISも書いてくださ〜い。



59 名前: 名無しさん@お腹いっぱい。 投稿日: 2000/11/02(木) 09:48
int c の b ビット目の on / off

#define BITon(b,c)  ((c) = ((c)|(0x01<<(b))))
#define BIToff(b,c)  ((c) = (~(~(c)|(0x01<<(b)))))

ダサイ???


60 名前: 名無しさん@お腹いっぱい。 投稿日: 2000/11/02(木) 18:46
#define BIToff(b,c) ((c) = (c) & ~(1 << (b)))
c++ を無意識に使う怖さから、inline にしたほうがいいと思うが。



61 名前: 名無しさん@お腹いっぱい。 投稿日: 2000/11/02(木) 21:06
>54
6809版
ADDA #$90
DAA
ADCA #$40
DAA

6バイト


62 名前: 名無しさん@お腹いっぱい。 投稿日: 2000/11/02(木) 22:47

#define BIT_Reverse(b,c) ((c)=(c)^(1<<(b)))


63 名前: 名無しさん@お腹いっぱい。 投稿日: 2000/11/03(金) 00:28
なんか、懐かしのテクニークスレッドと化してきたな(ワラ



64 名前: 名無しさん@お腹いっぱい。 投稿日: 2000/11/03(金) 20:25
>>63
しょうがねぇじゃん。ここに書いてる奴はみんなレベル低いんだから。



65 名前: 名無しさん@お腹いっぱい。 投稿日: 2000/11/03(金) 22:25
オマエモナーと言われたいM男君が増えてるな
逝ってやらん


66 名前: 名無しさん@お腹いっぱい。 投稿日: 2000/11/05(日) 04:41
age


67 名前: 名無しさん@お腹いっぱい。 投稿日: 2000/11/07(火) 06:49
ここにHerrさんいるでしょ。



68 名前: 名無しさん@お腹いっぱい。 投稿日: 2000/11/07(火) 07:30
#DIV(x, y) (y ? x / y : 0)

うーん、こんなのは?
望んだ結果が出ないかもしれんけど。


69 名前: 68 投稿日: 2000/11/07(火) 07:44
あ、((y) ? (x) / (y) : 0) だな。


70 名前: 名無しさん@お腹いっぱい。 投稿日: 2000/11/07(火) 12:47
>>68 何に使うの? 無限大を0に修正する? 用途を示してくんない?


71 名前: 名無しさん@お腹いっぱい。 投稿日: 2000/11/07(火) 13:29
除算エラーにしたくないのでしょう。


72 名前: >70 投稿日: 2000/11/07(火) 13:31
たぶんゼロ除算例外を防止する為でしょう。

でも、その前の段階でyがゼロにならないよう管理すべきだと思ってたから
こんな事はやったことないな。逆に原因不明にするだけじゃん。


73 名前: 名無しさん@お腹いっぱい。 投稿日: 2000/11/07(火) 13:56
>>72 わしもそう思う。




74 名前: 70 投稿日: 2000/11/07(火) 14:33
ゼロ除算防止なのは、わかる。
オレも72の言うとおりこのマクロの使用では原因不明になるだけじゃないのか
と思う。

でもこういう形で記述すると上手く解決できる問題分野があり、それを
オレが知らないだけかとも思ったワケ。

そこらへん、どうよ >>68

#行列の特異値分解かなにかで 1/ε -> 0 (εは非常に小さい正数)と
置き換える場合とかがあった気がする。でもその場合はこのマクロは
使えないとも思う。


75 名前: 名無しさん@お腹いっぱい。 投稿日: 2000/11/07(火) 15:04
ビット数をカウントするアルゴリズムでさぁ
0x7777とか、0x33333?とか使うやつあったっしょ
あれってどーゆーのだっけ?


76 名前: 名無しさん@お腹いっぱい。 投稿日: 2000/11/07(火) 15:58
>>75
そこまで分かってるなら自分で検索すれ!
http://www.st.rim.or.jp/~phinloda/cqa/cqa15.html


77 名前: 75 投稿日: 2000/11/07(火) 19:42
ありがと。(探したけど、見つからなかったの、ゆ・る・し・て)


78 名前: 名無しさん@お腹いっぱい。 投稿日: 2000/11/07(火) 19:48
ちょっとズレるけどさ、マクロって関数コールのオーバーヘッドを
避けるために多用したりすることってないの?>制御分野のお方。



79 名前: >78 投稿日: 2000/11/07(火) 20:14
僕は制御じゃないけど
複雑になりそうな場合マクロをやめて関数にしてpragmaでinline化します。
移植性は下がるけど、可読性のほうが大事なので。


80 名前: 名無しさん@お腹いっぱい。 投稿日: 2000/11/07(火) 21:28
制御用のクロスコンパイラは実装が貧困すぎて
inlineできないのがあります。



81 名前: 名無しさん@お腹いっぱい。 投稿日: 2000/11/08(水) 02:49
最近は制御系にもgccとか使われる場合が結構ある。


82 名前: >78 投稿日: 2000/11/08(水) 05:12
あるよ。


83 名前: ななしさん@目立ちたがりの厨房 投稿日: 2000/11/08(水) 16:50
コメントテク。
通常、
/*
....
*/
と書くが、
/*
....
//*/
と、コメントアウトしておくと、
//*
....
//*/
と、最初の一行に'/'一個追加するだけで、"...."の行が有効になる。

デバッグの時にちょっと便利。



84 名前: 名無しさん@お腹いっぱい。 投稿日: 2000/11/08(水) 16:56
偶数化:変数 & -2



85 名前: 名無しさん@お腹いっぱい。 投稿日: 2000/11/08(水) 17:44
>76
ちなみにどんなキーワードで見つけたの?すごい


86 名前: 吾輩は名無しさんである 投稿日: 2000/11/08(水) 17:58
ここあとで修正しとく必要があるなーってとこには
/**/を書いときます。


87 名前: 名無しさん@お腹いっぱい。 投稿日: 2000/11/08(水) 18:03
>>83
頼むからやめてくれ。



88 名前: 68じゃないけど 投稿日: 2000/11/08(水) 19:04
>>68-74
もちろん、y=0にならないように書くのが正しいんだけど、仕事でゲームの
開発をしていると、最悪でも例外がおきないようにしておくのはわりと
大事だったりします。
# ハングるよりは変な場所に表示される方がマシってこと。


89 名前: 68 投稿日: 2000/11/08(水) 19:23
あ、遅レスだけど 71-73,88 の言う通りですね。
まあこれは 88 の言うように許容できる場合に限るので今考えると特殊な部類に入るかもね…
返す値を 0 じゃなくて自作関数で説明入りエラー吐くようにしておけば 0 割りのトラップもしやすいかもね。


90 名前: 名無しさん@お腹いっぱい。 投稿日: 2000/11/09(木) 00:47
0が返っても許容できる、じゃなくて、
エラー処理の存在自体が許容できないわけです。ゲームでは。


91 名前: 名無しさん@お腹いっぱい。 投稿日: 2000/11/09(木) 00:49
ちょっとしたテクニークスって事で
typedef で一度にポインタも定義出来ます

例:
typedef struct { なんとかかんとか} HOGE,*PHOGE;


92 名前: 名無しさん@お腹いっぱい。 投稿日: 2000/11/09(木) 01:04
<91
typedefの書式は、識別子の宣言とおなじだからね。


93 名前: 名無しさん@お腹いっぱい。 投稿日: 2000/11/09(木) 01:08
常識と思うけど大文字化(ASCII 文字セット限定)
c には英文字が入ってると思いねぇ
char to_upper(char c) {
return c & ~0x20;
}


94 名前: 名無しさん@お腹いっぱい。 投稿日: 2000/11/09(木) 01:46
>>91
const PHOGE
ってやってハマる奴がたまにいる。



95 名前: >>93 投稿日: 2000/11/09(木) 12:53
普通のtoupperじゃなんであかんの?


96 名前: Dr.URI 投稿日: 2000/11/10(金) 19:12
URIのことをかまってくださいー・・・

typedef struct{
  unsigned int Value : 2;
} ROTATE;

void FuncA()
{
  ROTATE st;
  unsigned int p;
  st.Value = 0;
  int i;
  for (i = 0; i < 10; i++)
  {
    p = st.Value++;
    printf("%d\n", p);
  }
}



97 名前: 名無しさん@お腹いっぱい。 投稿日: 2000/11/10(金) 20:00
#define FLAG_CHECK( NUM, FLAG) ((NUM & FLAG) / FLAG)
#define FLAG_ON( NUM, FLAG) NUM |= (NUM ^ FLAG)
#define FLAG_OFF( NUM, FLAG) NUM ^= (NUM & FLAG)

いまどきフラグなんてせこい使い方しないか?



98 名前: ビット操作を最近覚えた人 投稿日: 2000/11/10(金) 20:05
>>97
結構便利なんですが、、、
例えばゲームの毒、混乱、眠りなどの状態を表すとか。



99 名前: 名無しさん@お腹いっぱい。 投稿日: 2000/11/10(金) 20:45
#define FLAG_CHECK(NUM, FLAG) (!!(NUM & FLAG))
の方が好みだ。


100 名前: 名無しさん@お腹いっぱい。 投稿日: 2000/11/10(金) 21:52
#define FLAG_CHECK(NUM, FLAG) (((NUM)&(FLAG))==(FLAG))


101 名前: ビット"猿"Zよか 投稿日: 2000/11/10(金) 23:30
ビットフィールド使うなぁ…


102 名前: 名無しさん@お腹いっぱい。 投稿日: 2000/11/11(土) 04:45
>>101
俺もビットフィールド使うなぁ…


103 名前: 投稿日: 2000/11/12(日) 01:16
>>101-102
フラグとかをビットフィールトで、
struct {
int a:1;
int b:1;
} flag;
とかで定義した場合、すべてを0でクリアするとき、
*(int *)&flag=0;
とか書いてるんですけど、もっとエレガントな方法はないでしょうか?

i


104 名前: 名無しさん@お腹いっぱい。 投稿日: 2000/11/12(日) 01:20
>>103
UNION使っとけ!


105 名前: 名無しさん@お腹いっぱい。 投稿日: 2000/11/12(日) 01:59
この場合 int だと変な領域に書込んでしまわないか?



106 名前: 名無しさん@お腹いっぱい。 投稿日: 2000/11/12(日) 02:22
左辺値のポインタのキャスト、よくある勘違いだよね。


107 名前: 名無しさん@お腹いっぱい。 投稿日: 2000/11/12(日) 06:19
どなたか MMX の飽和演算を高速に真似る方法を教えてください。
4つの8ビットに加算したとき、ループせずに 0xff で飽和する演算を
考えていたのですが if 文を使う以外にいい方法が思いつきませんでした。

BYTE a, b;
int c;
c = a + b;
if( c > (BYTE)0xff ) c = 0xff;
... 以下 4 つ繰り返し。



108 名前: 名無しさん@お腹いっぱい。 投稿日: 2000/11/12(日) 06:56
0xff * 0xffサイズのテーブルを作る……
って、今のPCだと逆効果かも。


109 名前: 108 投稿日: 2000/11/12(日) 06:57
あう、0x100 * 0x100サイズの間違い
ああ鬱だし脳


110 名前: 名無しさん@お腹いっぱい。 投稿日: 2000/11/12(日) 07:14
int なんちゃら(unsigned char a, unsigned char b)
{
  unsigned char retval;
  _asm {
    mov al, a
    mov dl, b

    add al, dl
    sbb cl, cl
    or al, cl
    mov retval, al
  }
  return retval;
}

うまく使わんと、パーシャルレジスタストールの餌食になるよ。


111 名前: 110 投稿日: 2000/11/12(日) 07:18
clはdlでもよかった…


112 名前: >110 投稿日: 2000/11/12(日) 18:21
どこがテクニークなの?



113 名前: 名無しさん 投稿日: 2000/11/12(日) 18:41
Cでやるならテーブルが一番手軽だろ。
BYTE Table[2]={0,0xFF};
BYTE a, b;
int c;
c = a + b;

c=c | Table[c >> 8];

255+255は512以下だからな。


114 名前: 飽和加算 投稿日: 2000/11/12(日) 23:50
86系のアセンブラなら、alに3つ足して ahに127を足して、符号拡張
して、alとandかな。
4つ足した数を使って飽和させるほうが早い気がする。
どっちにしろ、cでifを使うのにくらべて、測定可能な速度差が出るかど
うかは、わからんけど。


115 名前: 名無しさん@お腹いっぱい。 投稿日: 2000/11/13(月) 00:32
あまり気にしすぎるのも時間の無駄のような気がするなぁ。

前いた会社に最適化マニアがいて、きちんと動いてるのに
まだ速くする!とか言ってゴネてくれたが・・・。



116 名前: 投稿日: 2000/11/13(月) 03:47
>>104
unionだと、
union {
int all;
struct {
int a:1;
int b:1;
} bit;
} flag;
みたいな書き方になると思うのですが、それだと階層が一つ深くなる
じゃないですか。
>>105-106
すいません、どこがまずいのかわかんないです。


117 名前: 名無しさん@お腹いっぱい。 投稿日: 2000/11/13(月) 04:05
>116
sizeof flag をかんがえてごらん



118 名前: 107 投稿日: 2000/11/13(月) 05:22
>>108-115
皆さんご教授いただきありがとうございます
インラインアセンブラやビット操作で if 文は削ることが
できるんですね、勉強になりました。

>c=c | Table[c >> 8];

c |= (BYTE)((0x100) - (c >> 8));
これでもいいのかな



119 名前: >117 投稿日: 2000/11/13(月) 05:39
116のまずいのは、そっちじゃない気がするんだけど…


120 名前: 119 投稿日: 2000/11/13(月) 05:43
116でなくて、>>103


121 名前: >113,118 投稿日: 2000/11/13(月) 08:08
なんでOR演算になってるの?


122 名前: 121 投稿日: 2000/11/13(月) 08:20
これでどう?
BYTE Table[2]={0xFF,0};
c &= Table[c >> 8];
---
c &= (0 - (c >> 8));


123 名前: 121,122 投稿日: 2000/11/13(月) 08:25
あ、ごめん。大きな勘違いだった。氏のう。


124 名前: 投稿日: 2000/11/13(月) 11:52
すいません、まだ引っ張ります。
>>117 >>119
(flag.c)
int main(int argc, char **argv) {
struct {
int a:1;
int b:1;
} flag;

*(int *)&flag=0;

printf("size of flag=%d\n", sizeof(flag));
printf("size of int=%d\n", sizeof(int));

return 0;
}
>./flag
size of flag=4
size of int=4
なんですけど…。ちなみにgccです。


125 名前: 名無しさん@お腹いっぱい。 投稿日: 2000/11/13(月) 13:50
そりゃANSIだとビットフィールドはintに満たなくてもintに切り上げられるからねえ。


126 名前: 107 投稿日: 2000/11/13(月) 14:37
>>121
>c &= (0 - (c >> 8));

ありがとうございます。飽和減算に使えそうです。

c |= -(c >> 8);
これで定数が消えました。いいかんじになってきました。
shr eax, 8
neg eax
or ebx, eax
(たぶんコンパイルするとこんな感じになりそう)
これ以上の高速化は 8bit * 4 を一気に処理するしかないでしょうか。


127 名前: 名無しさん@お腹いっぱい。 投稿日: 2000/11/13(月) 17:08
テクニークとかく事。


128 名前: 名無しさん@お腹いっぱい。 投稿日: 2000/11/13(月) 19:13
>>126
>c |= -(c >> 8);
>これで定数が消えました。いいかんじになってきました。

よくわからんな。その処理ってなんなんだ?
0か1になった奴を答えから引くことに何の意味がある?


129 名前: Visual名無しさん 投稿日: 2000/11/13(月) 21:03
>>128
0xffを越えてれば
c |= 0xff
でなけりゃ
c |= 0x00
って感じだから問題ないだろ。


130 名前: 名無しさん@お腹いっぱい。 投稿日: 2000/11/13(月) 23:05
>128
8bit同士の加算だと、飽和してるのは 0x100〜0x1fe だ。
8bitシフトすると1 になるのだな。
で、これを符号反転すると(2の補数表現だと)0xff になって、
飽和しない場合は 0 を符号反転するから 0 。
で、>>129のようになってめでたしめでたし。



131 名前: 123 投稿日: 2000/11/13(月) 23:54
>126
厳密には
c = (c | -(c >> 8)) & 0xFF;
だね。後で代入時にキャストするから書かなかっただけかな?
また勘違いだったらごめん。


132 名前: 126 投稿日: 2000/11/14(火) 08:04
>>131
>後で代入時にキャストするから書かなかっただけかな?

はい。0xff でマスクかけたほうが ANSI 定義の
キャスト変換に合うのでいいのですが -1 になってるから
ま、いいかなと思いました。(^^;)
補数表現とかキャスト変換は自分の使っている処理系に依存しています。

まとめて処理するのを考えていますがなかなか難しいです。


133 名前: 名無しさん@お腹いっぱい。 投稿日: 2000/11/14(火) 10:34
>132
4つ足してからなら>>114の方法でええんでないの?
Cで書くなら 0x7f00を足して16ビットシフトして符号反転、かな。


134 名前: 133 投稿日: 2000/11/14(火) 10:35
15ビットシフトして、だった。


135 名前: 133 投稿日: 2000/11/14(火) 10:39
ああ、0x7f00じゃだめだな、まぁ、察してくれや。


136 名前: 某ランド 投稿日: 2000/11/14(火) 11:11
unsigned ClipAdd4(unsigned a,int b)
{
unsigned c;
_asm {
 mov eax,a;
 mov ebx,b;
 and eax,7f7f7f7fh;//MSB以外と
 and ebx,7f7f7f7fh;//MSB以外と
 add eax,ebx;
 mov ecx,eax;
 mov eax,a
 mov ebx,b
 and eax,80808080h;// ax,bx,cxのMSBが2つ以上1なら飽和
 and ebx,80808080h;// ax,bx,cxのMSBがひとつでも1ならMSB=1
 add eax,ebx
 mov ebx,ecx
 rcr eax,1
 shr ebx,1
 and ebx,40404040h
 add eax,ebx
 mov ebx,eax
 shl eax,1
 shr ebx,7    ;//各桁のキャリをLSBに合わせる
 and ebx,01010101h
 add ebx,7f7f7f7fh;//CF=0 then 7F else 80
 not ebx     ;//CF=0 then 80 else 7f
 and ebx,7f7f7f7fh;//cf=0 then 00 else 7f
 and eax,80808080h;
 or  ecx,ebx
 or  eax,ecx
 mov c,eax; //帰値はeaxなので不要だが警告を黙らせる為に
 }
 return c;
}


137 名前: 某ランド 投稿日: 2000/11/14(火) 11:28
がんばってみたけど、110さんの方法の方が短い
unsigned ClipAdd4(unsigned a,int b)
{
unsigned c;
_asm {
 mov eax,a;
 mov ebx,b;
 add AL,BL
 sbb CL,CL
 or  CL,AL
 ror ecx,8
 shr eax,8
 shr ebx,8
 add AL,BL
 sbb CL,CL
 or  CL,AL
 ror ecx,8
 shr eax,8
 shr ebx,8
 add AL,BL
 sbb CL,CL
 or  CL,AL
 ror ecx,8
 shr eax,8
 shr ebx,8
 add AL,BL
 sbb CL,CL
 or  CL,AL
 ror ecx,8
 mov c,ecx
 }
 return c;
}


138 名前: 某ランド 投稿日: 2000/11/14(火) 11:32
ごめん、こっちだ
nsigned ClipAdd4(unsigned a,int b)
{
unsigned c;
_asm {
 mov eax,a;
 mov ebx,b;
 add AL,BL
 sbb CL,CL
 add AH,BH
 sbb CH,CH
 or  CX,AX
 ror ecx,16
 shr eax,16
 shr ebx,16
 add AL,BL
 sbb CL,CL
 add AH,BH
 sbb CH,CH
 or  CX,AX
 ror ecx,16
 mov c,ecx
 }
 return c;
}


139 名前: 名無しさん@お腹いっぱい。 投稿日: 2000/11/14(火) 12:54
エナジーといったり
ヴァイタミンといったり


140 名前: >136 投稿日: 2000/11/14(火) 19:23
unsigned ClipAdd4(unsigned a,unsigned b)
{
unsigned r = (a & 0x7f7f7f7f) + (b & 0x7f7f7f7f);
unsigned c = ((a>>1) & 0x40404040)
      + ((b>>1) & 0x40404040)
      + ((r>>1) & 0x40404040);
return  ( (~( ( (c>>7) & 0x01010101 ) + 0x7f7f7f7f) ) & 0x7f7f7f7f )
     | ( (c<<1) & 0x80808080 )
     |   r;
}


141 名前: 126 投稿日: 2000/11/15(水) 00:45
>>133-140
126です。133さん、某ランドさん、140さん
ご教示いただき、ありがとうございます。

アセンブラとフラグ、強力ですね。
できればcで書こうかなと思っていたのですが、
アセンブラソース見ていたら
アセンブラのほうがいいのかもと思いました。(^^;)

皆さんのアセンブラコードのテクニーク、
有り難く拝読、教科書にさせていただきます。m(__)m

僕が使ってたコードはこんな感じです。

inline DWORD add4byte( DWORD a, DWORD b)
{
DWORD t = (a & 0x7f7f7f7f) + (b & 0x7f7f7f7f);
DWORD u = (a ^ b) & 0x80808080;
DWORD m = ((a & b) | ((a ^ b) & t)) & 0x80808080;
m |= m - (m >> 7);
return (m ^ u) | t;
}

いまいち u,m がマターリしてます。(^^;)



142 名前: sage 投稿日: 2000/11/15(水) 00:52
あ return (t ^ u) | m です。