トップページ⇒tech
142コメント40KB

ちょっとしたテクニークスレッド

■ このスレッドは過去ログ倉庫に格納されています
0001名無しさん@お腹いっぱい。NGNG
if( hogehoge == 1 )
を
if( 1 == hogehoge )
と書くと、イコールが一個しかなかったときエラーに
なってくれる。

#罵倒をおそれずかきこめー
0002>1NGNG
その話題ふると 恐い人がやってくるのでsageですぅ
0003名無しさん@お腹いっぱい。NGNG
(define (dbg x . s) (for-each display s) (display x) (newline) x)
0004名無しさん@お腹いっぱい。NGNG
つーか、1(最初の文章)に
>#罵倒をおそれずかきこめー
だけ書いて
2に内容書けばよかったのに・・・


struct hoge {
  char *ptr;
  char str[1];
};
C++だと使いにくいが…
0005名無しさん@お腹いっぱい。NGNG
VC++だと
struct hoge{
 char *ptr;
 char str[0];
}
が出きるから、それに慣れてたせいでgccに移植するときに泣いたことが…
0006名無しさん@お腹いっぱい。NGNG
>4@`5
それって何に使うんですか?純粋に知りたいです。
00074NGNG
つい、例にポインタをいれてしまったので、わかりにくいか。

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

もちろん、charに限らず、
「不定長の領域を本体とは別に確保する必要がある場合」に、
使う事が出来る。
00081NGNG
誰も上げないので
あげ
0009>6NGNG
構造体の最後のメンバが可変長のデータを持っている(指しているのではない)
の時に使います。
とくに、生成から消滅までの間固定長だけど、モノによってデータサイズが違う
ときに有効です。
0010名無しさん@お腹いっぱい。NGNG
Shift-JIS 漢字第一バイトの判定

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

のかわりに

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

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

0011このスレおもしろいかもNGNG
//1と2を入れ替える
i := (i - 1) * (-1) + 2;
{
if i = 1 then
 i := 2
eles
 i := 1;
}
2つもコメントを入れてしまった俺は根性なし・・・
0012名無しさん@お腹いっぱい。NGNG
<10
2つ以上の範囲の判定なら、いつでも使えそうですね。
0013名無しさん@お腹いっぱい。NGNG
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は奥深いよ……。
0014名無しさん@お腹いっぱい。NGNG
常識かもしらんけど。

#define SWAP(a@`b) (a^=b@`b^=a@`a^=b)
0015>11NGNG
i = (1+2) - i;
でええんとちゃうの?
BASIC時代にはしょっちゅう使ったテクだが。
0016名無しさん@お腹いっぱい。NGNG
>15
つーか、それって3-i
0017名無しさん@お腹いっぱい。NGNG
有名かもしれんが、

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


00186NGNG
>7@` 9
なるほど〜。
WinAPIでパレットいじるときのあれみたいなものですね〜。
どうもありがとうございました。
0019>13NGNG
それ以前に
COMBOやMSFLEXGRIDなんかは

Combo1.Visible = False

処理

Combo1.Visible = True

とするとオーバーヘッドが発生するはずなのになぜかかなりの高速化になる。
0020名無しさん@お腹いっぱい。NGNG
LD BC@`DEを実現する
PUSH DE
POP BC
0021名無しさん@お腹いっぱい。NGNG
ALの符号をAHに拡張する
CBW
0022>20NGNG
mov b@` d
mov c@` e
でいいと思うんだけど。なぜにスタックを使う?
メモリを介さない分、速いだろうとおもうのですが。
002320NGNG
>>22
??言われてみれば、そうだな……。Z80の話だからなあ。
よく覚えてねえや。
じゃあ、これでどうだ
XCHG BC DE を実現する
PUSH BC
PUSH DE
POP BC
POP DE
0024名無しさん@お腹いっぱい。NGNG
inline int IsShiftJIS(unsigned char c)
{
 if(c>=0x81)
 {
  if(c<=0x9F)
   return 1;
  else
  {
   c += 0x20;
   if(c <= 0x1C)
    return 1;
  }
 }
 return 0;
}

