2026年05月13日

高速なシャッフル処理


1.はじめに
 X(旧Twitter)でシャッフル処理の話題があり、高速にシャッフルする方法について考察した結果をメモしておきたいと思います。
 今回は(も)ネットでググったり、AIに聞いたりせずに自力で検討を進めました。
 自力で検討した場合、「車輪の再発明」になってしまうかもしれませんが、思考過程を楽しみたいこと及び、ググった場合はその手法に捕らわれて思考の広がりが制限されてしまうことを避けたいためです。


2.物理的なシャッフル操作
 もともとのお題としてはトランプのシャッフル動作をプログラム化することが話の発端です。
 具体的には一山のトランプからランダムに一枚を選び、そのカードをトランプの山から取り除き、一列に並べていくという動作を繰り返すことでシャッフルされたカードの列を作り出すというものです。


3.トランプ操作とは異なるシャッフル方法
 前項で書いたトランプの操作は直感的にも偏りなくランダムに並べ替えられることが直ぐに判りますが、下記の「シャッフル処理1」でシャッフルしても、確率計算してみると均等にシャッフルできることに気が付きました。尚、下記の処理では0から9までの10個の配列要素をシャッフルしています(以降の処理も同様)。
       
シャッフル処理1(BASIC)  
10 DEFINT A-Z
20 N=10
30 FOR I=0 TO N-1:A(I)=I:NEXT
40 FOR I=0 TO N-1:SWAP A(RND(1)*N),A(I):NEXT
※RND(1)*N は自動的に整数変換された結果 0..N-1 の範囲の整数になる、SWAPは変数の値を交換する処理

 更に下記の「シャッフル処理2」の結果も確率計算してみると偏りなくランダムに並べ替えられるので、配列要素に連番を設定するループとシャッフルするためのループを同一にできました。
       
シャッフル処理2(BASIC)  
10 DEFINT A-Z
20 N=10
30 FOR I=0 TO N-1:A(I)=I:SWAP A(RND(1)*(I+1)),A(I):NEXT



4.シャフル処理の改善
 上記の「シャッフル処理2」ではループ処理の最初の I=0 の時に A(0) と A(0) を入れ替えているので無駄な乱数発生を行っていることになります。このことからN個の要素をシャッフルするには(N-1)回の乱数発生を行えばいいことが判ります(上記2項の「物理的なシャッフル操作」の場合も同数の乱数発生が必要ですね)。
 変数の初期値が零であることを利用して乱数発生回数を最小限になるように「シャッフル処理2」を改善した処理が下記になります(Iの初期値を1に変更)。
       
シャッフル処理3(BASIC)  
10 DEFINT A-Z
20 N=10
30 FOR I=1 TO N-1:A(I)=I:SWAP A(RND(1)*(I+1)),A(I):NEXT

 しかし、上記の処理は A(0) が零であることを前提にしているので、そのままでは再度シャッフルできないという欠点があります。
 そこでシャッフル処理だけに特化した下図の処理を考えました。これならば何度でもシャッフルすることが可能で、当然ですがシャッフル対象も連番である必要がないので汎用的なシャッフル処理として利用できます。
       
