HSPポータル
サイトマップ お問い合わせ


HSPTV!掲示板


未解決 解決 停止 削除要請

2013
0506
qqqHSPでのビット操作4未解決


qqq

リンク

2013/5/6(Mon) 09:49:49|NO.53826

さて、最近非常に大きなデータを扱うことになったのですが、
それが真と偽の区別しか必要ないデータなんです。
0と1だけの区別しかないのに1byteづつ使っているととんでもないことになる量なので、
ビット操作をしようということになりました。

で、文字列型変数を使うことにして、次のようなソースを書きました。
(下ソース自体はintでもdoubleでもいけると思います)

#module #deffunc BitPokeO var _dat, int _n, int _f //p1変数のp2 bit目を変更します。 //p2は0から開始します。 //p3には0かそれ以外を指定して、off/onとします。 _Chk =_n>>3 _Chkn =_n-(_Chk<<3) if _f{ poke _dat,_Chk,peek(_dat,_CHk) or 1<<_Chkn }else{ poke _dat,_Chk,peek(_dat,_CHk) and 1<<_Chkn xor peek(_dat,_Chk) } return //"BitPokeO _a,0,1"を実行すると_aは1に、"BitPokeO _a,8,1"では256になります。 #global #module #defcfunc BitPeekO var _dat, int _n //p1変数のp2 bit目を参照します。 //p2は0から開始します。 //返り値は0かそれ以外です。1以外が返る場合に注意してください。 _Chk =_n>>3 _Chkn =_n-(_Chk<<3) return peek(_dat,_Chk) and 1<<_Chkn #global
割り算とかも最初は考えたのですが、そもそもの用途からして、
この命令と関数は何度も実行されるものですよね。
実行時間が長くなると困るので、ビットシフトで代用しました。

それで、ここからが本題なのですが、
このソース、もっと早くはならないでしょうか。

何かいいお考えをお持ちの方は教えてください。



この記事に返信する


KA

リンク

2013/5/6(Mon) 10:33:07|NO.53828

>>1byteづつ使っているととんでもないことになる量なので、
>>ビット操作をしようということになりました。

なぜ8倍の処理を選ぶのか、その発想が分からない。
質問も具体性に欠け、スクリプトから読み解く気力も出てこない。



y.tack

リンク

2013/5/6(Mon) 11:40:34|NO.53830

僕が書くとこうなりました

#module #defcfunc is_bit int n,int m switch n case 1:if m&1:return 1:return 0 case 2:if m&2:return 1:return 0 case 3:if m&4:return 1:return 0 case 4:if m&8:return 1:return 0 case 5:if m&$10:return 1:return 0 case 6:if m&$20:return 1:return 0 case 7:if m&$40:return 1:return 0 case 8:if m&$80:return 1:return 0 default:return 0 swend dialog "error",1 return-1 #defcfunc is_bytes int bytes,int bytes_index,int n switch bytes_index case 1:return is_bit(n,bytes&$ff) case 2:return is_bit(n,(bytes>>8)&$ff) case 3:return is_bit(n,(bytes>>16)&$ff) case 4:return is_bit(n,(bytes>>24)&$ff) swend dialog "error",1 return-1 #global mes is_bit(2,3) mes is_bit(3,3) mes is_bytes($200,2,2) mes is_bytes($300,2,3)
文字列管理はめんどくさいからintで済ますくらいです
Cだとswitch使った方が早そうですが
HSPのswitchはelseifみたいな印象があってどっちが早いかわからないです

0と1で1byteづつ使ってもとんでもない量にはならないような
じゃあ画像はどうなるんだ?という話で
0と1で1byteづつ使ってとんでもない量になるスクリプトは
SQLele使うといいかも
(いや。僕はまだ使ったことないんですが)

0と1の計算をとんでもない量計算するのは
PC(いやワークステーション向き計算?という意味で)の
範疇超えてる気がするんですがどうなのでしょうか?

僕もそんなにスキルありませんが可読範囲で十分早いような

いっそマシン語に移植するしかないという見解もありそうです



y.tack

リンク

2013/5/6(Mon) 11:59:33|NO.53831

>さて、最近非常に大きなデータを扱うことになったのですが、
>それが真と偽の区別しか必要ないデータなんです。
うーん。絶対Cで書いた方が早いような
GUIじゃなくて良さそうなのでHSP向きじゃない処理だと思います
インラインアセンブラも使えますし
ってCのインラインアセンブラは日本語の資料少ないんですが
Visual C++ Expressのインラインアセンブラに挑戦しても
マシン語学ぶより楽でしょう