こう言うのはやっぱり無駄な努力なんでしょうか。
0025!=22NGNG
どうだ、って、それもaを使って6回LDする方が速いんじゃねーの?
002620NGNG
>>25
かな?
まあ、アキュムレータを使わないでも済む方法、ってことで一つ……。
どっちが早いかは、今手元に資料が無いから分かんないよ。
0027!=22@`25 NGNG
8ビット汎用レジスタ間LDは全部4クロック、PUSH/POPは11+10クロック
だから、スタックは使わない方が基本的に速い。
23のはAレジスタ使わないなら
PUSH BC
LD B@`D
LD C@`E
POP DE
あたりで妥協かな。
0028名無しさん@お腹いっぱい。NGNG
ageてみよう
0029名無しさん@お腹いっぱい。NGNG
>>14
逆の意味で常識。
SWAP(x@` x);
とした場合、何が起こる?
0030名無しさん@お腹いっぱい。NGNG
0と1を入れ替え。

int a = 0;
a = 1 - a;

すげーだろー。
0031名無しさん@お腹いっぱい。NGNG
>30
a^=1; でええやん。

0032名無しさん@お腹いっぱい。NGNG
人差し指と薬指で広げておいて、中指を膣口に忍ばせ、
更に親指はクリトリスを責める!
0033名無しさん@お腹いっぱい。NGNG
0からN-1までをなめるとき、
for (int i = N - 1; i >= 0; --i) {
...
}
みたいに判定を0で行うとほんの少し速くなるかも
#こんなこと気にしながらプログラム書きたくないけど・・・
0034ミトコンドリ子NGNG
アタシはこっちの書き方のほうが好きよ。
for ( int i=N ; --i >= 0 ; ) {...}
Nの表記が長いときに -1 が紛らわしくならないからよ。

0比較のため、というよりはインデックス逆巡回を書くときの
イディオムよね。
0035名無しさん@お腹いっぱい。NGNG
>>33@`>>34
境界判定のための比較が要らなくなるか、
って、アセンブラなら減産して0だった時点でZeroフラグ立つよね。

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

003633NGNG
>>34
>for ( int i=N ; --i >= 0 ; ) {...}
あ、、、きれい・・・いただきます:-)

>0比較のため、というよりはインデックス逆巡回を書くときの
>イディオムよね。
んーでも、比較すべき数値をレジスタにロードしなくて良い分
速いかなぁと・・・CPUによりけりですけど。
おまじないのように上記のようにがんばって書いてました。
「もうちょっと速くなりますように」とお祈りしながら・・・
003733NGNG
>>35
>Cって、
>オプティマイズされたオブジェクトなら、意外な方法で高速にしたりするんで、意味無し!
いや、先の例で、Nが変数のときには
for (int i=0; i < N; ++i) {...}
で、比較部分がほんのちょこっとだけ最適化あまくなるようなきがしません?
まあ、目に見えて速くなるわけではないですが、
藁にもすがりたいときにはおまじないとしてやってます。。。
だめっすかねぇ・・・
0038名無しさん@お腹いっぱい。NGNG
for ( int i=N ; --i >= 0 ; ) {...}  って
for ( int i=N ; i-- ; ) {...} でも可?
0039名無しさん@お腹いっぱい。NGNG
x+=(button==RIGHT)-(button==LEFT);
y+=(button==UP)-(button==DOWN);
(;´Д`)
0040名無しさん@お腹いっぱい。NGNG
すんません
ここの人はアセンブラとかにも詳しいのかな?
便乗質問させてください。

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

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