汎用化したシャッフル処理[(A(0)からA(N-1)の要素を高速にシャッフル]  
FOR I=1 TO N-1:SWAP A(RND(1)*(I+1)),A(I):NEXT
※Nはシャッフル対象要素の個数


5.フィッシャー・イェーツのシャッフル
 Xのコメントで教えて頂いたのですが「フィッシャー・イェーツのシャッフル」というシャッフル処理があります。ネットで「高速なシャッフル処理」を検索すると最初に出てきました。
 処理内容は上記2項に書いた「物理的なシャッフル操作」を効率よく行う処理になっています。計算量は上記の「汎用化したシャッフル処理」と同等で O(N) オーダーであり、高速です。
       
フィッシャー・イェーツのシャッフル  
要素数が n の配列 a をシャッフルする(添字は0からn-1):
  i を n - 1 から 1 まで減少させながら、以下を実行する
       j に 0 以上 i 以下のランダムな整数を代入する
       a[j] と a[i]を交換する
ウィキペディアより引用


6.あとがき
 ひょんなことからシャッフル処理の検討が始まり、現在最速と思われるフィッシャー・イェーツのシャッフルと同程度の速度で処理内容の異なるシャッフル処理まで辿り着きました。
 今回のような検討のトリガが得られるのもXの醍醐味ではないかと思います。また、安易にネット検索やAIに聞かないことで思考の過程を楽しむことができました。
 尚、今回辿り着いたシャッフル処理を skyriverのシャッフル と命名しますw


posted by skyriver at 19:22| Comment(2) | その他 | このブログの読者になる | 更新情報をチェックする

2026年04月01日

TMPZ84Compactの開発(その6)PICの乗算機能


1.はじめに
 秋月さんが秋葉原店で安売りしていた Super AKI-80 から取り外したCPU(東芝製TMPZ84C015)を使って開発した TMPZ84Compact(下の写真)はハードを開発してからかなり時間が経ちましたが、ここで制御用に使用している20ピンの PIC(PIC18F14K50)には8bitの符号無し乗算を1サイクルで実行できる命令があることを思い出しました。今回、この乗算機能を Z80 から利用できるようにしてみたので記録しておきます。

開発したTMPZ84Compact


2.PICの乗算命令
 下図は PIC のデータシートから引用した命令表の一部です。黄色マーカー部に記載されているように1サイクルで8bitの乗算が完了します。
 実は「CPLD(XC9572)で遊ぶ」の記事で書いた XC9572 を使って8x8の乗算器を作って TMPZ84Compact に接続してみようかとも考えていたのですが、上述のように PIC に同様の機能があるのでPIC 側を使うことにしました。

PICの命令表(抜粋)


3.Z80とのインターフェース
 もともと PIC から Z80 にパソコンとの通信機能やSDアクセス機能を提供しているので、同様の手法で乗算機能を利用できるように対応するサービスIDを追加しました。
 具体的には下記のようなコードでZ80が乗算機能を利用できるようにしました。

乗算機能使用のサンプルソース(Z80アセンブラ)
                                ;+++++++++++++++++++++++++++++++++++++++++++
                                ; PIC18 Mul service test
                                ;  ver 0.01 2026/04/01 skyriver
                                ;+++++++++++++++++++++++++++++++++++++++++++
                                
                                INCLUDE	TMPZ84C.INC

  0007                          MUL_SRV	EQU	7	; MUL service ID
                                
                                	ORG	0100H
                                
  0100    3E 07                 START:	LD	A,MUL_SRV
  0102    D3 01                 	OUT	(CMDPORT),A	; send mul service ID
  0104    2A 0200               	LD	HL,(MULVAL)
  0107    7D                    	LD	A,L
  0108    D3 00                 	OUT	(DATPORT),A	; send variable0
  010A    7C                    	LD	A,H
  010B    D3 00                 	OUT	(DATPORT),A	; send variable1
  010D    DB 00                 	IN	A,(DATPORT)	; get result(low)
  010F    6F                    	LD	L,A
  0110    DB 00                 	IN	A,(DATPORT)	; get result(high)
  0112    67                    	LD	H,A
  0113    22 0202               	LD	(RESULT),HL
  0116    C9                    	RET
                                
                                
                                	ORG	0200H
                                
  0200    04 05                 MULVAL:	DB	4,5
  0202                          RESULT:	DS	2
                                
                                	END

 CP/M環境でGAME言語を使って下記のソースで 0x00~0xff の全範囲での乗算結果の検証を行い、問題無いことを確認しました。
 尚、下記のソースで 1000~1040行の部分は動作確認のためのもので最終的には非実行にしています。

乗算機能の検証ソース(GAME言語)
1'++++++++++++++++++++++++++++++++++++
2' PIC18 Mul service function test
3'  ver 0.01 2026/04/01 skyriver
4'++++++++++++++++++++++++++++++++++++
10 M=$2000
20 M(1)=$2100 M(3)=$073E M(4)=$01D3 M(5)=$D37D
30 M(6)=$7C00 M(7)=$00D3 M(8)=$00DB M(9)=$DB6F
40 M(10)=$6700 M(11)=$2200 M(12)=M M(13)=$C9
50 #=2000
1000 /"input val0" M:4)=?
1002 ;=M:4)=0 #=-1
1010 "      val1" M:5)=?
1020 >=$2002
1030 /"result:" ?=M(0)
1040 #=1000
2000 I=0,255
2002  "."
2010  M:4)=I
2020  J=0,255
2030   M:5)=J
2040   >=$2002
2050   ;=M(0)<>(I*J) /"error at " ?=I " x " ?=J " ans:" ?=M(0) #=-1
2060  @=J+1
2070 @=I+1