なんかアプリ作成じゃなく一回きりの操作ぽいので
考えずにそのモジュールでガリガリ計算してれば
既に大分進んでるような



ツノン

リンク

2013/5/6(Mon) 16:58:57|NO.53844

以前書いたスクリプトから。
指定数のbit を完全に含む ビット列を作成して、各ビットの操作を行います。

////////////////////////////////////////////////////////// // // Name : BITSTRING_MCRS 1.00 // type : Header // date : 2012/04/15(確認) // ////////////////////////////////////////////////////////// // ビット列を作成します。 // 主にアプリケーションで 1タイプのみBIT列を使用する場合に適しています。 // 引数として // BITSTRG_ONE_ELEMENT_SIZE に 32 で割り切れる数字 // 1 2 4 8 16 // のいずれかを指定すると // 1 要素の bit 数を指定できます。 // それ以外は1配列要素毎に無駄な領域が発生する恐れがあります。 #ifndef BITSTRG_ONE_ELEMENT_SIZE #const global BITSTRG_ONE_ELEMENT_SIZE 1 #endif #define global ctype MAKE32BITMASK(%1)\ ((%1>=32)<<31|(%1>=31)<<30|(%1>=30)<<29|(%1>=29)<<28|(%1>=28)<<27|(%1>=27)<<26|(%1>=26)<<25|(%1>=25)<<24|(%1>=24)<<23|(%1>=23)<<22|(%1>=22)<<21|(%1>=21)<<20|(%1>=20)<<19|(%1>=19)<<18|(%1>=18)<<17|(%1>=17)<<16|(%1>=16)<<15|(%1>=15)<<14|(%1>=14)<<13|(%1>=13)<<12|(%1>=12)<<11|(%1>=11)<<10|(%1>=10)<<9|(%1>=9)<<8|(%1>=8)<<7|(%1>=7)<<6|(%1>=6)<<5|(%1>=5)<<4|(%1>=4)<<3|(%1>=3)<<2|(%1>=2)<<1|(%1>=1)<<0) #const global BITSTRG_SHIFT_OFSET 32/BITSTRG_ONE_ELEMENT_SIZE #const global BITSTRG_MASK MAKE32BITMASK(BITSTRG_ONE_ELEMENT_SIZE) // インデックス を計算する /*配列インデックス*/ #define global ctype bitstrg_Ai(%1) (%1/BITSTRG_SHIFT_OFSET) /*ビットインデックス*/ #if (BITSTRG_ONE_ELEMENT_SIZE==1) #define global ctype bitstrg_Bi(%1) ((%1\BITSTRG_SHIFT_OFSET)) #else #define global ctype bitstrg_Bi(%1) ((%1\BITSTRG_SHIFT_OFSET)*BITSTRG_ONE_ELEMENT_SIZE) #endif // 配列の要素数を計算する。 #define global ctype bitstrg_CalcEleTotal(%1) \ (bitstrg_Ai(%1))+(bitstrg_Bi(%1)!=0) // ビット操作 /*ビット列の作成*/ #define global CreateBitString(%1,%2)\ dim %1 , bitstrg_CalcEleTotal(%2) /*指定ビットの切替*/ #define global ctype bitstrg_Xor(%1,%2=0,%3=BITSTRG_MASK)\ %1(bitstrg_Ai(%2)) ^ %3<<(bitstrg_Bi(%2)) /*指定ビットを立てる*/ #define global ctype bitstrg_Or(%1,%2=0,%3=BITSTRG_MASK)\ %1(bitstrg_Ai(%2)) | %3<<(bitstrg_Bi(%2)) /*指定ビットを読み込む*/ #define global ctype bitstrg_And(%1,%2=0)\ ((%1(bitstrg_Ai(%2)) >> bitstrg_Bi(%2))&BITSTRG_MASK) //######################### ここまで ############################## // テスト CreateBitString buf,80 // 80bit のビット列を作成 bitstrg_Or(buf,3) // 3 を立てる bitstrg_Or(buf,5) // 5 を立てる bitstrg_Or(buf,64) // 64を立てる bitstrg_Or(buf,31) // 31を立てる bitstrg_Or(buf,64) // 64を立てる bitstrg_XOr(buf,31) // 31を切り替える val = bitstrg_Or(buf,10) // 左辺の変数に対して代入すると、配列の変更後の値を読み出す。ビット列の変更はされない。 /*出力してみる*/ tx="" repeat 80 tx+= ""+bitstrg_And(buf,cnt) if(cnt\32==31):tx+=" " loop mesbox tx,ginfo_winx,ginfo_winy



ONION software Copyright 1997-2023(c) All rights reserved.