の両方のケースで教えてください。
0041名無しさん@お腹いっぱい。NGNG
>>40
何故自分で確かめない?
0042名無しさん@お腹いっぱい。NGNG
x=y=z=0;
(;´Д`)
0043名無しさん@お腹いっぱい。NGNG
>>40
ループ回数違うような・・・
あと、iが0になったかどうかだけで判定してますが
Nが負で渡ってきちゃったときとか不安・・・
iのスコープも違ってるし・・・

スピードは同じっぽそう。逆アセンブルして確かめよう。
0044名無しさん@お腹いっぱい。NGNG
自分の目で確かめろ。
アゲてるやつはみんな白痴。
0045名無しさん@お腹いっぱい。NGNG
他人を白痴呼ばわりするのって楽しい?
0046名無しさん@お腹いっぱい。NGNG
>>45
あなたは、そんなこと聞いてどうするの?
0047名無しさん@お腹いっぱい。NGNG
int a@`b@`c;
....;
if(int d=a-b)
{
d+=...;
c+=d;
}
(;´Д`)
0048名無しさん@お腹いっぱい。NGNG
何これ?>47
0049名無しさん@お腹いっぱい。NGNG
>>45
たのしぃでぇ〜す。

酔っぱらい関数きぼん。
0050名無しさん@お腹いっぱい。NGNG
ここおもろい!!わしもかきこ!!

nビットのマスク生成

(1 << n) - 1;
0051名無しさん@お腹いっぱい。NGNG
あらら、sageばっかり・・・
あげちゃえ!
0052名無しさん@お腹いっぱい。NGNG
mvi a@`0
ではなく
xra a
とすると1バイトで済む

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

dadで16bitの引き算をするには…
bcとdeをxchgしたい時には…
は当たり前の事か
0053名無しさん@お腹いっぱい。NGNG
bool light0;
…;
(light0?Enable:Disable)(LIGHTING);
(;´Д`)
0054名無しさん@お腹いっぱい。NGNG
CMP AL@`0Ah
SBB AL@`69h
DAS

5バイトの1桁16進バイナリ−ASCII文字変換。
有名だねー。
0055名無しさん@お腹いっぱい。NGNG
CLEAR @`&HBFFFしないでGVRAMにアクセスするルーチンをC000以前に置くには
文字列変数に入れてVARPTR()の値を参考に絶対アドレスの部分を書き換える

って何の話だ
0056名無しさん@お腹いっぱい。NGNG

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
0057名無しさん@お腹いっぱい。NGNG
typedef unsigned char BYTE;
typedef struct { BYTE stuff[100]; } BYTE100;

*(BYTE100*)px = *(BYTE100*)py; //memcpy(px@`py@`100)と同じ?
0058名無しさん@お腹いっぱい。NGNG
>>56
よかったらJIS2SJISも書いてくださ〜い。
0059名無しさん@お腹いっぱい。NGNG
int c の b ビット目の on / off

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

ダサイ???
0060名無しさん@お腹いっぱい。NGNG
#define BIToff(b@`c) ((c) = (c) & ~(1 << (b)))
c++ を無意識に使う怖さから、inline にしたほうがいいと思うが。
0061名無しさん@お腹いっぱい。NGNG
>54
6809版
ADDA #$90
DAA
ADCA #$40
DAA

6バイト
0062名無しさん@お腹いっぱい。NGNG