4.乗算機能の評価
 追加した乗算機能を評価するために ASCIIART のアセンブラソースに適用してみました。この ASCIIART の処理は2バイトの固定小数点を使って高速化しています。2バイトの乗算を行うために乗数をバイトに分割して処理するバイト分割法を使いました。
 実行した際の画面キャプチャが下図になります。今回追加した乗算機能を使った場合、マンデルブロ描画は 14.5秒で完了しました(TMPZ84C015は6MHz12.5MHz、メモリウェイト無しで動作 ※修正 2026/04/02)。

ASCIIART実行画面

 ん~~、思った程には高速化していませんね・・
 実は元々のソフト演算による2バイト固定小数点処理を使ったものでは、4.6秒で描画が完了します。
 8bitの乗算処理単体では PICから提供する乗算機能の方が速そうですが、2バイト乗算ではバイト分割法によるオーバーヘッドがかなり大きいようです。

 最後に、2バイトの固定小数点乗算処理のソースも貼っておきます(後半が元々あったソフト乗算処理)。

2バイト固定小数点演算処理(Z80アセンブラ)
				if	01

                                ; use PIC's Mul Function
                                ; HL,DE <- value
                                ; HL -> result:HL*DE
                                ;    (256*x1 + x0)*(256*y1 + y0)
                                ;   = 2^16x1y1 + 2^8(x0*y1 + x1*y0) + x0*y0
                                ; 
                                ; |   .   |   .   |   .   |   .   |
                                ; <---  x1y1   --->
                                ;         <---  x0y1  --->
                                ;         <---  x1y0  --->
                                ;                 <---  x0y0  --->
                                
  01C8    0E 00                 MUL:	LD	C,0
  01CA    CB 7C                 	BIT	7,H
  01CC    28 07                 	JR	Z,Mul10
                                
  01CE    0C                    	INC	C
  01CF    AF                    	XOR	A
  01D0    95                    	SUB	L
  01D1    6F                    	LD	L,A
  01D2    9C                    	SBC	A,H
  01D3    95                    	SUB	L
  01D4    67                    	LD	H,A
  01D5    CB 7A                 Mul10:	BIT	7,D
  01D7    28 07                 	JR	Z,Mul20
                                
  01D9    0C                    	INC	C
  01DA    AF                    	XOR	A
  01DB    93                    	SUB	E
  01DC    5F                    	LD	E,A
  01DD    9A                    	SBC	A,D
  01DE    93                    	SUB	E
  01DF    57                    	LD	D,A
  01E0    CB 19                 Mul20:	RR	C		; Cy 1:negative
  01E2    08                    	EX	AF,AF'
                                
  01E3    3E 07                 	LD	A,MUL_SRV
  01E5    D3 01                 	OUT	(CMDPORT),A
  01E7    0E 00                 	LD	C,DATPORT
  01E9    ED 59                 	OUT	(C),E
  01EB    ED 69                 	OUT	(C),L
  01ED    ED 40                 	IN	B,(C)		; dummy read
  01EF    ED 40                 	IN	B,(C)
  01F1    D3 01                 	OUT	(CMDPORT),A
  01F3    ED 59                 	OUT	(C),E
  01F5    ED 61                 	OUT	(C),H
  01F7    ED 78                 	IN	A,(C)
  01F9    80                    	ADD	A,B
  01FA    5F                    	LD	E,A
  01FB    ED 78                 	IN	A,(C)
  01FD    CE 00                 	ADC	A,0
  01FF    47                    	LD	B,A		; B:E
  0200    3E 07                 	LD	A,MUL_SRV
  0202    D3 01                 	OUT	(CMDPORT),A
  0204    ED 51                 	OUT	(C),D
  0206    ED 69                 	OUT	(C),L
  0208    ED 78                 	IN	A,(C)
  020A    83                    	ADD	A,E
  020B    6F                    	LD	L,A
  020C    ED 78                 	IN	A,(C)
  020E    88                    	ADC	A,B
  020F    47                    	LD	B,A		; B:L
  0210    3E 07                 	LD	A,MUL_SRV
  0212    D3 01                 	OUT	(CMDPORT),A
  0214    ED 51                 	OUT	(C),D
  0216    ED 61                 	OUT	(C),H
  0218    ED 78                 	IN	A,(C)
  021A    80                    	ADD	A,B
  021B    67                    	LD	H,A
  021C    ED 78                 	IN	A,(C)		; dummy read
                                
  021E    08                    	EX	AF,AF'
  021F    D0                    	RET	NC
                                
  0220    AF                    	XOR	A
  0221    95                    	SUB	L
  0222    6F                    	LD	L,A
  0223    9C                    	SBC	A,H
  0224    95                    	SUB	L
  0225    67                    	LD	H,A
  0226    C9                    	RET
                                
                                
                                	else
                                
                                
                                MUL:	LD	BC,15*256
                                	BIT	7,H
                                	JR	Z,Mul10
                                
                                	INC	C
                                	XOR	A
                                	SUB	L
                                	LD	L,A
                                	SBC	A,H
                                	SUB	L
                                	LD	H,A
                                Mul10:	EX	DE,HL
                                	ADD	HL,HL
                                	JR	NC,Mul20
                                
                                	INC	C
                                	XOR	A
                                	SUB	L
                                	LD	L,A
                                	SBC	A,H
                                	SUB	L
                                	LD	H,A
                                Mul20:	RR	C		; Cy 1:negative
                                	EX	AF,AF'
                                	LD	C,H
                                	LD	A,L
                                	LD	HL,0
                                MulLoop:
                                	ADD	HL,HL
                                	RLA
                                	RL	C
                                	JR	NC,MulL10
                                
                                	ADD	HL,DE
                                	ADC	A,0
                                MulL10:	DJNZ	MulLoop
                                
                                	LD	L,H
                                	LD	H,A
                                
                                	EX	AF,AF'
                                	RET	NC
                                
                                	XOR	A
                                	SUB	L
                                	LD	L,A
                                	SBC	A,H
                                	SUB	L
                                	LD	H,A
                                	RET
                                
                                	endif
	