#define BIT_Reverse(b@`c) ((c)=(c)^(1<<(b)))
0063名無しさん@お腹いっぱい。NGNG
なんか、懐かしのテクニークスレッドと化してきたな(ワラ
0064名無しさん@お腹いっぱい。NGNG
>>63
しょうがねぇじゃん。ここに書いてる奴はみんなレベル低いんだから。
0065名無しさん@お腹いっぱい。NGNG
オマエモナーと言われたいM男君が増えてるな
逝ってやらん
0066名無しさん@お腹いっぱい。NGNG
age
0067名無しさん@お腹いっぱい。NGNG
ここにHerrさんいるでしょ。
0068名無しさん@お腹いっぱい。NGNG
#DIV(x@` y) (y ? x / y : 0)

うーん、こんなのは?
望んだ結果が出ないかもしれんけど。
006968NGNG
あ、((y) ? (x) / (y) : 0) だな。
0070名無しさん@お腹いっぱい。NGNG
>>68 何に使うの? 無限大を0に修正する? 用途を示してくんない?
0071名無しさん@お腹いっぱい。NGNG
除算エラーにしたくないのでしょう。
0072>70NGNG
たぶんゼロ除算例外を防止する為でしょう。

でも、その前の段階でyがゼロにならないよう管理すべきだと思ってたから
こんな事はやったことないな。逆に原因不明にするだけじゃん。
0073名無しさん@お腹いっぱい。NGNG
>>72 わしもそう思う。

007470NGNG
ゼロ除算防止なのは、わかる。
オレも72の言うとおりこのマクロの使用では原因不明になるだけじゃないのか
と思う。

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

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

#行列の特異値分解かなにかで 1/ε -> 0 (εは非常に小さい正数)と
置き換える場合とかがあった気がする。でもその場合はこのマクロは
使えないとも思う。
0075名無しさん@お腹いっぱい。NGNG
ビット数をカウントするアルゴリズムでさぁ
0x7777とか、0x33333?とか使うやつあったっしょ
あれってどーゆーのだっけ?
0076名無しさん@お腹いっぱい。NGNG
>>75
そこまで分かってるなら自分で検索すれ!
http://www.st.rim.or.jp/~phinloda/cqa/cqa15.html
007775NGNG
ありがと。(探したけど、見つからなかったの、ゆ・る・し・て)
0078名無しさん@お腹いっぱい。NGNG
ちょっとズレるけどさ、マクロって関数コールのオーバーヘッドを
避けるために多用したりすることってないの?>制御分野のお方。
0079>78NGNG
僕は制御じゃないけど
複雑になりそうな場合マクロをやめて関数にしてpragmaでinline化します。
移植性は下がるけど、可読性のほうが大事なので。
0080名無しさん@お腹いっぱい。NGNG
制御用のクロスコンパイラは実装が貧困すぎて
inlineできないのがあります。
0081名無しさん@お腹いっぱい。NGNG
最近は制御系にもgccとか使われる場合が結構ある。
0082>78NGNG
あるよ。
0083ななしさん@目立ちたがりの厨房NGNG
コメントテク。
通常、
/*
....
*/
と書くが、
/*
....
//*/
と、コメントアウトしておくと、
//*
....
//*/
と、最初の一行に'/'一個追加するだけで、"...."の行が有効になる。

デバッグの時にちょっと便利。
0084名無しさん@お腹いっぱい。NGNG
偶数化:変数 & -2
0085名無しさん@お腹いっぱい。NGNG
>76
ちなみにどんなキーワードで見つけたの?すごい
0086吾輩は名無しさんであるNGNG
ここあとで修正しとく必要があるなーってとこには
/**/を書いときます。
0087名無しさん@お腹いっぱい。NGNG
>>83
頼むからやめてくれ。
008868じゃないけどNGNG
>>68-74
もちろん、y=0にならないように書くのが正しいんだけど、仕事でゲームの
開発をしていると、最悪でも例外がおきないようにしておくのはわりと
大事だったりします。
# ハングるよりは変な場所に表示される方がマシってこと。
008968NGNG
あ、遅レスだけど 71-73@`88 の言う通りですね。
まあこれは 88 の言うように許容できる場合に限るので今考えると特殊な部類に入るかもね…
返す値を 0 じゃなくて自作関数で説明入りエラー吐くようにしておけば 0 割りのトラップもしやすいかもね。
0090名無しさん@お腹いっぱい。NGNG
0が返っても許容できる、じゃなくて、
エラー処理の存在自体が許容できないわけです。ゲームでは。
0091名無しさん@お腹いっぱい。NGNG
ちょっとしたテクニークスって事で
typedef で一度にポインタも定義出来ます

例:
typedef struct { なんとかかんとか} HOGE@`*PHOGE;
0092名無しさん@お腹いっぱい。NGNG
<91
typedefの書式は、識別子の宣言とおなじだからね。
0093名無しさん@お腹いっぱい。NGNG
常識と思うけど大文字化(ASCII 文字セット限定)
c には英文字が入ってると思いねぇ
char to_upper(char c) {
return c & ~0x20;
}
0094名無しさん@お腹いっぱい。NGNG
>>91
const PHOGE
ってやってハマる奴がたまにいる。
0095>>93NGNG
普通のtoupperじゃなんであかんの?
0096Dr.URINGNG
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);
  }
}
0097名無しさん@お腹いっぱい。NGNG
#define FLAG_CHECK( NUM@` FLAG) ((NUM & FLAG) / FLAG)
#define FLAG_ON( NUM@` FLAG) NUM |= (NUM ^ FLAG)
#define FLAG_OFF( NUM@` FLAG) NUM ^= (NUM & FLAG)

いまどきフラグなんてせこい使い方しないか?
0098ビット操作を最近覚えた人NGNG
>>97
結構便利なんですが、、、
例えばゲームの毒、混乱、眠りなどの状態を表すとか。
0099名無しさん@お腹いっぱい。NGNG
#define FLAG_CHECK(NUM@` FLAG) (!!(NUM & FLAG))
の方が好みだ。
0100名無しさん@お腹いっぱい。NGNG
#define FLAG_CHECK(NUM@` FLAG) (((NUM)&(FLAG))==(FLAG))
0101ビット"猿"ZよかNGNG
ビットフィールド使うなぁ…
0102名無しさん@お腹いっぱい。NGNG
>>101
俺もビットフィールド使うなぁ…
0103虹NGNG
>>101-102
フラグとかをビットフィールトで、
struct {
int a:1;
int b:1;
} flag;
とかで定義した場合、すべてを0でクリアするとき、
*(int *)&flag=0;
とか書いてるんですけど、もっとエレガントな方法はないでしょうか?

i
0104名無しさん@お腹いっぱい。NGNG
>>103
UNION使っとけ!
0105名無しさん@お腹いっぱい。NGNG
この場合 int だと変な領域に書込んでしまわないか?
0106名無しさん@お腹いっぱい。NGNG
左辺値のポインタのキャスト、よくある勘違いだよね。
0107名無しさん@お腹いっぱい。NGNG
どなたか MMX の飽和演算を高速に真似る方法を教えてください。
4つの8ビットに加算したとき、ループせずに 0xff で飽和する演算を
考えていたのですが if 文を使う以外にいい方法が思いつきませんでした。