※2026/04/03 変更



[TOP] [ 前へ ] TMPZ84Compactの開発 [ 次へ ]

posted by skyriver at 22:42| Comment(2) | Z80 | このブログの読者になる | 更新情報をチェックする

2026年03月06日

XがSeesaaドメインを危険視リストに追加?


1.はじめに
 Xにポストされたメッセージ内にあるSeesaaドメインのURLをクリックすると警告が表示されることに2026年03月05日に気が付きました。
 Grokさんに確認したところ、SeesaaドメインがXの危険視リストに追加されていることが原因のようです。


2.問題内容
 ポスト内容に記載されたSeesaaドメインのURLをクリックしてURLページに飛ぼうとすると下図のような警告が表示されるようになりました。

URLクリックで表示される警告

 上記の警告は私がポストしたメッセージ内にあるURLをクリックした際に表示されたものです。警告の末尾に書いてある「続ける」をクリックすると対象のページが表示されますが、この状態で「続ける」をクリックする人は少ないのではないかと思います。
 X内でSeesaaドメインを検索し、メッセージ内にあるSeesaaドメインのURLをクリックしても同様の警告が表示されました。


3.原因
 XのAIであるGrokさんに聞いてみた結果が下記になります。クリックすると拡大表示されます。

Grokさんの回答


4.対処
 上記の回答の最後に書いてある「まとめ」の直前に「Seesaa側がXに「誤検出です」と申請しない限り、ドメイン単位のブロックは解除されにくい」と書いてあるので、Seesaaさん側にXに解除申請をするように依頼しておきました。
 状況に変化がありましたら追記したいと思います。


★追記 2026/03/07
 本件に関して Seesaa さんから「【重要】X(旧Twitter)への「seesaa.net」URL投稿について」のお知らせが発出されました。
  • X(旧Twitter)側に対して、弊社公式アカウント等から異議申し立ておよび調査依頼中
  • 異議申し立てには、以下のフォーム等を通じて対応
     https://help.x.com/ja/forms/authenticity/spam
  • 暫定対応について(リンク共有用ページのご案内)
    下記の「共有用リンクの作成」によりURLをseesaa.jpドメインに変換すればXへの投稿が可能
     https://blog.seesaa.jp/pages/link
とのことです。
 効果の程は??ですが、上記の「異議申し立て」ページで本ブログのURL(https://piclabo.seesaa.net/)を誤ってブロックされたリンクとして報告しておきました。


★追記 2026/03/11
 seesaa.net がXの危険リスト(潜在的に有害なリンク判定)から中々削除されないようなのでGrokさんに削除される可能性について聞いてみた際の回答が下記です。
  • 削除される可能性は60~70%程度
  • 削除されるまでの期間は数週間から1ヶ月以上かかる可能性がある

Grokさんの回答(その2)


★追記 2026/03/11 12:38
 Xでのクリックを今試したら、警告表示無しでブログが表示されました。
 seesaa.netドメインがXの危険視リストから削除されたようです。^^




posted by skyriver at 08:41| Comment(0) | 日記 | このブログの読者になる | 更新情報をチェックする