BYTE a@` b;
int c;
c = a + b;
if( c > (BYTE)0xff ) c = 0xff;
... 以下 4 つ繰り返し。
0108名無しさん@お腹いっぱい。NGNG
0xff * 0xffサイズのテーブルを作る……
って、今のPCだと逆効果かも。
0109108NGNG
あう、0x100 * 0x100サイズの間違い
ああ鬱だし脳
0110名無しさん@お腹いっぱい。NGNG
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;
}

うまく使わんと、パーシャルレジスタストールの餌食になるよ。
0111110NGNG
clはdlでもよかった…
0112>110NGNG
どこがテクニークなの?
0113名無しさんNGNG
Cでやるならテーブルが一番手軽だろ。
BYTE Table[2]={0@`0xFF};
BYTE a@` b;
int c;
c = a + b;

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

255+255は512以下だからな。
0114飽和加算NGNG
86系のアセンブラなら、alに3つ足して ahに127を足して、符号拡張
して、alとandかな。
4つ足した数を使って飽和させるほうが早い気がする。
どっちにしろ、cでifを使うのにくらべて、測定可能な速度差が出るかど
うかは、わからんけど。
0115名無しさん@お腹いっぱい。NGNG
あまり気にしすぎるのも時間の無駄のような気がするなぁ。

前いた会社に最適化マニアがいて、きちんと動いてるのに
まだ速くする!とか言ってゴネてくれたが・・・。
0116虹NGNG
>>104
unionだと、
union {
int all;
struct {
int a:1;
int b:1;
} bit;
} flag;
みたいな書き方になると思うのですが、それだと階層が一つ深くなる
じゃないですか。
>>105-106
すいません、どこがまずいのかわかんないです。
0117名無しさん@お腹いっぱい。NGNG
>116
sizeof flag をかんがえてごらん
0118107NGNG
>>108-115
皆さんご教授いただきありがとうございます
インラインアセンブラやビット操作で if 文は削ることが
できるんですね、勉強になりました。

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

c |= (BYTE)((0x100) - (c >> 8));
これでもいいのかな
0119>117NGNG
116のまずいのは、そっちじゃない気がするんだけど…
0120119NGNG
116でなくて、>>103ね
0121>113@`118NGNG
なんでOR演算になってるの?
0122121NGNG
これでどう?
BYTE Table[2]={0xFF@`0};
c &= Table[c >> 8];
---
c &= (0 - (c >> 8));
0123121@`122NGNG
あ、ごめん。大きな勘違いだった。氏のう。
0124虹NGNG
すいません、まだ引っ張ります。
>>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です。
0125名無しさん@お腹いっぱい。NGNG
そりゃANSIだとビットフィールドはintに満たなくてもintに切り上げられるからねえ。
0126107NGNG
>>121
>c &= (0 - (c >> 8));

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

c |= -(c >> 8);
これで定数が消えました。いいかんじになってきました。
shr eax@` 8
neg eax
or ebx@` eax
(たぶんコンパイルするとこんな感じになりそう)
これ以上の高速化は 8bit * 4 を一気に処理するしかないでしょうか。
0127名無しさん@お腹いっぱい。NGNG
テクニークとかく事。
0128名無しさん@お腹いっぱい。NGNG
>>126
>c |= -(c >> 8);
>これで定数が消えました。いいかんじになってきました。

よくわからんな。その処理ってなんなんだ?
0か1になった奴を答えから引くことに何の意味がある?
0129Visual名無しさんNGNG
>>128
0xffを越えてれば
c |= 0xff
でなけりゃ
c |= 0x00
って感じだから問題ないだろ。
0130名無しさん@お腹いっぱい。NGNG
>128
8bit同士の加算だと、飽和してるのは 0x100〜0x1fe だ。
8bitシフトすると1 になるのだな。
で、これを符号反転すると(2の補数表現だと)0xff になって、
飽和しない場合は 0 を符号反転するから 0 。
で、>>129のようになってめでたしめでたし。
0131123NGNG
>126
厳密には
c = (c | -(c >> 8)) & 0xFF;
だね。後で代入時にキャストするから書かなかっただけかな?
また勘違いだったらごめん。
0132126NGNG
>>131
>後で代入時にキャストするから書かなかっただけかな?

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

まとめて処理するのを考えていますがなかなか難しいです。
0133名無しさん@お腹いっぱい。NGNG
>132
4つ足してからなら>>114の方法でええんでないの?
Cで書くなら 0x7f00を足して16ビットシフトして符号反転、かな。
0134133NGNG
15ビットシフトして、だった。
0135133NGNG
ああ、0x7f00じゃだめだな、まぁ、察してくれや。
0136某ランドNGNG
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;
}
0137某ランドNGNG
がんばってみたけど、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;
}
0138某ランドNGNG
ごめん、こっちだ
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;
}
0139名無しさん@お腹いっぱい。NGNG
エナジーといったり
ヴァイタミンといったり
0140>136NGNG
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;
}
0141126NGNG
>>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 がマターリしてます。(^^;)
0142sageNGNG
あ return (t ^ u) | m です。
■ このスレッドは過去ログ倉庫に格納されています