title

Raspberry PI 3

更新:2025-04-25 下村清 / sameon@asahi-net.email.ne.jp

2025-04-25 「SWI-PROLOG 日本語を使う」
参照:
「Prologを学ぶ ーー文化とその実践ーー」 杉崎昭生著 海文堂 1995

$ nano 事実.pl
...
醸造酒(ビール).
醸造酒(ワイン).
蒸留酒(ブランデー).
蒸留酒(ウィスキー).
こはく色(ブランデー).
こはく色(ウィスキー).
こはく色(ビール).
淡黄色(ワイン).
...

$ swipl 事実.pl
Welcome to SWI-Prolog (threaded, 64 bits, version 9.0.4)
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software.
Please run ?- license. for legal details.

For online help and background, visit https://www.swi-prolog.org
For built-in help, use ?- help(Topic). or ?- apropos(Word).

?- 醸造酒(ブランデー).
false.

?- 醸造酒(ビール).
true.

$ nano 階乗.pl
...
階乗(0,1) :- !.
階乗(1,1) :- !.
階乗(_値N, _階乗値) :-
    _値N1 is _値N - 1,
    階乗(_値N1, _階乗値1),
    _階乗値 is _階乗値1 * _値N.
...

$ swipl 階乗.pl
Welcome to SWI-Prolog (threaded, 64 bits, version 9.0.4)
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software.
Please run ?- license. for legal details.

For online help and background, visit https://www.swi-prolog.org
For built-in help, use ?- help(Topic). or ?- apropos(Word).

?- 階乗(5, _階乗値).
_階乗値 = 120.

?- 階乗(0, _階乗値).
_階乗値 = 1.
2025-04-06  「trealla-prolog install」
https://github.com/trealla-prolog/trealla
Trealla Prolog

$ git clone https://github.com/trealla-prolog/trealla.git

$ cd trealla

$ cd src

$ sudo apt install libreadline-dev libffi-dev libssl-dev xxd

$ make

インストールは、
$ ln -s $(pwd)/tpl ~/bin/tpl

ライブラリ読み込み指定
$ nano ~/.tplrc
ーーーーーーーーーーーーーーーーー
:-use_module(library(assoc)).
:-use_module(library(ordsets)).
ーーーーーーーーーーーーーーーーー

prolog真理表で使ったtruth_t3.plを修正する。
$ nano truth_t3.pl
...
pl_eval(~Phi, V) :-
        not(pl_eval(Phi, V)).   <<== \+ を not()に修正
...

実行。

$ tpl truth_t3.pl
?- pl_print_truth_table(((p => q) /\ p)  => q).
'Truth table for '=>(/\(=>(p,q),p),q)
p	q	formula
false	false	true
false	true	true
true	false	true
true	true	true
   true.
?- pl_print_truth_table((~p /\ (p \/ q)) => q).
'Truth table for '=>(/\(~(p),\/(p,q)),q)
p	q	formula
false	false	true
false	true	true
true	false	true
true	true	true
   true.
?- pl_print_truth_table( (p /\ (p \/ q)) => ~q).
'Truth table for '=>(/\(p,\/(p,q)),~(q))
p	q	formula
false	false	true
false	true	true
true	false	true
true	true	false
   true.
?- pl_print_truth_table( (p /\ ~(p <=> q)) => ~q).
'Truth table for '=>(/\(p,~(<=>(p,q))),~(q))
p	q	formula
false	false	true
false	true	true
true	false	true
true	true	true
   true.
?- pl_print_truth_table(((((p => q) => ( ~r => ~s)) => r) => u) => ((u => p) => (s => p))).
'Truth table for '=>(=>(=>(=>(=>(p,q),=>(~(r),~(s))),r),u),=>(=>(u,p),=>(s,p)))
p	q	r	s	u	formula
false	false	false	false	false	true
false	false	false	false	true	true
false	false	false	true	false	true
false	false	false	true	true	true
false	false	true	false	false	true
false	false	true	false	true	true
false	false	true	true	false	true
false	false	true	true	true	true
false	true	false	false	false	true
false	true	false	false	true	true
false	true	false	true	false	true
false	true	false	true	true	true
false	true	true	false	false	true
false	true	true	false	true	true
false	true	true	true	false	true
false	true	true	true	true	true
true	false	false	false	false	true
true	false	false	false	true	true
true	false	false	true	false	true
true	false	false	true	true	true
true	false	true	false	false	true
true	false	true	false	true	true
true	false	true	true	false	true
true	false	true	true	true	true
true	true	false	false	false	true
true	true	false	false	true	true
true	true	false	true	false	true
true	true	false	true	true	true
true	true	true	false	false	true
true	true	true	false	true	true
true	true	true	true	false	true
true	true	true	true	true	true
   true.
?- halt.
2025-04-03  「cu-prolog install」
第五世代コンピュータプロジェクト・アーカイブスにあるCU-PROLOGをやってみようとしたが、
ソースsyspred1.cが面倒なことになってしまったので、検索していたら以下のところにあったので
やってみた。

PROLOG文法はSWI-PROLOGとは違うところがあるのでSWI-PROGのスクリプトはそのままでは動かない。

https://az-prolog.com/natural-language-processing/nlu/
CU-Prologダウンロード

Original CU-Prologダウンロード
Download クリック で、cuprolog.zip ダウンロード。

第五世代コンピュータプロジェクト・アーカイブスにあるソースプログラムとは内容が違うの、パッチを
作ったこちらのほうを使う。

SOFNEC改修ファイルダウンロード
Download クリック で、cuprolog_sofnec_patch.zip ダウンロード。

$ mkdir CU-PROLOG
$ cd CU-PROLOG
$ mv ~/ダウンロード/cuprolog.zip .
  解凍する。

$ mv ~/ダウンロード/cuprolog_sofnec_patch.zip .
  解凍する。

$ cd cuprolog/src        # cu-prologのソースディレクトリ
$ chmod 666 *
$ patch -R < ../../cuprolog_sofnec_patch/cu64.patch
..
patching file funclist.h
Unreversed patch detected!  Ignore -R? [n] y
;;
;;
 全部パッチ 'y'

$ nano globalv.h
...
extern struct func *LIST,*CUNIFY;
extern struct term *NIL,  *FAIL, *END_OF_FILE;
extern struct term *Anonymous_var;
extern struct pair *Anonymous_env;
extern struct clause *MFAIL;
extern struct term *XF_P, *YF_P, *FX_P, *FY_P, *XFX_P, *XFY_P, *YFX_P;
extern struct term *S_GLOBAL_VAR, *S_VAR, *S_INTEGER, *S_FLOAT;
extern struct term *S_STRING, *S_FILE_POINTER, *S_PST, *S_CLAUSE;
extern struct term *S_LIST, *S_FUNCTOR, *S_ATOM, *S_PSTOBJ;
extern struct term *S_EQ, *S_GREATER, *S_LESS;
...
"extern "を追加。

$ nano include.h
...
#define RASPI
...追加

$ chmod +w main.c
$ nano main.c
...
void heap_realloc()		/* reallocate system/user heaps */
{
#if	defined(WIN64) || defined(RASPI)  <<==修正
    free((char *)sheap); SHEAP_SIZE=SHEAP_SIZE*1.2; system_heap_alloc();
#else
...
$ make

ワーニングが出る。includeファイル、関数プロトタイプを設定すればなくなる。とりあえずは無視。
英文構文解析 実行。

$ ./cup3 ../sample/hpsg.p
>>> open ../sample/hpsg.p 

	*******  cu - Prolog III  Ver. 3.1 (July 6, 1994)  *******
	[COPYRIGHT] Institute for New Generation Computer Technology (ICOT)
		Tokyo, Japan 1991-93
	Type '%h' for help.

	[Heap=1000K System_heap=2000K Env_heap=160K Cstr_heap=2000K
	 Ustack=100K Name_heap=50K]

 ****** end of file ******* 
CPU time = 0.000 sec (Constraints Handling = 0.000 sec)
_?-p([mary,meets,john]).

{head/verb, ph/[mary,meets,john], sc/[]}---1
 | 
 |--{head/verb, ph/[mary,meets], sc/[noun]}---2
 |   | 
 |   |--noun---[mary]
 |   | 
 |   |__verb---[meets]
 | 
 |__noun---[john]

category= {head/verb, ph/[mary,meets,john], sc/[]}
constraint= 
true.
CPU time = 0.000 sec (Constraints Handling = 0.000 sec)
_?-p([mary,is,nice]).

{head/verb, ph/[mary,is,nice], sc/[]}---2
 | 
 |--noun---[mary]
 | 
 |__{head/verb, ph/[is,nice], sc/[noun]}---1
     | 
     |--verb---[is]
     | 
     |__adjective---[nice]

category= {head/verb, ph/[mary,is,nice], sc/[]}
constraint= 
true.
CPU time = 0.000 sec (Constraints Handling = 0.000 sec)
_:-halt.

---- Quit cu-Prolog ? (y/n) ----y

'%Q'でプログラム終了

sample/jpsg.p は、日本語構文解析。
2025-04-14  「prolog論理学真理表」
https://www.sra.co.jp/public/sra/gsletter/
GSLetterNeo
 全然関係ないことで検索していて見つけてしまったことから始まる。

 ◎Vol.153 DX? アジャイル? イノベーション? ― 思考する力、想像する力 / 土屋正人
   この中にある↓
  
「思考の教室 ― じょうずに考えるレッスン」 戸田山和久著 NHK 出版 2020, 2023
  を読んで、おもしろいなあでやってみようかと始めた。

「論理学をつくる」 戸田山和久著 名古屋大学出版会 2000, 2014
  「思考の教室 」のつながりで。
他には。
「論証の教室 入門編」 倉田剛著 新曜社 2022
「思考の技術論」 鹿島茂著 平凡社
がある。

まずは論理学をプログラムするのは何かなとと思いつくのはPROLOG。
昔に、”第五世代コンピュータプロジェクト”でつかわれていたもの。
(https://www.airc.aist.go.jp/aitec-icot/ICOT/HomePage-J.html
「第五世代コンピュータプロジェクト・アーカイブスへようこそ!」)

SRA GSLetterNeo 「Vol.197 Pythonで始める論理プログラミング -SWI-Prolog編-」にあったもの
はRaspberry pi ではpython モジュールがみつからないのでとりあえずはswi-prologをインストールする。

$ sudo apt install swi-prolog

参考:
https://barrywatson.se/cl/cl_truth_table.html
Truth Table

論理学にはいつもついてまわる真理表を作るPROLOGがないかと検索して、何個か試したが上記の
「Truth Table」のスクリプトがよかったのでやってみた。これのPrologスクリプトのみをファイルにする。
python, c などとは違う演算子がある。

*** 基本 ***

?- pl_print_truth_table( p \/ q ).
'Truth table for 'p\/q
p	q	formula
false	false	false
false	true	true
true	false	true
true	true	true
true.

?- pl_print_truth_table( p /\ q ).
'Truth table for 'p/\q
p	q	formula
false	false	false
false	true	false
true	false	false
true	true	true
true.

?- pl_print_truth_table( p => q ). # →演算子
'Truth table for 'p=>q
p	q	formula
false	false	true
false	true	true
true	false	false
true	true	true
true.

?- pl_print_truth_table( p <=> q ). # ≡演算子
'Truth table for 'p<=>q
p	q	formula
false	false	true
false	true	false
true	false	false
true	true	true
true.

*********

例題は、「論理学をつくる」 戸田山和久著 名古屋大学出版会 2000, 2014 より
第Ⅰ部 第4章 4.2.7 妥当性、トートロジー性、論理的同値性の判定とタブロー 
練習問題23 (6)トートロジー チェック
よりもらった。?- 以降を1行入力する。

$ swipl truth_t3.pl

■(6)(a)
?- pl_print_truth_table(((p => q) /\ p)  => q).
'Truth table for '(p=>q)/\p=>q
p	q	formula
false	false	true
false	true	true
true	false	true
true	true	true
true.

■(6)(b)
?- pl_print_truth_table((~p /\ (p \/ q)) => q).
'Truth table for '~p/\(p\/q)=>q
p	q	formula
false	false	true
false	true	true
true	false	true
true	true	true
true.

■(6)(c)
?- pl_print_truth_table( (p /\ (p \/ q)) => ~q).
'Truth table for 'p/\(p\/q)=> ~q
p	q	formula
false	false	true
false	true	true
true	false	true
true	true	false
true.

■(6)(d)
?- pl_print_truth_table( (p /\ ~(p <=> q)) => ~q).
'Truth table for 'p/\ ~ (p<=>q)=> ~q
p	q	formula
false	false	true
false	true	true
true	false	true
true	true	true
true.

■(6)(e)
?- pl_print_truth_table(((((p => q) => ( ~r => ~s)) => r) => u) => ((u => p) => (s => p))).
'Truth table for '((((p=>q)=> ~r=> ~s)=>r)=>u)=>(u=>p)=>s=>p
p	q	r	s	u	formula
false	false	false	false	false	true
false	false	false	false	true	true
false	false	false	true	false	true
false	false	false	true	true	true
false	false	true	false	false	true
false	false	true	false	true	true
false	false	true	true	false	true
false	false	true	true	true	true
false	true	false	false	false	true
false	true	false	false	true	true
false	true	false	true	false	true
false	true	false	true	true	true
false	true	true	false	false	true
false	true	true	false	true	true
false	true	true	true	false	true
false	true	true	true	true	true
true	false	false	false	false	true
true	false	false	false	true	true
true	false	false	true	false	true
true	false	false	true	true	true
true	false	true	false	false	true
true	false	true	false	true	true
true	false	true	true	false	true
true	false	true	true	true	true
true	true	false	false	false	true
true	true	false	false	true	true
true	true	false	true	false	true
true	true	false	true	true	true
true	true	true	false	false	true
true	true	true	false	true	true
true	true	true	true	false	true
true	true	true	true	true	true
true.

◇◇トートロジー◇◇
参考:「数理論理学」 戸次大介著 東京大学出版会 2012
      より
 第一部 一階論理の統語論と意味論
  第3章 一階命題論理:統語論と意味論 
   から

◎排中律
?- pl_print_truth_table( p \/ ~p ).

◎矛盾律
?- pl_print_truth_table( ~(p /\ ~p) ).

◎結合律
?- pl_print_truth_table(( p /\ ( q /\ r)) <=> ((p /\ q ) /\ r) ).

?- pl_print_truth_table(( p \/ ( q \/ r)) <=> ((p \/ q ) \/ r) ).

◎交換律
?- pl_print_truth_table(( p \/  q) <=> ( q \/ p) ).

?- pl_print_truth_table(( p /\  q) <=> ( q /\ p) ).

◎吸収律
?- pl_print_truth_table(( p /\ (p \/ q)) <=> p ).

?- pl_print_truth_table(( p \/ (p /\ q)) <=> p ).

◎冪等律
?- pl_print_truth_table(( p \/ p ) <=> p ).

?- pl_print_truth_table(( p /\ p ) <=> p ).

◎縮小律
?- pl_print_truth_table(( p /\ q ) => p ).

?- pl_print_truth_table(( p /\ q ) => q ).

◎拡大律
?- pl_print_truth_table(p => ( p \/ q ) ).

?- pl_print_truth_table(q => ( p \/ q ) ).

◎分配律
?- pl_print_truth_table(( p \/ (q /\ x)) <=> ((p \/ q) /\ (p \/ x)) ).

?- pl_print_truth_table(( p /\ (q \/ x)) <=> ((p /\ q) \/ (p /\ x)) ).

◎同一律
?- pl_print_truth_table( p => p ).

◎推移律
?- pl_print_truth_table((( p => q ) /\ ( q => x)) => (p => x) ).

◎移入律
?- pl_print_truth_table(( p => q  => x) => (p => q => x) ).

◎移出律
?- pl_print_truth_table(( p /\ q  => x) => (p => q => x) ).

◎ドゥ・モルガンの法則
?- pl_print_truth_table( (~( p /\ q )) <=> (~p \/ ~q) ).

?- pl_print_truth_table( (~( p \/ q )) <=> (~p /\ ~q) ).

◎対偶律
?- pl_print_truth_table( ( p => q ) <=> (~q => ~p) ).

◎二重否定律
?- pl_print_truth_table( p  <=> ~(~p) ).

◎前件肯定式
?- pl_print_truth_table( p /\ (p => q) => q ).

◎選言的三段論法
?- pl_print_truth_table( ~p /\ (p \/ q) => q ).

◎構成的両刃論法
?- pl_print_truth_table( (p => x) => (q => x) => (p \/ q => x) ).

参考:
 記号論理学 藤川吉美著 大竹出版 1986,1995

?- pl_print_truth_table( p <=> p ).
?- pl_print_truth_table( ~(~p) <=> p ).
?- pl_print_truth_table( ~(~p) => p ).
?- pl_print_truth_table( (p => q ) /\ p => q).
?- pl_print_truth_table( (p <=> q ) <=> ( q <=> p )).
?- pl_print_truth_table( (p => q ) /\ ~q => ~p ).
?- pl_print_truth_table( (p => q ) /\ (p => ~q ) => ~p ).
?- pl_print_truth_table( (p <=> q ) /\ (q <=> r ) => ( p <=> r) ).
?- pl_print_truth_table( (p => (q => r) ) => (p /\ q => r ) ).
?- pl_print_truth_table( (p /\ q => r)  => (p => ( q => r )) ).
?- pl_print_truth_table( (p => q ) => (( q => r) => ( p => r )) ).
?- pl_print_truth_table( (p => ( q => r )) <=> ( q => ( p => r ) ) ).
?- pl_print_truth_table( (p => r ) /\ ( q => r) => ( p \/ q => r ) ).
?- pl_print_truth_table( p /\ (q \/ r ) <=> ( p /\ q ) \/ ( p /\ r ) ).
?- pl_print_truth_table( p \/ (q /\ r ) <=> ( p \/ q ) /\ ( p \/ r ) ).
?- pl_print_truth_table( p => ( q => p ) ).
?- pl_print_truth_table( ~(~p) => p \/ q ).
?- pl_print_truth_table( ~p => p => q ).
?- pl_print_truth_table( p => ( ~p => q ) ).
?- pl_print_truth_table( ( ~p => p ) => p ).
?- pl_print_truth_table( p \/ q <=> ~p => q ).
?- pl_print_truth_table( p => q <=> ~p \/ q ).
?- pl_print_truth_table( p => ( q => p /\ q ) ).
?- pl_print_truth_table( p /\ ( q \/ ~q ) <=> p ).
?- pl_print_truth_table( p \/ ( q /\ ~q ) <=> p ).
?- pl_print_truth_table( p => q <=> ~( p /\ ~q ) ).
?- pl_print_truth_table( (p <=> q) => ( p => q ) ).
?- pl_print_truth_table( (p <=> q) => ( q => p ) ).
?- pl_print_truth_table( p /\ q <=> ~( p => ~q ) ).
?- pl_print_truth_table( p /\ q <=> ~( ~p \/ ~q ) ).
?- pl_print_truth_table( p \/ q <=> ~( ~p /\ ~q ) ).
?- pl_print_truth_table( ( p => q ) <=> ( ~(~p) => q ) ).
?- pl_print_truth_table( p /\ ( q /\ ~q ) <=> q /\ ~q ).
?- pl_print_truth_table( p \/ ( q \/ ~q ) <=> q \/ ~q ).
?- pl_print_truth_table( ( p => q ) => ( p /\ r => q /\ r ) ).
?- pl_print_truth_table( ( p => q ) => ( p \/ r => q \/ r ) ).
?- pl_print_truth_table( ( p => ( q => r) ) <=> ( p /\ q => r ) ).
?- pl_print_truth_table( p => ( ( p /\ q => r ) => ( q => r ) ) ).
?- pl_print_truth_table( ( p <=> q ) <=> ( p => q ) /\ ( q => p ) ).
?- pl_print_truth_table( ( p => q ) /\ ( p /\ r ) => ( q /\ r ) ).
?- pl_print_truth_table( ( p => q ) /\ ( p \/ r ) => ( q \/ r ) ).
?- pl_print_truth_table( ( p /\ q => r ) => ( p /\ ~r => ~q ) ).
?- pl_print_truth_table( ( p /\ q => r ) => ( ~r /\ q => ~p ) ).
?- pl_print_truth_table( ( p /\ ~q => ~r ) => ( p /\ r => q ) ).
?- pl_print_truth_table( ( p => r ) => ( ( p => q ) => ( p => r) ) ).
?- pl_print_truth_table( ( p => q ) => ( ( q => p ) => ( p <=> q ) ) ).
?- pl_print_truth_table( ( p => r ) => ( ( q => r ) => ( p /\ q => r ) ) ).
?- pl_print_truth_table( ( p => r ) => ( ( q => r ) => ( p \/ q => r ) ) ).
?- pl_print_truth_table( ( p => ( q => r ) ) <=> ( ~( p => ~q ) => r ) ).
?- pl_print_truth_table( ( ~( p =>  q ) => r ) <=> ( p => ( ~q  => r ) ) ).
?- pl_print_truth_table( ( p =>  q ) => ( ( p => ( q  => r ) ) => ( p => r)) ).
?- pl_print_truth_table( ( ( p =>  q ) => r ) <=> ( ~p => r ) /\ ( q  => r ) ).
?- pl_print_truth_table( ( p =>  q ) /\ ( r /\ s ) => ( p /\ r => q /\ s ) ).
?- pl_print_truth_table( ( p =>  q ) => ( ( r => s ) => ( p /\ r => q /\ s ) ) ).
?- pl_print_truth_table( ( s =>  p ) => ( ( p /\ q => r) => ( s /\ q => r )) ).
?- pl_print_truth_table( ( p /\ q  => r ) => ( ( s => q ) => ( p /\ s => r ) ) ).
?- pl_print_truth_table( ( r /\ s ) => ( ( p /\ q => r ) => ( q /\ p => s ) ) ).

参照:
 現代論理学  末木、坂井、大出著  光文堂 1978

?- pl_print_truth_table( p => ( ~( ~ p )) ).
?- pl_print_truth_table( ~( p /\ ~p ) ).
?- pl_print_truth_table( ( ( p => q ) /\ p ) => q ).
?- pl_print_truth_table( ( ( p => q ) /\ ~q ) => ~p ).

参考:
 記号論理学の原理 H・ライヘンバッハ著 石本新訳 大修館書店 1982
   2.命題計算 8 可能な演算の外観、トートロジー

?- pl_print_truth_table( p \/ p <=> p ). 同一律
?- pl_print_truth_table( p /\ p <=> p ). 同一律
?- pl_print_truth_table( p => ~p <=> ~p ). 背理法
?- pl_print_truth_table( p /\ ( q \/ r) <=> p /\ q \/ p /\  r ). 第1分配法則
?- pl_print_truth_table( p \/  q /\ r <=> ( p \/ q ) /\ ( p \/ r ) ). 第2分配法則
?- pl_print_truth_table( (p \/ q) /\ (r \/ s) <=> p /\ r \/ q /\ r \/ p /\ s \/ q /\ s ). 二重分配法則
?- pl_print_truth_table( p/\ q \/ r /\ s <=> ( p \/ r ) /\ ( q \/ r ) /\ ( p \/ s ) /\ ( q \/ s ) ). 二重分配法則
?- pl_print_truth_table( ~( p /\ q ) <=> ~p \/ ~q ). 否定線の分解
?- pl_print_truth_table( ~( p \/ q ) <=> ~p /\ ~q ). 否定線の分解
?- pl_print_truth_table( p \/ q /\ ~q  <=> p ). 恒偽項の除去
?- pl_print_truth_table( p \/ ~p /\ q  <=> p \/ q ). 否定の吸収
?- pl_print_truth_table( p => q  <=> ~p \/ q ). 含意の消去
?- pl_print_truth_table( p => q  <=> ~q => ~p ). 対偶
?- pl_print_truth_table( (p => q) /\ (p => r) <=> p => q /\ r ). 含意統合
?- pl_print_truth_table( (p => r) /\ (q => r) <=> p \/ q => r ). 含意統合
?- pl_print_truth_table( (p => q) \/ (p => r) <=> p => q \/ r ). 含意統合
?- pl_print_truth_table( (p => r) \/ (q => r) <=> p /\ q => r ). 含意統合
?- pl_print_truth_table( (p <=> q) <=> p /\ q \/ ~p /\ ~q ). 同値の消去
?- pl_print_truth_table( ~(p <=> q) <=> ( p <=> ~q ) ). 同値の否定
?- pl_print_truth_table( (p <=> q) <=> ( ~p <=> ~q ) ). 同値な項の否定
?- pl_print_truth_table( p => p \/ q ). 項の追加
?- pl_print_truth_table( p /\ q => p ). 2つの前提からその1つへの含意
?- pl_print_truth_table( ~p => ( p => q ) ). 含意の追加
?- pl_print_truth_table( (p => q ) => ( p => q \/ r ) ). 結論の追加
?- pl_print_truth_table( (p => q ) => ( p /\ r => q ) ). 前提の追加
?- pl_print_truth_table( (p \/ r => q ) => ( p => q ) ). 前提の除去
?- pl_print_truth_table( (p => q /\ r ) => ( p => q ) ). 結論の除去
?- pl_print_truth_table( (p => q ) /\ ( r => s ) => ( p \/ r => q \/ s ) ). 統合された含意
?- pl_print_truth_table( (p => q ) /\ ( q => r ) => ( p => r ) ). 含意の推移性

参考:
「論理学をつくる」 戸田山和久著 名古屋大学出版会 2000, 2014

pl_print_truth_table( ( ~q /\ ( p => q ) ) => ~p). # 否定式
pl_print_truth_table( ( ( p /\ p ) => r ) => ( p => ( q => r))). # 移出律
pl_print_truth_table( ( ( p => r ) /\ ( q => r ) ) => ( ( p \/ q ) => r)). # 構成的両刀論法
pl_print_truth_table( ( ( p => q) => p ) => p ). # パースの法則
pl_print_truth_table( p => ( q => ( p /\ q ) ) ). # law of adjunction
pl_print_truth_table( ( p => q ) <=> ( ~p \/ q )).
pl_print_truth_table( ( p => q ) <=> ~( p /\ ~q)).
pl_print_truth_table( ( p => q ) => ( ( p => r ) => ( p => ( q /\ r ) ) ) ). # 合成律

蛇足。
■ P → Q は、 (〜p)V Q に等しい
?- pl_print_truth_table( (p => q) <=> ( (~p) \/ q)).
'Truth table for 'p=>q<=> ~p\/q
p	q	formula
false	false	true
false	true	true
true	false	true
true	true	true
true.

■ P ↔ Q は、 (p→Q)^(Q→P)に等しい
?- pl_print_truth_table( (p <=> q) <=> ( (p => q) /\ (q => p))).
'Truth table for '(p<=>q)<=>(p=>q)/\(q=>p)
p	q	formula
false	false	true
false	true	true
true	false	true
true	true	true
true.

■・・・論理演算子 優先順位・・・
              ③ ②  ①
?- pl_print_truth_table( p <=> q => p \/ q ).
'Truth table for 'p<=>q=>p\/q
p	q	formula
false	false	false
false	true	false
true	false	true
true	true	true
true.

?- pl_print_truth_table( p <=> (q => (p \/ q))).
'Truth table for 'p<=>q=>p\/q
p	q	formula
false	false	false
false	true	false
true	false	true
true	true	true
true.

              ③ ②  ①
?- pl_print_truth_table( p <=> q => p /\ q ).
'Truth table for 'p<=>q=>p/\q
p	q	formula
false	false	false
false	true	true
true	false	true
true	true	true
true.

?- pl_print_truth_table( p <=> (q => (p /\ q)) ).
'Truth table for 'p<=>q=>p/\q
p	q	formula
false	false	false
false	true	true
true	false	true
true	true	true
true.
2025-03-26 「Wii リモコン・ヌンチャク」
ニンテンドーWiiのリモコン、ヌンチャクがリサイクルショップで安いので触ってみた。
両方に加速度センサが入っている。
リモコンはBluetooth、ヌンチャクはI2Cで接続できる。

(1)Blutooth接続
参照:
https://www.raspberrypi-spy.co.uk/2013/02/nintendo-wii-remote-python-and-the-raspberry-pi/
Nintendo Wii Remote, Python and The Raspberry Pi

  接続方法は何種類かあるが確実につなげるpython3-cwiidでしてみる。
  wmguiプログラムも使える。

 $ sudo apt install python3-cwiid
 $ nano cwiid-remote.py
...
import time
import cwiid

print('ボタン①とボタン② か、電池ケース内のSYNCボタンを押してください。...')

while True:   # 2回め以降の接続がうまく行かないので再接続するため
    try:
        wii = cwiid.Wiimote()
        break
    except:
        print('接続失敗...')
        time.sleep(0.2)
else:
    exit(0)

time.sleep(0.1)

wii.rpt_mode = cwiid.RPT_BTN | cwiid.RPT_ACC | cwiid.RPT_NUNCHUK | cwiid.RPT_IR
# ボタン、加速度センサ、ヌンチャク、赤外線センサ 検出 設定

while True:
    if (wii.state['buttons'] - cwiid.BTN_PLUS - cwiid.BTN_MINUS == 0):
        print( '\nリモコン接続 (x)断')
        wii.rumble = 1
        time.sleep(0.2)
        wii.rumble = 0
        exit(0)
    print("---------")
    print(wii.state)
    time.sleep(1)
...
  実行
 
 +ボタンとーボタン 同時押しでプログラム終了。

  $ python cwiid-remote.py
...
ボタン①とボタン② か、電池ケース内のSYNCボタンを押してください。...
No wiimotes found
接続失敗...
No wiimotes found
接続失敗...
No wiimotes found
接続失敗...
 :::
---------
{'rpt_mode': 30, 'led': 0, 'rumble': 0, 'battery': 104, 'ext_type': 1, 'error': 0, 'buttons': 0, 'acc': (128, 128, 151), 'ir_src': [None, None, None, None], 'nunchuk': {'stick': (123, 128), 'acc': (172, 136, 105), 'buttons': 0}}
 :::                     *リモコン、ヌンチャクを傾けたり、キーを押すとbutton, accの値が変化する
---------
{'rpt_mode': 30, 'led': 0, 'rumble': 0, 'battery': 104, 'ext_type': 1, 'error': 0, 'buttons': 0, 'acc': (128, 125, 151), 'ir_src': [{'pos': (928, 590)}, {'pos': (835, 601)}, {'pos': (766, 713)}, None], 'nunchuk': {'stick': (123, 128), 'acc': (173, 136, 105), 'buttons': 0}}
 :::                     *赤外線リモコンをWIIリモコンIPセンサに向けてキーを押すと検出する
---------
{'rpt_mode': 30, 'led': 0, 'rumble': 0, 'battery': 90, 'ext_type': 0, 'error': 0, 'buttons': 0, 'acc': (138, 131, 150), 'ir_src': [None, None, None, None]}
 :::                     *ヌンチャクを抜くと'nunchuk':キーワードはなくなる
リモコン接続 (x)断
....

WII 赤外LED センサバーの場合

・通常カメラで見た
[wiibar-n.jpg]

・赤外カメラで見た
[wiibat-r.jpg]

..
{'rpt_mode': 30, 'led': 0, 'rumble': 0, 'battery': 77, 'ext_type': 0, 'error': 0, 'buttons': 4116, 'acc': (115, 118, 144), 'ir_src': [{'pos': (333, 407), 'size': 3}, {'pos': (649, 340), 'size': 3}, None, None]}
..
   2点が検出される。向きを変えると1個、なしとなる。

(2) I2C接続

参照:
https://htlab.net/electronics/game/wii-remote-extension-controller/
Wiiリモコン拡張コントローラープロトコル解析

https://github.com/rkrishnasanka/ArduinoNunchuk/blob/master/README.md
Arduino Nunchuk Library

[nunchukpins-0.jpeg]
  配線:
   nunchuck sca(data) ---- raspi GPIO-02
               scl(clock) ----       GPIO-03
               GND        ----       GND

 コネクタは、両面プリント基板に2.54mmピッチで3本 ■ ■ ■ 両面にスジを入れ各スジが接続していないようにして
 おいて、その端子にはんだ付けするなりしてコネクタの穴に差し込めば良い。スジの長さはコネクタの穴の深さで決まる。

  $ nano i2c-nunchuck.py
...
#!/usr/bin/env python

import smbus
import time

def get_id(bus0, address):
    time.sleep(0.1)
    bus0.write_byte(address, 0xFA)
    time.sleep(0.1)  # すぐだとデータが書き込めない
    print("識別子: ",end='')
    for _ in range(6):
         print("%02X " % (bus0.read_byte(address)),end='')
    print('\n  --    00 00 A4 20 00 00 : ヌンチャク')

def main():
    print("**** WII ヌンチャク接続 ****")
    bus = smbus.SMBus(1)
    address = 0x52
    get_id(bus, address)

    time.sleep(0.1)
    # === 最初    
    bus.write_byte(address,0xF0)
    print("暗号フラグ:",hex(bus.read_byte(address)))
    # === 0x55:暗号解除 それ以外は暗号化    
    time.sleep(0.1)
    print("<暗号化解除>")
    bus.write_byte_data(address, 0xF0, 0x55)   # 暗号化解除
    time.sleep(0.1)  # すぐだとデータが書き込めない

    # === 暗号化解除書き込み後    
    bus.write_byte(address,0xF0)
    print("暗号フラグ:",hex(bus.read_byte(address)))
    # === 0x55:暗号解除 それ以外は暗号化    
    get_id(bus, address)
    
    time.sleep(0.1)  # すぐだとデータが書き込めない
    while True:
        try:
            data = [0] * 6
            bus.write_byte(address,0x00)
            time.sleep(0.005)  # すぐだとデータが読み込めない
            for i in range(6):
                data[i] = bus.read_byte(address)
            #
            #  JOY stick , Acc X,y,Z and Button C,Z
            #    8 bits * 6 Bytes
            #   +========================================+
            # 0 | Joy X  7-0 bit                         |
            # 1 | Joy Y  7-0 bit                         |
            # 2 | Acc x  9-2 bit                         |
            # 3 | Acc y  9-2 bit                         |
            # 4 | Acc z  9-2 bit                         |
            # 5 | Az 1-0 | Ay 1-0 | Ax 1-0 | Cb 1 | Zb 1 |
            #   +========================================+ 
            #  x-axis, y-axis = 0 : 水平
            #  x-axis > 0 : ジョイスティック上向き
            #
            b = (data[5] & 0x03) ^ 3
            xaxis = data[2] << 2
            xaxis |= (data[5] >> 2) & 0x03
            yaxis = data[3] << 2
            yaxis |= (data[5] >> 4) & 0x03
            zaxis = data[4] << 2
            zaxis |= (data[5] >> 6) & 0x03
            print( "Analog X: %d" %(data[0]/2 - 62) )
            print( "Analog Y: %d" %(data[1]/2 - 64) )   
            print( "X-axis: %d" %(xaxis - 512))
            print( "Y-axis: %d" %(yaxis - 512))
            print( "Z-axis: %d" %(zaxis - 512))
            
            print( "Button: %s%s" % (" ZC"[b&2]," ZC"[b&1]))
            time.sleep(0.2)
        except KeyboardInterrupt:
            print("\x1b[2K")
            break    
        except IOError as e:
            print( e)
            print("")
            break    
        for _ in range(6):
            print("\x1b[1F\x1b[2K", end='')

if __name__ == '__main__':
    main()
...
  実行
 $ python i2c-nunchuck.py
...
**** WII ヌンチャク接続 ****
識別子: FF FF FF FF FF FF 
  --    00 00 A4 20 00 00 : ヌンチャク
暗号フラグ: 0xff
<暗号化解除>
暗号フラグ: 0x55
識別子: 00 00 A4 20 00 00 
  --    00 00 A4 20 00 00 : ヌンチャク
Analog X: 0
Analog Y: 0
X-axis: -20
Y-axis: 15
Z-axis: 194
Button:  Z
...
   一度実行後は電源オフにしない限り識別子は正しく読める。

 暗号化解除は、0xF0, 0x55 書き込みが確実であった。白、黒ヌンチャクとも。
 暗号復号は (8ビットデータ ^ 0x17) + 0x17。
2025-03-11 「NFT -> LOG -> ulogd2 -> mariadb(mysql) db」
NFTABLEのログをMARIADB(Mysql)データベースに書き込んでみた。
SQLITE3書き込みができているのを前提で。

(1) db インストール
$ sudo apt install -y  mariadb-server python3-mysqldb
$ sudo service mysql restart
$ sudo mysql_secure_installation
...
Enter current password for root (enter for none): <Enter>

Switch to unix_socket authentication [Y/n] y<Enter>

Change the root password? [Y/n] y<Enter>
New password: ルートパスワード<Enter>
Re-enter new password: ルートパスワード<Enter>

Remove anonymous users? [Y/n] y<Enter>

Disallow root login remotely? [Y/n] y<Enter>

Remove test database and access to it? [Y/n] y<Enter>

Reload privilege tables now? [Y/n] y<Enter>
...
  データベースの初期設定とルートパスワード設定。

$ nano tmysql.sh
----
#!/bin/bash
echo "MySql Install "

cat << 'EOF'| sudo mysql -u root -pルートパスワード
show variables like 'char%';
create user 'tuser'@'localhost' identified by 'tuserpp';
create database tdb;
grant all privileges on tdb.* to 'tuser'@'localhost';
quit
EOF
cat << 'EOF' | tee mysql.py
#!/usr/bin/python3
# -*- coding: utf-8 -*-
import MySQLdb
try:
    connect0 = MySQLdb.connect(
        host="localhost",
        port=3306,
        db='tdb',
        user='tuser',
        passwd='tuserpp',
        charset="utf8"
    )
    cursor = connect0.cursor()
    print("OK<br>")
except:
    print("NG<br>")

cursor.close()
connect0.close()
EOF
echo "----TEST Mysql----"
python ./mysql.py
---

MYSQLデータベースの動作テスト。

$ sh tmysql.sh
...
MySql Install 
Variable_name	Value
character_set_client	utf8mb3
character_set_connection	utf8mb3
character_set_database	utf8mb4
character_set_filesystem	binary
character_set_results	utf8mb3
character_set_server	utf8mb4
character_set_system	utf8mb3
character_sets_dir	/usr/share/mysql/charsets/
#!/usr/bin/python3
# -*- coding: utf-8 -*-
import MySQLdb
try:
    connect0 = MySQLdb.connect(
        host="localhost",
        port=3306,
        db='tdb',
        user='tuser',
        passwd='tuserpp',
        charset="utf8"
    )
    cursor = connect0.cursor()
    print("OK<br>")
except:
    print("NG<br>")

cursor.close()
connect0.close()
----TEST Mysql----
OK<br>
...
  mariadb(MYSQL)動作テストOK

ULOGD2用のデータベース ユーザ登録。

$ mysql -u root -p
Enter password: 
> create user 'mulogd'@'localhost' identified by 'パスワード';

> create database nulog;

> grant all privileges on nulog.* to 'mulogd'@'localhost';

> grant file on *.* to 'mulogd'@'localhost';

> flush privileges;
> quit
....

ULOGD2用テーブルの作成。

$ gzip -dc /usr/share/doc/ulogd2/mysql-ulogd2.sql.gz | mysql -D nulog -u mulogd -p
$ mysql -u mulogd -p nulog < sqlm.sql

$ nano sqlm.sql
..
drop table IF EXISTS t_ip_prot;

CREATE TABLE t_ip_prot (id  int unsigned, header_prot text );

insert into t_ip_prot values ( 0 ,"HOPOPT");
insert into t_ip_prot values ( 1 ,"ICMP");
insert into t_ip_prot values ( 2 ,"IGMP");
insert into t_ip_prot values ( 3 ,"GGP");
insert into t_ip_prot values ( 4 ,"IP-in-IP");
insert into t_ip_prot values ( 5 ,"ST");
insert into t_ip_prot values ( 6 ,"TCP");
insert into t_ip_prot values ( 7 ,"CBT");
insert into t_ip_prot values ( 8 ,"EGP");
insert into t_ip_prot values ( 9 ,"IGP");
insert into t_ip_prot values ( 10 ,"BBN-RCC-MON");
insert into t_ip_prot values ( 11 ,"NVP-II");
insert into t_ip_prot values ( 12 ,"PUP");
insert into t_ip_prot values ( 13 ,"ARGUS");
insert into t_ip_prot values ( 14 ,"EMCON");
insert into t_ip_prot values ( 15 ,"XNET");
insert into t_ip_prot values ( 16 ,"CHAOS");
insert into t_ip_prot values ( 17 ,"UDP");
insert into t_ip_prot values ( 18 ,"MUX");
insert into t_ip_prot values ( 19 ,"DCN-MEAS");
insert into t_ip_prot values ( 20 ,"HMP");
insert into t_ip_prot values ( 21 ,"PRM");
insert into t_ip_prot values ( 22 ,"XNS-IDP");
insert into t_ip_prot values ( 23 ,"TRUNK-1");
insert into t_ip_prot values ( 24 ,"TRUNK-2");
insert into t_ip_prot values ( 25 ,"LEAF-1");
insert into t_ip_prot values ( 26 ,"LEAF-2");
insert into t_ip_prot values ( 27 ,"RDP");
insert into t_ip_prot values ( 28 ,"IRTP");
insert into t_ip_prot values ( 29 ,"ISO-TP4");
insert into t_ip_prot values ( 30 ,"NETBLT");
insert into t_ip_prot values ( 31 ,"MFE-NSP");
insert into t_ip_prot values ( 32 ,"MERIT-INP");
insert into t_ip_prot values ( 33 ,"DCCP");
insert into t_ip_prot values ( 34 ,"3PC");
insert into t_ip_prot values ( 35 ,"IDPR");
insert into t_ip_prot values ( 36 ,"XTP");
insert into t_ip_prot values ( 37 ,"DDP");
insert into t_ip_prot values ( 38 ,"IDPR-CMTP");
insert into t_ip_prot values ( 39 ,"TP++");
insert into t_ip_prot values ( 40 ,"IL");
insert into t_ip_prot values ( 41 ,"IPv6");
insert into t_ip_prot values ( 42 ,"SDRP");
insert into t_ip_prot values ( 43 ,"IPv6-Route");
insert into t_ip_prot values ( 44 ,"IPv6-Frag");
insert into t_ip_prot values ( 45 ,"IDRP");
insert into t_ip_prot values ( 46 ,"RSVP");
insert into t_ip_prot values ( 47 ,"GRE");
insert into t_ip_prot values ( 48 ,"DSR");
insert into t_ip_prot values ( 49 ,"BNA");
insert into t_ip_prot values ( 50 ,"ESP");
insert into t_ip_prot values ( 51 ,"AH");
insert into t_ip_prot values ( 52 ,"I-NLSP");
insert into t_ip_prot values ( 53 ,"SwIPe");
insert into t_ip_prot values ( 54 ,"NARP");
insert into t_ip_prot values ( 55 ,"MOBILE");
insert into t_ip_prot values ( 56 ,"TLSP");
insert into t_ip_prot values ( 57 ,"SKIP");
insert into t_ip_prot values ( 58 ,"IPv6-ICMP");
insert into t_ip_prot values ( 59 ,"IPv6-NoNxt");
insert into t_ip_prot values ( 60 ,"IPv6-Opts");
insert into t_ip_prot values ( 61 ,"Any");
insert into t_ip_prot values ( 62 ,"CFTP");
insert into t_ip_prot values ( 63 ,"Any");
insert into t_ip_prot values ( 64 ,"SAT-EXPAK");
insert into t_ip_prot values ( 65 ,"KRYPTOLAN");
insert into t_ip_prot values ( 66 ,"RVD");
insert into t_ip_prot values ( 67 ,"IPPC");
insert into t_ip_prot values ( 68 ,"Any");
insert into t_ip_prot values ( 69 ,"SAT-MON");
insert into t_ip_prot values ( 70 ,"VISA");
insert into t_ip_prot values ( 71 ,"IPCU");
insert into t_ip_prot values ( 72 ,"CPNX");
insert into t_ip_prot values ( 73 ,"CPHB");
insert into t_ip_prot values ( 74 ,"WSN");
insert into t_ip_prot values ( 75 ,"PVP");
insert into t_ip_prot values ( 76 ,"BR-SAT-MON");
insert into t_ip_prot values ( 77 ,"SUN-ND");
insert into t_ip_prot values ( 78 ,"WB-MON");
insert into t_ip_prot values ( 79 ,"WB-EXPAK");
insert into t_ip_prot values ( 80 ,"ISO-IP");
insert into t_ip_prot values ( 81 ,"VMTP");
insert into t_ip_prot values ( 82 ,"SECURE-VMTP");
insert into t_ip_prot values ( 83 ,"VINES");
insert into t_ip_prot values ( 84 ,"IPTM");
insert into t_ip_prot values ( 85 ,"NSFNET-IGP");
insert into t_ip_prot values ( 86 ,"DGP");
insert into t_ip_prot values ( 87 ,"TCF");
insert into t_ip_prot values ( 88 ,"EIGRP");
insert into t_ip_prot values ( 89 ,"OSPF");
insert into t_ip_prot values ( 90 ,"Sprite-RPC");
insert into t_ip_prot values ( 91 ,"LARP");
insert into t_ip_prot values ( 92 ,"MTP");
insert into t_ip_prot values ( 93 ,"AX.25");
insert into t_ip_prot values ( 94 ,"OS");
insert into t_ip_prot values ( 95 ,"MICP");
insert into t_ip_prot values ( 96 ,"SCC-SP");
insert into t_ip_prot values ( 97 ,"ETHERIP");
insert into t_ip_prot values ( 98 ,"ENCAP");
insert into t_ip_prot values ( 99 ,"Any");
insert into t_ip_prot values ( 100 ,"GMTP");
insert into t_ip_prot values ( 101 ,"IFMP");
insert into t_ip_prot values ( 102 ,"PNNI");
insert into t_ip_prot values ( 103 ,"PIM");
insert into t_ip_prot values ( 104 ,"ARIS");
insert into t_ip_prot values ( 105 ,"SCPS");
insert into t_ip_prot values ( 106 ,"QNX");
insert into t_ip_prot values ( 107 ,"A/N");
insert into t_ip_prot values ( 108 ,"IPComp");
insert into t_ip_prot values ( 109 ,"SNP");
insert into t_ip_prot values ( 110 ,"Compaq-Peer");
insert into t_ip_prot values ( 111 ,"IPX-in-IP");
insert into t_ip_prot values ( 112 ,"VRRP");
insert into t_ip_prot values ( 113 ,"PGM");
insert into t_ip_prot values ( 114 ,"Any");
insert into t_ip_prot values ( 115 ,"L2TP");
insert into t_ip_prot values ( 116 ,"DDX");
insert into t_ip_prot values ( 117 ,"IATP");
insert into t_ip_prot values ( 118 ,"STP");
insert into t_ip_prot values ( 119 ,"SRP");
insert into t_ip_prot values ( 120 ,"UTI");
insert into t_ip_prot values ( 121 ,"SMP");
insert into t_ip_prot values ( 122 ,"SM");
insert into t_ip_prot values ( 123 ,"PTP");
insert into t_ip_prot values ( 124 ,"IS-IS");
insert into t_ip_prot values ( 125 ,"FIRE");
insert into t_ip_prot values ( 126 ,"CRTP");
insert into t_ip_prot values ( 127 ,"CRUDP");
insert into t_ip_prot values ( 128 ,"SSCOPMCE");
insert into t_ip_prot values ( 129 ,"IPLT");
insert into t_ip_prot values ( 130 ,"SPS");
insert into t_ip_prot values ( 131 ,"PIPE");
insert into t_ip_prot values ( 132 ,"SCTP");
insert into t_ip_prot values ( 133 ,"FC");
insert into t_ip_prot values ( 134 ,"RSVP-E2E-IGNORE");
insert into t_ip_prot values ( 135 ,"Mobility");
insert into t_ip_prot values ( 136 ,"UDPLite");
insert into t_ip_prot values ( 137 ,"MPLS-in-IP");
insert into t_ip_prot values ( 138 ,"manet");
insert into t_ip_prot values ( 139 ,"HIP");
insert into t_ip_prot values ( 140 ,"Shim6");
insert into t_ip_prot values ( 141 ,"WESP");
insert into t_ip_prot values ( 142 ,"ROHC");
insert into t_ip_prot values ( 143 ,"Ethernet");
insert into t_ip_prot values ( 144 ,"AGGFRAG");
insert into t_ip_prot values ( 145 ,"NSH");
insert into t_ip_prot values ( 146 ,"undefine");
insert into t_ip_prot values ( 147 ,"undefine");
insert into t_ip_prot values ( 148 ,"undefine");
insert into t_ip_prot values ( 149 ,"undefine");
insert into t_ip_prot values ( 150 ,"undefine");
insert into t_ip_prot values ( 151 ,"undefine");
insert into t_ip_prot values ( 152 ,"undefine");
insert into t_ip_prot values ( 153 ,"undefine");
insert into t_ip_prot values ( 154 ,"undefine");
insert into t_ip_prot values ( 155 ,"undefine");
insert into t_ip_prot values ( 156 ,"undefine");
insert into t_ip_prot values ( 157 ,"undefine");
insert into t_ip_prot values ( 158 ,"undefine");
insert into t_ip_prot values ( 159 ,"undefine");
insert into t_ip_prot values ( 160 ,"undefine");
insert into t_ip_prot values ( 161 ,"undefine");
insert into t_ip_prot values ( 162 ,"undefine");
insert into t_ip_prot values ( 163 ,"undefine");
insert into t_ip_prot values ( 164 ,"undefine");
insert into t_ip_prot values ( 165 ,"undefine");
insert into t_ip_prot values ( 166 ,"undefine");
insert into t_ip_prot values ( 167 ,"undefine");
insert into t_ip_prot values ( 168 ,"undefine");
insert into t_ip_prot values ( 169 ,"undefine");
insert into t_ip_prot values ( 170 ,"undefine");
insert into t_ip_prot values ( 171 ,"undefine");
insert into t_ip_prot values ( 172 ,"undefine");
insert into t_ip_prot values ( 173 ,"undefine");
insert into t_ip_prot values ( 174 ,"undefine");
insert into t_ip_prot values ( 175 ,"undefine");
insert into t_ip_prot values ( 176 ,"undefine");
insert into t_ip_prot values ( 177 ,"undefine");
insert into t_ip_prot values ( 178 ,"undefine");
insert into t_ip_prot values ( 179 ,"undefine");
insert into t_ip_prot values ( 180 ,"undefine");
insert into t_ip_prot values ( 181 ,"undefine");
insert into t_ip_prot values ( 182 ,"undefine");
insert into t_ip_prot values ( 183 ,"undefine");
insert into t_ip_prot values ( 184 ,"undefine");
insert into t_ip_prot values ( 185 ,"undefine");
insert into t_ip_prot values ( 186 ,"undefine");
insert into t_ip_prot values ( 187 ,"undefine");
insert into t_ip_prot values ( 188 ,"undefine");
insert into t_ip_prot values ( 189 ,"undefine");
insert into t_ip_prot values ( 190 ,"undefine");
insert into t_ip_prot values ( 191 ,"undefine");
insert into t_ip_prot values ( 192 ,"undefine");
insert into t_ip_prot values ( 193 ,"undefine");
insert into t_ip_prot values ( 194 ,"undefine");
insert into t_ip_prot values ( 195 ,"undefine");
insert into t_ip_prot values ( 196 ,"undefine");
insert into t_ip_prot values ( 197 ,"undefine");
insert into t_ip_prot values ( 198 ,"undefine");
insert into t_ip_prot values ( 199 ,"undefine");

drop table IF EXISTS t_oob_prot;

CREATE TABLE t_oob_prot (id  text, frame_format text );

insert into t_oob_prot values ( 2048 ,"Internet IP ( IPv4 )");
insert into t_oob_prot values ( 2054 ,"Address Resolution Protocol ( ARP )");
insert into t_oob_prot values ( 32821 ,"Reverse Address Resolution Protocol ( RARP )");
insert into t_oob_prot values ( 32859 ,"VMTP ( Versatile Message Transaction Protocol )");
insert into t_oob_prot values ( 32923 ,"AppleTalk ( EtherTalk )");
insert into t_oob_prot values ( 33011 ,"AppleTalk Address Resolution Porotocol ( AARP )");
insert into t_oob_prot values ( 33079 ,"IPX ( Novell Netware )");
insert into t_oob_prot values ( 33100 ,"SNMP over Ethernet");
insert into t_oob_prot values ( 33169 ,"NetBIOS/NetBEUI");
insert into t_oob_prot values ( 33149 ,"XTP");
insert into t_oob_prot values ( 34525 ,"IP version 6 ( IPv6 )");
insert into t_oob_prot values ( 34915 ,"PPPoE Discovery Stage");
insert into t_oob_prot values ( 34916 ,"PPPoE Session Stage");
insert into t_oob_prot values ( 36864 ,"Loopback ( Configuration Test Protocol )");

drop table IF EXISTS t_af_family;

CREATE TABLE t_af_family (id  text, af_family text );

insert into t_af_family values ( 0 ,"AF_UNSPEC");
insert into t_af_family values ( 1 ,"AF_UNIX");
insert into t_af_family values ( 2 ,"AF_INET");
insert into t_af_family values ( 3 ,"AF_AX25");
insert into t_af_family values ( 4 ,"AF_IPX");
insert into t_af_family values ( 5 ,"AF_APPLETALK");
insert into t_af_family values ( 6 ,"AF_NETROM");
insert into t_af_family values ( 7 ,"AF_BRIDGE");
insert into t_af_family values ( 8 ,"AF_ATMPVC");
insert into t_af_family values ( 9 ,"AF_X25");
insert into t_af_family values ( 10 ,"AF_INET6");
insert into t_af_family values ( 11 ,"AF_ROSE");
insert into t_af_family values ( 12 ,"AF_DECnet");
insert into t_af_family values ( 13 ,"AF_NETBEUI");
insert into t_af_family values ( 14 ,"AF_SECURITY");
insert into t_af_family values ( 15 ,"AF_KEY");
insert into t_af_family values ( 16 ,"AF_NETLINK");
insert into t_af_family values ( 17 ,"AF_PACKET");
insert into t_af_family values ( 18 ,"AF_ASH");
insert into t_af_family values ( 19 ,"AF_ECONET");
insert into t_af_family values ( 20 ,"AF_ATMSVC");
insert into t_af_family values ( 21 ,"AF_RDS");
insert into t_af_family values ( 22 ,"AF_SNA");
insert into t_af_family values ( 23 ,"AF_IRDA");
insert into t_af_family values ( 24 ,"AF_PPPOX");
insert into t_af_family values ( 25 ,"AF_WANPIPE");
insert into t_af_family values ( 26 ,"AF_LLC");
insert into t_af_family values ( 27 ,"AF_IB");
insert into t_af_family values ( 28 ,"AF_MPLS");
insert into t_af_family values ( 29 ,"AF_CAN");
insert into t_af_family values ( 30 ,"AF_TIPC");
insert into t_af_family values ( 31 ,"AF_BLUETOOTH");
insert into t_af_family values ( 32 ,"AF_IUCV");
insert into t_af_family values ( 33 ,"AF_RXRPC");
insert into t_af_family values ( 34 ,"AF_ISDN");
insert into t_af_family values ( 35 ,"AF_PHONET");
insert into t_af_family values ( 36 ,"AF_IEEE802154");
insert into t_af_family values ( 37 ,"AF_CAIF");
insert into t_af_family values ( 38 ,"AF_ALG");
insert into t_af_family values ( 39 ,"AF_NFC");
insert into t_af_family values ( 40 ,"AF_VSOCK");
insert into t_af_family values ( 41 ,"AF_KCM");
insert into t_af_family values ( 42 ,"AF_QIPCRTR");
insert into t_af_family values ( 43 ,"AF_SMC");
insert into t_af_family values ( 44 ,"AF_XDP");
insert into t_af_family values ( 45 ,"AF_MCTP");

drop table IF EXISTS t_icmpv6_typ;

CREATE TABLE t_icmpv6_typ (id  int unsigned, icmp_type6 text );

insert into t_icmpv6_typ values ( 1 ,"Destination Unreachable");
insert into t_icmpv6_typ values ( 2 ,"Packet too Big");
insert into t_icmpv6_typ values ( 3 ,"Time Exceeded");
insert into t_icmpv6_typ values ( 4 ,"Parameter Problem");
insert into t_icmpv6_typ values ( 128 ,"Echo Request");
insert into t_icmpv6_typ values ( 129 ,"Echo Reply");
insert into t_icmpv6_typ values ( 130 ,"Multicast Listener Query");
insert into t_icmpv6_typ values ( 131 ,"Multicast Listener Report");
insert into t_icmpv6_typ values ( 132 ,"Multicast Listener Done");
insert into t_icmpv6_typ values ( 133 ,"Router Solicitation");
insert into t_icmpv6_typ values ( 134 ,"Router Advertisement");
insert into t_icmpv6_typ values ( 135 ,"Neighbor Solicitation");
insert into t_icmpv6_typ values ( 136 ,"Neighbor Advertisement");
insert into t_icmpv6_typ values ( 137 ,"Redirect");
..
  DROP文以外はsqlite3用の内容と同じ。

IDの参照 項目名 テーブル作成。

$ mysql -u mulogd -p nulog < sqlm.sql

ULOGD2設定。

$ sudo nano /etc/ulogd.conf
...
[global]
logfile="syslog"
loglevel=3
plugin="/usr/lib/aarch64-linux-gnu/ulogd/ulogd_inppkt_NFLOG.so"
plugin="/usr/lib/aarch64-linux-gnu/ulogd/ulogd_inppkt_ULOG.so"
plugin="/usr/lib/aarch64-linux-gnu/ulogd/ulogd_inppkt_UNIXSOCK.so"
plugin="/usr/lib/aarch64-linux-gnu/ulogd/ulogd_inpflow_NFCT.so"
plugin="/usr/lib/aarch64-linux-gnu/ulogd/ulogd_filter_IFINDEX.so"
plugin="/usr/lib/aarch64-linux-gnu/ulogd/ulogd_filter_IP2STR.so"
plugin="/usr/lib/aarch64-linux-gnu/ulogd/ulogd_filter_IP2BIN.so"
plugin="/usr/lib/aarch64-linux-gnu/ulogd/ulogd_filter_IP2HBIN.so"
plugin="/usr/lib/aarch64-linux-gnu/ulogd/ulogd_filter_PRINTPKT.so"
plugin="/usr/lib/aarch64-linux-gnu/ulogd/ulogd_filter_HWHDR.so"
plugin="/usr/lib/aarch64-linux-gnu/ulogd/ulogd_filter_PRINTFLOW.so"
plugin="/usr/lib/aarch64-linux-gnu/ulogd/ulogd_filter_MARK.so"
plugin="/usr/lib/aarch64-linux-gnu/ulogd/ulogd_output_LOGEMU.so"
plugin="/usr/lib/aarch64-linux-gnu/ulogd/ulogd_output_SYSLOG.so"
plugin="/usr/lib/aarch64-linux-gnu/ulogd/ulogd_output_GPRINT.so"
plugin="/usr/lib/aarch64-linux-gnu/ulogd/ulogd_output_NACCT.so"
plugin="/usr/lib/aarch64-linux-gnu/ulogd/ulogd_output_MYSQL.so"
plugin="/usr/lib/aarch64-linux-gnu/ulogd/ulogd_raw2packet_BASE.so"
stack=log2:NFLOG,base1:BASE,ifi1:IFINDEX,ip2bin1:IP2BIN,mac2str1:HWHDR,mysql1:MYSQL

[log2]
group=1 # Group has to be different from the one use in log1

[mysql1]
db="nulog"
host="localhost"
user="mulogd"
table="ulog"
pass="mulogdpp"
procedure="INSERT_PACKET_FULL"
...
 上記の行がコメントになっていないこと。上の内容を修正・追加する。

ファイアーウォール設定。

$ nano nftables.sh
...
#!/bin/sh
echo "[NFTABLES.SH] **** start ****" > /dev/kmsg
# === initial ===
nft flush ruleset
# === ipv6 initial ===
nft add table ip6 filter6
nft add chain ip6 filter6 INPUT { type filter hook input priority 0 \; policy drop \; }
nft add chain ip6 filter6 FORWARD {  type filter hook forward priority 0 \; policy drop \; }
nft add chain ip6 filter6 OUTPUT {  type filter hook output priority 0 \; policy accept \; }
nft add chain ip6 filter6 POSTROUTING { type nat hook postrouting priority 100 \; policy drop \; }
nft add rule ip6 filter6 POSTROUTING log prefix \"[IPV6 POSTROUTE]\" group 1
nft add rule ip6 filter6 POSTROUTING drop
nft add rule ip6 filter6 FORWARD  log prefix \"[IPV6 FORWARD]\" group 1
nft add rule ip6 filter6 FORWARD drop
nft add rule ip6 filter6 INPUT log prefix \"[IPV6 INPUT]\" group 1
nft add rule ip6 filter6 INPUT drop
# === ipv4 initial ===
nft add table ip setwall
nft add chain ip setwall input { type filter hook input priority 0 \; policy drop \; }
nft add chain ip setwall forward {  type filter hook forward priority 0 \; policy drop \; }
nft add chain ip setwall output {  type filter hook output priority 0 \; policy accept \; }
nft add chain ip setwall callsub
# === ipv4 set input wall === 
nft add rule ip setwall input iifname lo accept
nft add rule ip setwall input iif eth0 ct state { established, related } accept
nft add rule ip setwall input iif wlan0 ct state { established, related } accept
nft add rule ip setwall input ct state invalid drop
# 
nft add rule ip setwall input ip saddr 192.168.0.0/16 tcp dport {22, 8080} jump callsub
nft add rule ip setwall input log prefix \"[DROP]\" group 1
# --- call sub
nft add rule ip setwall callsub log prefix \"[INPUT]\" group 1 accept
# ... END ...
...
 各チェーンごとにlogでパケットを確認する場合に入れる。
 行右端にあるgroup 2は、/etc/ulogd.confのstack=log2:NFLOG,base1:BASE,i.... で定義した[log2]に
 書いたgroupの数字と同じものを指定。番号があっていないとログはDBに入らない。

$ chmod +x nftables.sh
$ sudo ./nftables.sh
  ファイアーウォール設定

ULOGD2 再起動。

$ sudo systemctl restart ulogd
$ sudo systemctl status ulogd
 動作確認、エラーが出てないこと。

動作確認。
$ python -m http.server 8080

他のPCで。
$ curl http://192.168.x.xx:8080

Mysql検出結果表示。
$ nano sel2.sql
...
$ cat sel2.sql
SELECT " DateTime","prefix","in-if","mac_saddr","saddr","out-if","mac_daddr","daddr","af_family","udp_sport","udp_dport","header_prot","tcp_dport" UNION select from_unixtime(oob_time_sec) as DateTime,oob_prefix,oob_in,mac_saddr_str,INET6_NTOA(ip_saddr_bin) as saddr,oob_out,mac_daddr_str, INET6_NTOA(ip_daddr_bin)as daddr,t_af_family.af_family, udp_sport, udp_dport,t_ip_prot.header_prot,tcp_dport from ulog left outer join t_ip_prot on ulog.ip_protocol = t_ip_prot.id  left outer join t_af_family on ulog.oob_family = t_af_family.id  order by DateTime into outfile "/tmp/sample.csv" FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' ;
...
  1行で書く。
 最初のselect の" DateTime"の空白は日付数字よりコードが小さいことで入れた。order by DateTime の処理のため。
 into outfile "/tmp/sample.csv"は書き込みユーザがmysqlなので"/tmp"に書き込む。

mariadb(MYSQL)に書き込まれたデータの確認。

$ mysql -u mulogd -p nulog < sel2.sql

$ cp /tmp/sample.csv .
 UIDが自分になる
$ sudo rm /tmp/sample.csv
 ファイル削除
$ cat sample.csv
...
" DateTime","prefix","in-if","mac_saddr","saddr","out-if","mac_daddr","daddr","af_family","udp_sport","udp_dport","header_prot","tcp_dport"
"2025-03-10 22:49:07","[DROP]","eth0","xx:xx:xx:xx:5d:31","::ffff:192.168.1.xx","","xx:xx:xx:xx:00:fb","::ffff:224.0.0.251","AF_INET","5353","5353","UDP",\N
"2025-03-10 22:56:17","[INPUT]","eth0","xx:xx:xx:xx:44:a1","::ffff:192.168.1.x","","xx:xx:xx:xx:b6:5f","::ffff:192.168.1.x","AF_INET",\N,\N,"TCP","8080"
"2025-03-10 23:00:21","[DROP]","eth0","xx:xx:xx:xx:5d:31","::ffff:192.168.1.xx","","xx:xx:xx:xx:00:fb","::ffff:224.0.0.251","AF_INET","5353","5353","UDP",\N
...

参考:
https://stackoverflow.com/questions/13552206/grant-file-on-just-one-database
`GRANT FILE ON` just one database

https://dba.stackexchange.com/questions/17029/cannot-output-mysql-data-to-file
Cannot output MySQL data to file

https://forums.mysql.com/read.php?10,698113,698116#msg-698116
Re: Export table to csv with column headers
2025-02-27  「NFT -> LOG -> ulogd2 -> SQLITE3 db」
NFTABLEのログをSQLITE3データベースに書き込んでみた。

(1) db インストール
$ sudo apt install sqlite3
$ sudo apt install ulogd2 ulogd2-sqlite3
  ulogd2をインストールすると以下がインストールされる。

$ ls -l /usr/share/doc/ulogd2
合計 100
-rw-r--r-- 1 root root   106 11月  2  2022 AUTHORS
-rw-r--r-- 1 root root   388 12月 30  2022 NEWS.Debian.gz
-rw-r--r-- 1 root root  3387 11月  2  2022 README
-rw-r--r-- 1 root root  1304 12月 30  2022 README.Debian
-rw-r--r-- 1 root root   190 11月  2  2022 TODO
-rw-r--r-- 1 root root  1826 12月 30  2022 changelog.Debian.gz
-rw-r--r-- 1 root root  2757 12月 30  2022 copyright
drwxr-xr-x 2 root root  4096  2月 24 23:02 examples
-rw-r--r-- 1 root root  3399 11月  2  2022 mysql-ulogd2-flat.sql.gz
-rw-r--r-- 1 root root  6517 11月  2  2022 mysql-ulogd2.sql.gz
-rw-r--r-- 1 root root  2767 11月  2  2022 pgsql-ulogd2-flat.sql.gz
-rw-r--r-- 1 root root  5179 11月  2  2022 pgsql-ulogd2.sql.gz
-rw-r--r-- 1 root root   854 11月  2  2022 sqlite3.table
-rw-r--r-- 1 root root 25990 12月 30  2022 ulogd.html
-rw-r--r-- 1 root root  8790 12月 30  2022 ulogd.txt.gz
...

参照:
https://gist.github.com/AlexanderARodin/5adc9113a03642857ad2b459a7ecb825
AlexanderARodin/ulogd2-sqlite3.md

$ sudo cp /etc/ulogd.conf /etc/ulogd-org.conf
$ sudo nano /etc/ulogd.conf
...
[global]
logfile="syslog"
loglevel=3
plugin="/usr/lib/aarch64-linux-gnu/ulogd/ulogd_inppkt_NFLOG.so"
plugin="/usr/lib/aarch64-linux-gnu/ulogd/ulogd_inppkt_ULOG.so"
plugin="/usr/lib/aarch64-linux-gnu/ulogd/ulogd_inppkt_UNIXSOCK.so"
plugin="/usr/lib/aarch64-linux-gnu/ulogd/ulogd_inpflow_NFCT.so"
plugin="/usr/lib/aarch64-linux-gnu/ulogd/ulogd_filter_IFINDEX.so"
plugin="/usr/lib/aarch64-linux-gnu/ulogd/ulogd_filter_IP2STR.so"
plugin="/usr/lib/aarch64-linux-gnu/ulogd/ulogd_filter_IP2BIN.so"
plugin="/usr/lib/aarch64-linux-gnu/ulogd/ulogd_filter_IP2HBIN.so"
plugin="/usr/lib/aarch64-linux-gnu/ulogd/ulogd_filter_PRINTPKT.so"
plugin="/usr/lib/aarch64-linux-gnu/ulogd/ulogd_filter_HWHDR.so"
plugin="/usr/lib/aarch64-linux-gnu/ulogd/ulogd_filter_PRINTFLOW.so"
plugin="/usr/lib/aarch64-linux-gnu/ulogd/ulogd_filter_MARK.so"
plugin="/usr/lib/aarch64-linux-gnu/ulogd/ulogd_output_LOGEMU.so"
plugin="/usr/lib/aarch64-linux-gnu/ulogd/ulogd_output_SYSLOG.so"
plugin="/usr/lib/aarch64-linux-gnu/ulogd/ulogd_output_SQLITE3.so"
plugin="/usr/lib/aarch64-linux-gnu/ulogd/ulogd_output_GPRINT.so"
plugin="/usr/lib/aarch64-linux-gnu/ulogd/ulogd_output_NACCT.so"
plugin="/usr/lib/aarch64-linux-gnu/ulogd/ulogd_raw2packet_BASE.so"

stack=log3:NFLOG,base1:BASE,ifi1:IFINDEX,ip2str1:IP2STR,mac2str1:HWHDR,boot_sqlt:SQLITE3

[log3]
group=2 # Group has to be different from the one use in log1/log2
[boot_sqlt]
table="all_in"
db="/var/log/ulog/ulogd_sqlite3.db"
...
 上記の行がコメントになっていないこと。上の内容を修正・追加する。

$ cat ulogd.conf | sed -e "s/^#.*$//g" -e '/^ *$/d'

SQLITE3データベースの作成。

 列の項目がコードなので見やすくするためのコードの名前を表示するために紐付けるテーブルも作成。

$ nano sql3.sql
...
DROP TABLE all_in;

CREATE TABLE all_in (
  	oob_prefix		TEXT,
  	oob_time_sec		INT UNSIGNED,
  	oob_time_usec		INT UNSIGNED,
  	oob_uid			INT UNSIGNED,
        oob_protocol            TEXT,
        oob_family              TEXT,
  	ip_protocol		INT UNSIGNED,
  	ip_tos			INT UNSIGNED,
  	ip_ttl			INT UNSIGNED,
  	ip_totlen		INT UNSIGNED,
  	ip_ihl			INT UNSIGNED,
  	ip_csum			INT UNSIGNED,
  	ip_id			INT UNSIGNED,
  	ip_fragoff		INT UNSIGNED,
  	ip6_payloadlen		INT UNSIGNED,
  	ip6_priority		INT UNSIGNED,
  	ip6_flowlabel		INT UNSIGNED,
  	ip6_hoplimit		INT UNSIGNED,
  	ip6_nexthdr		INT UNSIGNED,
  	ip6_fragoff		INT UNSIGNED,
  	ip6_fragid		INT UNSIGNED,
  	tcp_sport		INT UNSIGNED,
  	tcp_dport		INT UNSIGNED,
  	tcp_seq			INT UNSIGNED,
  	tcp_ackseq		INT UNSIGNED,
  	tcp_window		INT UNSIGNED,
  	tcp_offset		INT UNSIGNED,
  	tcp_reserved		INT UNSIGNED,
  	tcp_urg			INT UNSIGNED,
  	tcp_urgp		INT UNSIGNED,
  	tcp_ack			INT UNSIGNED,
  	tcp_psh			INT UNSIGNED,
  	tcp_rst			INT UNSIGNED,
  	tcp_syn			INT UNSIGNED,
  	tcp_fin			INT UNSIGNED,
  	tcp_res1		INT UNSIGNED,
  	tcp_res2		INT UNSIGNED,
  	tcp_csum		INT UNSIGNED,
  	udp_sport		INT UNSIGNED,
  	udp_dport		INT UNSIGNED,
  	udp_len			INT UNSIGNED,
  	udp_csum		INT UNSIGNED,
  	icmp_type		INT UNSIGNED,
  	icmp_code		INT UNSIGNED,
  	icmp_echoid		INT UNSIGNED,
  	icmp_echoseq		INT UNSIGNED,
  	icmp_fragmtu		INT UNSIGNED,
  	icmp_csum		INT UNSIGNED,
  	icmpv6_type		INT UNSIGNED,
  	icmpv6_code		INT UNSIGNED,
  	icmpv6_echoid		INT UNSIGNED,
  	icmpv6_echoseq		INT UNSIGNED,
  	icmpv6_csum		INT UNSIGNED,
  	ahesp_spi		INT UNSIGNED,
  	arp_hwtype		INT UNSIGNED,
  	arp_protocoltype	INT UNSIGNED,
  	arp_operation		INT UNSIGNED,
  	sctp_sport		INT UNSIGNED,
  	sctp_dport		INT UNSIGNED,
  	sctp_csum		INT UNSIGNED,
  	oob_in			TEXT,
  	oob_out			TEXT,
  	mac_saddr_str		TEXT,
  	mac_daddr_str		TEXT,
  	ip_saddr_str		TEXT,
  	ip_daddr_str		TEXT,
  	orig_ip_saddr_str	TEXT,
  	orig_ip_daddr_str	TEXT,
  	reply_ip_saddr_str	TEXT,
  	reply_ip_daddr_str	TEXT,
  	arp_saddr_str		TEXT,
  	arp_daddr_str		TEXT,
	PRIMARY KEY ( oob_time_sec, oob_time_usec )
);

drop table t_ip_prot;

CREATE TABLE t_ip_prot (id  int unsigned, header_prot text );

insert into t_ip_prot values ( 0 ,"HOPOPT");
insert into t_ip_prot values ( 1 ,"ICMP");
insert into t_ip_prot values ( 2 ,"IGMP");
insert into t_ip_prot values ( 3 ,"GGP");
insert into t_ip_prot values ( 4 ,"IP-in-IP");
insert into t_ip_prot values ( 5 ,"ST");
insert into t_ip_prot values ( 6 ,"TCP");
insert into t_ip_prot values ( 7 ,"CBT");
insert into t_ip_prot values ( 8 ,"EGP");
insert into t_ip_prot values ( 9 ,"IGP");
insert into t_ip_prot values ( 10 ,"BBN-RCC-MON");
insert into t_ip_prot values ( 11 ,"NVP-II");
insert into t_ip_prot values ( 12 ,"PUP");
insert into t_ip_prot values ( 13 ,"ARGUS");
insert into t_ip_prot values ( 14 ,"EMCON");
insert into t_ip_prot values ( 15 ,"XNET");
insert into t_ip_prot values ( 16 ,"CHAOS");
insert into t_ip_prot values ( 17 ,"UDP");
insert into t_ip_prot values ( 18 ,"MUX");
insert into t_ip_prot values ( 19 ,"DCN-MEAS");
insert into t_ip_prot values ( 20 ,"HMP");
insert into t_ip_prot values ( 21 ,"PRM");
insert into t_ip_prot values ( 22 ,"XNS-IDP");
insert into t_ip_prot values ( 23 ,"TRUNK-1");
insert into t_ip_prot values ( 24 ,"TRUNK-2");
insert into t_ip_prot values ( 25 ,"LEAF-1");
insert into t_ip_prot values ( 26 ,"LEAF-2");
insert into t_ip_prot values ( 27 ,"RDP");
insert into t_ip_prot values ( 28 ,"IRTP");
insert into t_ip_prot values ( 29 ,"ISO-TP4");
insert into t_ip_prot values ( 30 ,"NETBLT");
insert into t_ip_prot values ( 31 ,"MFE-NSP");
insert into t_ip_prot values ( 32 ,"MERIT-INP");
insert into t_ip_prot values ( 33 ,"DCCP");
insert into t_ip_prot values ( 34 ,"3PC");
insert into t_ip_prot values ( 35 ,"IDPR");
insert into t_ip_prot values ( 36 ,"XTP");
insert into t_ip_prot values ( 37 ,"DDP");
insert into t_ip_prot values ( 38 ,"IDPR-CMTP");
insert into t_ip_prot values ( 39 ,"TP++");
insert into t_ip_prot values ( 40 ,"IL");
insert into t_ip_prot values ( 41 ,"IPv6");
insert into t_ip_prot values ( 42 ,"SDRP");
insert into t_ip_prot values ( 43 ,"IPv6-Route");
insert into t_ip_prot values ( 44 ,"IPv6-Frag");
insert into t_ip_prot values ( 45 ,"IDRP");
insert into t_ip_prot values ( 46 ,"RSVP");
insert into t_ip_prot values ( 47 ,"GRE");
insert into t_ip_prot values ( 48 ,"DSR");
insert into t_ip_prot values ( 49 ,"BNA");
insert into t_ip_prot values ( 50 ,"ESP");
insert into t_ip_prot values ( 51 ,"AH");
insert into t_ip_prot values ( 52 ,"I-NLSP");
insert into t_ip_prot values ( 53 ,"SwIPe");
insert into t_ip_prot values ( 54 ,"NARP");
insert into t_ip_prot values ( 55 ,"MOBILE");
insert into t_ip_prot values ( 56 ,"TLSP");
insert into t_ip_prot values ( 57 ,"SKIP");
insert into t_ip_prot values ( 58 ,"IPv6-ICMP");
insert into t_ip_prot values ( 59 ,"IPv6-NoNxt");
insert into t_ip_prot values ( 60 ,"IPv6-Opts");
insert into t_ip_prot values ( 61 ,"Any");
insert into t_ip_prot values ( 62 ,"CFTP");
insert into t_ip_prot values ( 63 ,"Any");
insert into t_ip_prot values ( 64 ,"SAT-EXPAK");
insert into t_ip_prot values ( 65 ,"KRYPTOLAN");
insert into t_ip_prot values ( 66 ,"RVD");
insert into t_ip_prot values ( 67 ,"IPPC");
insert into t_ip_prot values ( 68 ,"Any");
insert into t_ip_prot values ( 69 ,"SAT-MON");
insert into t_ip_prot values ( 70 ,"VISA");
insert into t_ip_prot values ( 71 ,"IPCU");
insert into t_ip_prot values ( 72 ,"CPNX");
insert into t_ip_prot values ( 73 ,"CPHB");
insert into t_ip_prot values ( 74 ,"WSN");
insert into t_ip_prot values ( 75 ,"PVP");
insert into t_ip_prot values ( 76 ,"BR-SAT-MON");
insert into t_ip_prot values ( 77 ,"SUN-ND");
insert into t_ip_prot values ( 78 ,"WB-MON");
insert into t_ip_prot values ( 79 ,"WB-EXPAK");
insert into t_ip_prot values ( 80 ,"ISO-IP");
insert into t_ip_prot values ( 81 ,"VMTP");
insert into t_ip_prot values ( 82 ,"SECURE-VMTP");
insert into t_ip_prot values ( 83 ,"VINES");
insert into t_ip_prot values ( 84 ,"IPTM");
insert into t_ip_prot values ( 85 ,"NSFNET-IGP");
insert into t_ip_prot values ( 86 ,"DGP");
insert into t_ip_prot values ( 87 ,"TCF");
insert into t_ip_prot values ( 88 ,"EIGRP");
insert into t_ip_prot values ( 89 ,"OSPF");
insert into t_ip_prot values ( 90 ,"Sprite-RPC");
insert into t_ip_prot values ( 91 ,"LARP");
insert into t_ip_prot values ( 92 ,"MTP");
insert into t_ip_prot values ( 93 ,"AX.25");
insert into t_ip_prot values ( 94 ,"OS");
insert into t_ip_prot values ( 95 ,"MICP");
insert into t_ip_prot values ( 96 ,"SCC-SP");
insert into t_ip_prot values ( 97 ,"ETHERIP");
insert into t_ip_prot values ( 98 ,"ENCAP");
insert into t_ip_prot values ( 99 ,"Any");
insert into t_ip_prot values ( 100 ,"GMTP");
insert into t_ip_prot values ( 101 ,"IFMP");
insert into t_ip_prot values ( 102 ,"PNNI");
insert into t_ip_prot values ( 103 ,"PIM");
insert into t_ip_prot values ( 104 ,"ARIS");
insert into t_ip_prot values ( 105 ,"SCPS");
insert into t_ip_prot values ( 106 ,"QNX");
insert into t_ip_prot values ( 107 ,"A/N");
insert into t_ip_prot values ( 108 ,"IPComp");
insert into t_ip_prot values ( 109 ,"SNP");
insert into t_ip_prot values ( 110 ,"Compaq-Peer");
insert into t_ip_prot values ( 111 ,"IPX-in-IP");
insert into t_ip_prot values ( 112 ,"VRRP");
insert into t_ip_prot values ( 113 ,"PGM");
insert into t_ip_prot values ( 114 ,"Any");
insert into t_ip_prot values ( 115 ,"L2TP");
insert into t_ip_prot values ( 116 ,"DDX");
insert into t_ip_prot values ( 117 ,"IATP");
insert into t_ip_prot values ( 118 ,"STP");
insert into t_ip_prot values ( 119 ,"SRP");
insert into t_ip_prot values ( 120 ,"UTI");
insert into t_ip_prot values ( 121 ,"SMP");
insert into t_ip_prot values ( 122 ,"SM");
insert into t_ip_prot values ( 123 ,"PTP");
insert into t_ip_prot values ( 124 ,"IS-IS");
insert into t_ip_prot values ( 125 ,"FIRE");
insert into t_ip_prot values ( 126 ,"CRTP");
insert into t_ip_prot values ( 127 ,"CRUDP");
insert into t_ip_prot values ( 128 ,"SSCOPMCE");
insert into t_ip_prot values ( 129 ,"IPLT");
insert into t_ip_prot values ( 130 ,"SPS");
insert into t_ip_prot values ( 131 ,"PIPE");
insert into t_ip_prot values ( 132 ,"SCTP");
insert into t_ip_prot values ( 133 ,"FC");
insert into t_ip_prot values ( 134 ,"RSVP-E2E-IGNORE");
insert into t_ip_prot values ( 135 ,"Mobility");
insert into t_ip_prot values ( 136 ,"UDPLite");
insert into t_ip_prot values ( 137 ,"MPLS-in-IP");
insert into t_ip_prot values ( 138 ,"manet");
insert into t_ip_prot values ( 139 ,"HIP");
insert into t_ip_prot values ( 140 ,"Shim6");
insert into t_ip_prot values ( 141 ,"WESP");
insert into t_ip_prot values ( 142 ,"ROHC");
insert into t_ip_prot values ( 143 ,"Ethernet");
insert into t_ip_prot values ( 144 ,"AGGFRAG");
insert into t_ip_prot values ( 145 ,"NSH");
insert into t_ip_prot values ( 146 ,"undefine");
insert into t_ip_prot values ( 147 ,"undefine");
insert into t_ip_prot values ( 148 ,"undefine");
insert into t_ip_prot values ( 149 ,"undefine");
insert into t_ip_prot values ( 150 ,"undefine");
insert into t_ip_prot values ( 151 ,"undefine");
insert into t_ip_prot values ( 152 ,"undefine");
insert into t_ip_prot values ( 153 ,"undefine");
insert into t_ip_prot values ( 154 ,"undefine");
insert into t_ip_prot values ( 155 ,"undefine");
insert into t_ip_prot values ( 156 ,"undefine");
insert into t_ip_prot values ( 157 ,"undefine");
insert into t_ip_prot values ( 158 ,"undefine");
insert into t_ip_prot values ( 159 ,"undefine");
insert into t_ip_prot values ( 160 ,"undefine");
insert into t_ip_prot values ( 161 ,"undefine");
insert into t_ip_prot values ( 162 ,"undefine");
insert into t_ip_prot values ( 163 ,"undefine");
insert into t_ip_prot values ( 164 ,"undefine");
insert into t_ip_prot values ( 165 ,"undefine");
insert into t_ip_prot values ( 166 ,"undefine");
insert into t_ip_prot values ( 167 ,"undefine");
insert into t_ip_prot values ( 168 ,"undefine");
insert into t_ip_prot values ( 169 ,"undefine");
insert into t_ip_prot values ( 170 ,"undefine");
insert into t_ip_prot values ( 171 ,"undefine");
insert into t_ip_prot values ( 172 ,"undefine");
insert into t_ip_prot values ( 173 ,"undefine");
insert into t_ip_prot values ( 174 ,"undefine");
insert into t_ip_prot values ( 175 ,"undefine");
insert into t_ip_prot values ( 176 ,"undefine");
insert into t_ip_prot values ( 177 ,"undefine");
insert into t_ip_prot values ( 178 ,"undefine");
insert into t_ip_prot values ( 179 ,"undefine");
insert into t_ip_prot values ( 180 ,"undefine");
insert into t_ip_prot values ( 181 ,"undefine");
insert into t_ip_prot values ( 182 ,"undefine");
insert into t_ip_prot values ( 183 ,"undefine");
insert into t_ip_prot values ( 184 ,"undefine");
insert into t_ip_prot values ( 185 ,"undefine");
insert into t_ip_prot values ( 186 ,"undefine");
insert into t_ip_prot values ( 187 ,"undefine");
insert into t_ip_prot values ( 188 ,"undefine");
insert into t_ip_prot values ( 189 ,"undefine");
insert into t_ip_prot values ( 190 ,"undefine");
insert into t_ip_prot values ( 191 ,"undefine");
insert into t_ip_prot values ( 192 ,"undefine");
insert into t_ip_prot values ( 193 ,"undefine");
insert into t_ip_prot values ( 194 ,"undefine");
insert into t_ip_prot values ( 195 ,"undefine");
insert into t_ip_prot values ( 196 ,"undefine");
insert into t_ip_prot values ( 197 ,"undefine");
insert into t_ip_prot values ( 198 ,"undefine");
insert into t_ip_prot values ( 199 ,"undefine");

drop table t_oob_prot;

CREATE TABLE t_oob_prot (id  text, frame_format text );

insert into t_oob_prot values ( 2048 ,"Internet IP ( IPv4 )");
insert into t_oob_prot values ( 2054 ,"Address Resolution Protocol ( ARP )");
insert into t_oob_prot values ( 32821 ,"Reverse Address Resolution Protocol ( RARP )");
insert into t_oob_prot values ( 32859 ,"VMTP ( Versatile Message Transaction Protocol )");
insert into t_oob_prot values ( 32923 ,"AppleTalk ( EtherTalk )");
insert into t_oob_prot values ( 33011 ,"AppleTalk Address Resolution Porotocol ( AARP )");
insert into t_oob_prot values ( 33079 ,"IPX ( Novell Netware )");
insert into t_oob_prot values ( 33100 ,"SNMP over Ethernet");
insert into t_oob_prot values ( 33169 ,"NetBIOS/NetBEUI");
insert into t_oob_prot values ( 33149 ,"XTP");
insert into t_oob_prot values ( 34525 ,"IP version 6 ( IPv6 )");
insert into t_oob_prot values ( 34915 ,"PPPoE Discovery Stage");
insert into t_oob_prot values ( 34916 ,"PPPoE Session Stage");
insert into t_oob_prot values ( 36864 ,"Loopback ( Configuration Test Protocol )");

drop table t_af_family;

CREATE TABLE t_af_family (id  text, af_family text );

insert into t_af_family values ( 0 ,"AF_UNSPEC");
insert into t_af_family values ( 1 ,"AF_UNIX");
insert into t_af_family values ( 2 ,"AF_INET");
insert into t_af_family values ( 3 ,"AF_AX25");
insert into t_af_family values ( 4 ,"AF_IPX");
insert into t_af_family values ( 5 ,"AF_APPLETALK");
insert into t_af_family values ( 6 ,"AF_NETROM");
insert into t_af_family values ( 7 ,"AF_BRIDGE");
insert into t_af_family values ( 8 ,"AF_ATMPVC");
insert into t_af_family values ( 9 ,"AF_X25");
insert into t_af_family values ( 10 ,"AF_INET6");
insert into t_af_family values ( 11 ,"AF_ROSE");
insert into t_af_family values ( 12 ,"AF_DECnet");
insert into t_af_family values ( 13 ,"AF_NETBEUI");
insert into t_af_family values ( 14 ,"AF_SECURITY");
insert into t_af_family values ( 15 ,"AF_KEY");
insert into t_af_family values ( 16 ,"AF_NETLINK");
insert into t_af_family values ( 17 ,"AF_PACKET");
insert into t_af_family values ( 18 ,"AF_ASH");
insert into t_af_family values ( 19 ,"AF_ECONET");
insert into t_af_family values ( 20 ,"AF_ATMSVC");
insert into t_af_family values ( 21 ,"AF_RDS");
insert into t_af_family values ( 22 ,"AF_SNA");
insert into t_af_family values ( 23 ,"AF_IRDA");
insert into t_af_family values ( 24 ,"AF_PPPOX");
insert into t_af_family values ( 25 ,"AF_WANPIPE");
insert into t_af_family values ( 26 ,"AF_LLC");
insert into t_af_family values ( 27 ,"AF_IB");
insert into t_af_family values ( 28 ,"AF_MPLS");
insert into t_af_family values ( 29 ,"AF_CAN");
insert into t_af_family values ( 30 ,"AF_TIPC");
insert into t_af_family values ( 31 ,"AF_BLUETOOTH");
insert into t_af_family values ( 32 ,"AF_IUCV");
insert into t_af_family values ( 33 ,"AF_RXRPC");
insert into t_af_family values ( 34 ,"AF_ISDN");
insert into t_af_family values ( 35 ,"AF_PHONET");
insert into t_af_family values ( 36 ,"AF_IEEE802154");
insert into t_af_family values ( 37 ,"AF_CAIF");
insert into t_af_family values ( 38 ,"AF_ALG");
insert into t_af_family values ( 39 ,"AF_NFC");
insert into t_af_family values ( 40 ,"AF_VSOCK");
insert into t_af_family values ( 41 ,"AF_KCM");
insert into t_af_family values ( 42 ,"AF_QIPCRTR");
insert into t_af_family values ( 43 ,"AF_SMC");
insert into t_af_family values ( 44 ,"AF_XDP");
insert into t_af_family values ( 45 ,"AF_MCTP");

drop table t_icmpv6_typ;

CREATE TABLE t_icmpv6_typ (id  int unsigned, icmp_type6 text );

insert into t_icmpv6_typ values ( 1 ,"Destination Unreachable");
insert into t_icmpv6_typ values ( 2 ,"Packet too Big");
insert into t_icmpv6_typ values ( 3 ,"Time Exceeded");
insert into t_icmpv6_typ values ( 4 ,"Parameter Problem");
insert into t_icmpv6_typ values ( 128 ,"Echo Request");
insert into t_icmpv6_typ values ( 129 ,"Echo Reply");
insert into t_icmpv6_typ values ( 130 ,"Multicast Listener Query");
insert into t_icmpv6_typ values ( 131 ,"Multicast Listener Report");
insert into t_icmpv6_typ values ( 132 ,"Multicast Listener Done");
insert into t_icmpv6_typ values ( 133 ,"Router Solicitation");
insert into t_icmpv6_typ values ( 134 ,"Router Advertisement");
insert into t_icmpv6_typ values ( 135 ,"Neighbor Solicitation");
insert into t_icmpv6_typ values ( 136 ,"Neighbor Advertisement");
insert into t_icmpv6_typ values ( 137 ,"Redirect");
...
$ sudo sqlite3 /var/log/ulog/ulogd_sqlite3.db < sql3.sql
 データベースは、ulogd.conf 「db="/var/log/ulog/ulogd_sqlite3.db"」で設定したもの。

$ sqlite3 /var/log/ulog/ulogd_sqlite3.db

all_in        t_af_family   t_icmpv6_typ  t_ip_prot     t_oob_prot  
sqlite> .q
...
$ sudo systemctl restart ulogd2
$ sudo systemctl status ulogd2
  確認
$ nano attach-ulogd.sh
...
#!/bin/sh
n=0
while [ $n -le 10 ]
do
    sleep 1
    ULOGD=`systemctl status ulogd | grep 'error'`
    if [ "$ULOGD" = "" ]; then
        echo "attached ulogd2"
        break
    fi
    systemctl restart ulogd
    n=`expr $n + 1`
done
if [ "$ULOGD" != "" ]; then
    echo "ULOGD2 ??? Error"
fi
...
$ sudo chmod +x /etc/raspi/attach-ulogd.sh

rc.local追加
  --- /etc/rc.local ---
  #!/bin/sh -e
  /home/pi/nftables.sh
  /home/pi/attach-ulogd.sh &
  exit 0
  ----
  追加する。
 ブート時、ulogd2が正常に動作しているかを確認・再起動をするもの。

$ nano nftables.sh
...
#!/bin/sh
echo "[NFTABLES.SH] **** start ****" > /dev/kmsg
# === initial ===
nft flush ruleset
# === ipv6 initial ===
nft add table ip6 filter6
nft add chain ip6 filter6 INPUT { type filter hook input priority 0 \; policy drop \; }
nft add chain ip6 filter6 FORWARD {  type filter hook forward priority 0 \; policy drop \; }
nft add chain ip6 filter6 OUTPUT {  type filter hook output priority 0 \; policy accept \; }
nft add chain ip6 filter6 POSTROUTING { type nat hook postrouting priority 100 \; policy drop \; }
nft add rule ip6 filter6 POSTROUTING log prefix \"[IPV6 POSTROUTE]\" group 2
nft add rule ip6 filter6 POSTROUTING drop
nft add rule ip6 filter6 FORWARD  log prefix \"[IPV6 FORWARD]\" group 2
nft add rule ip6 filter6 FORWARD drop
nft add rule ip6 filter6 INPUT log prefix \"[IPV6 INPUT]\" group 2
nft add rule ip6 filter6 INPUT drop
# === ipv4 initial ===
nft add table ip setwall
nft add chain ip setwall input { type filter hook input priority 0 \; policy drop \; }
nft add chain ip setwall forward {  type filter hook forward priority 0 \; policy drop \; }
nft add chain ip setwall output {  type filter hook output priority 0 \; policy accept \; }
nft add chain ip setwall callsub
# === ipv4 set input wall === 
nft add rule ip setwall input iifname lo accept
nft add rule ip setwall input iif eth0 ct state { established, related } accept
nft add rule ip setwall input iif wlan0 ct state { established, related } accept
nft add rule ip setwall input ct state invalid drop
# 
nft add rule ip setwall input ip saddr 192.168.0.0/16 tcp dport {22, 8080} jump callsub
nft add rule ip setwall input log prefix \"[DROP]\" group 2
# --- call sub
nft add rule ip setwall callsub log prefix \"[INPUT]\" group 2 accept
# ... END ...
...
 各チェーンごとにlogでパケットを確認する場合に入れる。
 行右端にあるgroup 2は、/etc/ulogd.confのstack=log3:NFLOG,base1:BASE,i.... で定義した[log3]に
 書いたgroup=2の数字と同じものを指定。番号があっていないとログはDBに入らない。

$ chmod +x nftables.sh
$ sudo ./nftables.sh
  ファイアーウォール設定

データベースを確認するためのPYTHONプログラム。

$ nano dblite.py
...
#!/usr/bin/python
# (c) K.Shimomura (The MIT License)
import datetime
import sqlite3
import sys
import warnings
import ip_socket_inf

# データベース パス
ip_dbname = "/var/log/ulog/ulogd_sqlite3.db"
# socket 情報格納テーブル名
ip_table = "all_in"

def main():
    argv = sys.argv
    if len(argv) < 2:
        day_time = '2025-02-20 00:00:00'
    else:
        day_time = argv[1]
    warnings.filterwarnings('ignore')
    #f = open(sys.stdout, "w", "utf-8")

    connect0 = sqlite3.connect(
        ip_dbname
    )
    cursor = connect0.cursor()
    ncolm = []
    #cursor.execute("SELECT name FROM PRAGMA_TABLE_INFO('" + ip_table + "')")
    #result = cursor.fetchall()
    #for row in result:
    #    ncolm.append(row)
    #print(ncolm)
    #day_time = '2025-02-24 01:00:00'
    #cursor.execute("select * from " + ip_table + " where datetime(oob_time_sec + 32400, 'unixepoch') > '" + day_time + "';")
    cursor.execute("select oob_time_sec as date,oob_prefix, oob_protocol,ip_protocol,tcp_sport,tcp_dport,udp_sport,udp_dport,oob_in,oob_out,ip_saddr_str,ip_daddr_str  from " + ip_table + " where datetime(oob_time_sec + 32400, 'unixepoch') > '" + day_time + "';")
    desc = cursor.description
    result = cursor.fetchall()
    for row in result:
        for n,i in enumerate(row):
            if i != None:
                if desc[n][0] == 'ip_protocol' and i < 200:
                    print("%s : %s / %s" % (desc[n][0] ,i,ip_socket_inf.ip_prot_t[i]))
                elif desc[n][0] == 'icmpv6_type':
                    print("%s : %s / %s" % (desc[n][0] ,i,icmpv6_type[i]))
                elif desc[n][0] == 'oob_family' and int(i) in ip_socket_inf.af_family:
                    print("%s : %s / %s" % (desc[n][0] ,i,ip_socket_inf.af_family[int(i)]))
                elif desc[n][0] == 'date' or desc[n][0] == 'oob_time_sec':
                    print("%s : %s" % (desc[n][0] ,datetime.datetime.fromtimestamp(i)))
                elif desc[n][0] == 'oob_protocol' and int(i) in ip_socket_inf.oob_prot_t:
                    print("%s : %s / %s" % (desc[n][0] ,i,ip_socket_inf.oob_prot_t[int(i)]))
                elif desc[n][0] == 'oob_time_usec':
                    pass
                else:
                    print("%s : %s" % (desc[n][0] ,i))
        print('----------')
    cursor.close()
    connect0.close()

if __name__ == "__main__":
    main()
...
$ nano ip_socket_inf.py
...
# ip_socket_inf.py
# (c) K.Shimomura (The MIT License)
'''
  ipプロトコル、icmpv6タイプ、インターネットファミリ、イーサネットフォーマット 名称変換テーブル

  (1) ip v4, ipv6 ヘッダー IPプロトコル
  (2) icmpv6 タイプ
  (3) socket インターネットファミリ
  (4) ethernet フレームフォーマット
'''
# ip v4, ipv6 ヘッダー IPプロトコル
ip_prot_t = ['HOPOPT', 'ICMP', 'IGMP', 'GGP', 'IP-in-IP', 'ST', 'TCP', 'CBT', 'EGP', 'IGP', 'BBN-RCC-MON', 'NVP-II', 'PUP', 'ARGUS', 'EMCON', 'XNET', 'CHAOS', 'UDP', 'MUX', 'DCN-MEAS', 'HMP', 'PRM', 'XNS-IDP', 'TRUNK-1', 'TRUNK-2', 'LEAF-1', 'LEAF-2', 'RDP', 'IRTP', 'ISO-TP4', 'NETBLT', 'MFE-NSP', 'MERIT-INP', 'DCCP', '3PC', 'IDPR', 'XTP', 'DDP', 'IDPR-CMTP', 'TP++', 'IL', 'IPv6', 'SDRP', 'IPv6-Route', 'IPv6-Frag', 'IDRP', 'RSVP', 'GRE', 'DSR', 'BNA', 'ESP', 'AH', 'I-NLSP', 'SwIPe', 'NARP', 'MOBILE', 'TLSP', 'SKIP', 'IPv6-ICMP', 'IPv6-NoNxt', 'IPv6-Opts', 'Any', 'CFTP', 'Any', 'SAT-EXPAK', 'KRYPTOLAN', 'RVD', 'IPPC', 'Any', 'SAT-MON', 'VISA', 'IPCU', 'CPNX', 'CPHB', 'WSN', 'PVP', 'BR-SAT-MON', 'SUN-ND', 'WB-MON', 'WB-EXPAK', 'ISO-IP', 'VMTP', 'SECURE-VMTP', 'VINES', 'IPTM', 'NSFNET-IGP', 'DGP', 'TCF', 'EIGRP', 'OSPF', 'Sprite-RPC', 'LARP', 'MTP', 'AX.25', 'OS', 'MICP', 'SCC-SP', 'ETHERIP', 'ENCAP', 'Any', 'GMTP', 'IFMP', 'PNNI', 'PIM', 'ARIS', 'SCPS', 'QNX', 'A/N', 'IPComp', 'SNP', 'Compaq-Peer', 'IPX-in-IP', 'VRRP', 'PGM', 'Any', 'L2TP', 'DDX', 'IATP', 'STP', 'SRP', 'UTI', 'SMP', 'SM', 'PTP', 'IS-IS', 'FIRE', 'CRTP', 'CRUDP', 'SSCOPMCE', 'IPLT', 'SPS', 'PIPE', 'SCTP', 'FC', 'RSVP-E2E-IGNORE', 'Mobility', 'UDPLite', 'MPLS-in-IP', 'manet', 'HIP', 'Shim6', 'WESP', 'ROHC', 'Ethernet', 'AGGFRAG', 'NSH', 'undefine', 'undefine', 'undefine', 'undefine', 'undefine', 'undefine', 'undefine', 'undefine', 'undefine', 'undefine', 'undefine', 'undefine', 'undefine', 'undefine', 'undefine', 'undefine', 'undefine', 'undefine', 'undefine', 'undefine', 'undefine', 'undefine', 'undefine', 'undefine', 'undefine', 'undefine', 'undefine', 'undefine', 'undefine', 'undefine', 'undefine', 'undefine', 'undefine', 'undefine', 'undefine', 'undefine', 'undefine', 'undefine', 'undefine', 'undefine', 'undefine', 'undefine', 'undefine', 'undefine', 'undefine', 'undefine', 'undefine', 'undefine', 'undefine', 'undefine', 'undefine', 'undefine', 'undefine', 'undefine']

# icmpv6 タイプ
icmpv6_type = {1:"Destination Unreachable",
2:"Packet too Big",
3:"Time Exceeded",
4:"Parameter Problem",
128:"Echo Request",
129:"Echo Reply",
130:"Multicast Listener Query",
131:"Multicast Listener Report",
132:"Multicast Listener Done",
133:"Router Solicitation",
134:"Router Advertisement",
135:"Neighbor Solicitation",
136:"Neighbor Advertisement",
137:"Redirect" }

# socket インターネットファミリ
af_family = {
0:"AF_UNSPEC",
1:"AF_UNIX",
2:"AF_INET",
3:"AF_AX25",
4:"AF_IPX",
5:"AF_APPLETALK",
6:"AF_NETROM",
7:"AF_BRIDGE",
8:"AF_ATMPVC",
9:"AF_X25",
10:"AF_INET6",
11:"AF_ROSE",
12:"AF_DECnet",
13:"AF_NETBEUI",
14:"AF_SECURITY",
15:"AF_KEY",
16:"AF_NETLINK",
17:"AF_PACKET",
18:"AF_ASH",
19:"AF_ECONET",
20:"AF_ATMSVC",
21:"AF_RDS",
22:"AF_SNA",
23:"AF_IRDA",
24:"AF_PPPOX",
25:"AF_WANPIPE",
26:"AF_LLC",
27:"AF_IB",
28:"AF_MPLS",
29:"AF_CAN",
30:"AF_TIPC",
31:"AF_BLUETOOTH",
32:"AF_IUCV",
33:"AF_RXRPC",
34:"AF_ISDN",
35:"AF_PHONET",
36:"AF_IEEE802154",
37:"AF_CAIF",
38:"AF_ALG",
39:"AF_NFC",
40:"AF_VSOCK",
41:"AF_KCM",
42:"AF_QIPCRTR",
43:"AF_SMC",
44:"AF_XDP",
45:"AF_MCTP" }

# ethernet フレームフォーマット
oob_prot_t = {
2048:"Internet IP ( IPv4 )",
2054:"Address Resolution Protocol ( ARP )",
32821:"Reverse Address Resolution Protocol ( RARP )",
32859:"VMTP ( Versatile Message Transaction Protocol )",
32923:"AppleTalk ( EtherTalk )",
33011:"AppleTalk Address Resolution Porotocol ( AARP )",
33079:"IPX ( Novell Netware )",
33100:"SNMP over Ethernet",
33169:"NetBIOS/NetBEUI",
33149:"XTP",
34525:"IP version 6 ( IPv6 )",
34915:"PPPoE Discovery Stage",
34916:"PPPoE Session Stage",
36864:"Loopback ( Configuration Test Protocol )" }
...
2本のソースは同じディレクトリに置く。
これは、データベース作成のときの項目表示用テーブル内容と同じもの。

httpサーバ起動
$ python -m http.server 8080

アクセス可能な別のPCで。
$ curl http://192.168.x.xx
CTRL+C

$ curl http://192.168.x.xx:8080

httpサーバ停止。

プログラムの実行。

$ python dblite.py
..
date : 2025-02-27 09:54:59
oob_prefix : [DROP]
oob_protocol : 2048 / Internet IP ( IPv4 )
ip_protocol : 6 / TCP
tcp_sport : 59836
tcp_dport : 80
oob_in : wlan0
oob_out : 
ip_saddr_str : 192.168.x.132
ip_daddr_str : 192.168.x.134
----------
date : 2025-02-27 09:55:07
oob_prefix : [INPUT]
oob_protocol : 2048 / Internet IP ( IPv4 )
ip_protocol : 6 / TCP
tcp_sport : 55094
tcp_dport : 8080
oob_in : wlan0
oob_out : 
ip_saddr_str : 192.168.x.132
ip_daddr_str : 192.168.x.134
----------
date : 2025-02-27 10:03:39
oob_prefix : [DROP]
oob_protocol : 2048 / Internet IP ( IPv4 )
ip_protocol : 17 / UDP
udp_sport : 68
udp_dport : 67
oob_in : wlan0
oob_out : 
ip_saddr_str : 0.0.0.0
ip_daddr_str : 255.255.255.255
----------

SQL文でログを見る。
$ nano sql-sel1.txt
...
.separator ,

.headers on

select datetime(oob_time_sec + 32400, 'unixepoch') as JST,oob_prefix,af_family,header_prot,icmp_type6, tcp_sport,tcp_dport,udp_sport,udp_dport,oob_in,oob_out,ip_saddr_str,ip_daddr_str from all_in left outer join t_ip_prot on all_in.ip_protocol = t_ip_prot.id  left outer join t_af_family on all_in.oob_family = t_af_family.id left outer join t_icmpv6_typ on all_in.icmpv6_type = t_icmpv6_typ.id;
...
 SQL文が長いですが。

sudo sqlite3 /var/log/ulog/ulogd_sqlite3.db < sql-sel1.txt
..
JST,oob_prefix,af_family,header_prot,icmp_type6,tcp_sport,tcp_dport,udp_sport,udp_dport,oob_in,oob_out,ip_saddr_str,ip_daddr_str
2025-02-27 09:55:03,[DROP],AF_INET,TCP,,59836,80,,,wlan0,,192.168.x.132,192.168.x.134
2025-02-27 09:55:07,[INPUT],AF_INET,TCP,,55094,8080,,,wlan0,,192.168.x.132,192.168.x.134
2025-02-27 10:03:39,[DROP],AF_INET,UDP,,,,68,67,wlan0,,0.0.0.0,255.255.255.255
...
2025-02-03 「bookworm - podmanインストール」
Raspberry pi 5Bで2024-11-19 bookworm DeskTop イメージを使ってPODMANコンテナを作ってみた。
処理が遅い。Diskスペースに余裕がないとできない。

FROMで指定する種のコンテナ選びが面倒。Raspi-5B用にするにはarm64v8, bookworm用のものを探さなくては行けない。

参考:https://docs.redhat.com/ja/documentation/red_hat_enterprise_linux/8/html/building_running_and_managing_containers/con_configuring-container-registries_working-with-container-registries
3.2. コンテナーレジストリーの設定

$ sudo apt install podman podman-compose

$ podman search debian
 何も表示なし

$ podman search docker.io/debian
 リスト表示

$ mkdir -p ~/.config/containers
$ nano ~/.config/containers/registries.conf
 ..
 unqualified-search-registries = ["docker.io", "registry.access.redhat.com", "registry.redhat.io"]
 short-name-mode = "permissive"
 [[registry]]
 location="localhost:5000"
 insecure=true
 ..

$ podman search debian
 ..
 NAME                              DESCRIPTION
 docker.io/library/debian          Debian is a Linux distribution that's compos...
 docker.io/jitesoft/debian         Debian base image.
 docker.io/dockette/debian         My Debian Sid | Jessie | Wheezy Base Images
 docker.io/corpusops/debian        debian corpusops baseimage
 docker.io/treehouses/debian       
 ;;
 ;;
 ..
$ podman run docker.io/arm64v8/hello-world
 ..
 ;;
 ;; 
 Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (arm64v8)
 ;;
 ...

$ podman ps
CONTAINER ID  IMAGE       COMMAND     CREATED     STATUS      PORTS       NAMES

$ podman ps -a
CONTAINER ID  IMAGE                                 COMMAND     CREATED        STATUS                   NAMES
641fcc949ded  docker.io/arm64v8/hello-world:latest  /hello      2 minutes ago  Exited (0) 2 minutes ago nice_wilbur
 ..

$ podman search raspberrysay
NAME                           DESCRIPTION
docker.io/tiny69/raspberrysay  An Alternative version of cowsay showing a c...

$ podman search --list-tags docker.io/tiny69/raspberrysay
 NAME                           TAG
 docker.io/tiny69/raspberrysay  fortune
 docker.io/tiny69/raspberrysay  justsaying
 ...
 フルネームでないと--list-tagsが有効にならない  

$ podman run docker.io/tiny69/raspberrysay:justsaying cowsay "Happi--!"

WARNING: image platform ({arm linux  [] }) does not match the expected platform ({arm64 linux  [] })
 __________
< Happi--! >
 ----------
    \
     \
      \     
       .~~.   .~~.
      '. \ ' ' / .'
       .~ .~~~..~.
      : .~.'~'.~. :
     ~ (   ) (   ) ~
    ( : '~'.~.'~' : )
     ~ .~ (   ) ~. ~
      (  : '~' :  )  Raspberry Pi
       '~ .~~~. ~'
           '~'
 ...
$ podman run -it arm64v8/debian /bin/bash

:/# cat /etc/os-release
PRETTY_NAME="Debian GNU/Linux 12 (bookworm)"
NAME="Debian GNU/Linux"
VERSION_ID="12"
VERSION="12 (bookworm)"
VERSION_CODENAME=bookworm
ID=debian
HOME_URL="https://www.debian.org/"
SUPPORT_URL="https://www.debian.org/support"
BUG_REPORT_URL="https://bugs.debian.org/"
...

$ podman ps
  実行中のDockerコンテナはない。

$ podman ps -a
 ユーザがdockerグループにはいっていないとエラーがでる。

$ podman rm --all
  podman ps で表示されたもの以外を全部削除する

$ podman rmi --all
  podman images で表示されたものを全部削除する

$ podman run --rm -it arm64v8/debian /bin/bash
--rmをつけて動かす。
どっちにしてもexitすると結果が残せない。ctrl+p, ctrl+q でdocker runを抜け、
$ podman ps
$ podman commit コンテナID イメージID
コンテナID、イメージIDはdocker ps で表示されたもの。
今の環境をイメージに残す時に使う。docker run に戻るには、
$ podman attach コンテナID

自分用の環境を自動で作る。
ロケール日本、タイムゾーンJST, ユーザpi の場合、以下の内容でテキストファイル名"Dockerfile”を作成する。
----Dockerfile-----------
# base/Dockerfile
FROM docker.io/osrf/debian_arm64:bookworm
ENV DEBIAN_FRONTEND=noninteractive
#           SIGNAL=37
STOPSIGNAL SIGRTMIN+3
# root パスワード設定
RUN printf "rootdocker\nrootdocker\n"| passwd > /dev/null 2>&1
RUN apt update
# ロケール設定
RUN apt install -y locales locales-all
ENV LC_ALL=ja_JP.UTF-8
ENV LANG=ja_JP.UTF-8
ENV LANGUAGE=ja_JP.UTF-8
ENV TZ=Asia/Tokyo
RUN echo 'export LC_ALL="ja_JP.UTF-8"' >> /etc/profile
RUN echo 'export LANG="ja_JP.UTF-8"' >> /etc/profile
RUN echo 'export LANGUAGE="ja_JP:jp"' >> /etc/profile
RUN echo 'export TZ="Asia/Tokyo"' >> /etc/profile
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
# PATH
RUN sed -i -e "s/^.*usr\/games\"$/    PATH=\"\/usr\/local\/sbin:\/usr\/local\/bin:\/usr\/sbin:\/usr\/bin:\/sbin:\/bin:\/usr\/local\/games:\/usr\/games\"/" /etc/profile
# GPIO 設定
RUN groupadd -g 998 i2c
RUN groupadd -g 999 spi
RUN groupadd -g 993 gpio

# ユーザ作成
RUN echo "pi:pidocker:1000:1000:,,,:/home/pi:/bin/bash"|newusers
# ユーザ 設定
RUN cp -r /etc/skel/.[a-z]* /home/pi
RUN chown -R pi:pi /home/pi
RUN adduser pi adm
RUN adduser pi gpio

# 動作環境
RUN apt install -y sudo
RUN printf 'pi ALL=(ALL) NOPASSWD: ALL\n' > /etc/sudoers.d/010_pi-nopasswd

# 開発環境のインストール
RUN apt install -y less nano python3
RUN apt install -y cdebconf net-tools iproute2 tree
RUN apt install -y telnet tcpdump
RUN apt install -y python3-dev python3-pip
RUN apt install -y original-awk install-info
RUN apt install -y patch dpkg-dev build-essential autoconf 
RUN apt install -y minisat unzip # libvala-0.48-0
RUN apt install -y ncurses-dev valac valabind libncursesw5-dev
RUN apt install -y sip-dev libzzip-0-13 libzzip-dev zziplib-bin
RUN apt install -y python3-tk python3-setuptools python3-wheel shared-mime-info python3-xdg file python3-keyring
RUN apt install -y git
RUN apt install -y libpython3-dev wget curl
RUN apt install -y python-is-python3
RUN apt install -y iputils-ping nftables

RUN apt install -y apt-utils
COPY raspi.list /etc/apt/sources.list.d
RUN wget  http://archive.raspberrypi.org/debian/raspberrypi.gpg.key
RUN apt-key add raspberrypi.gpg.key
RUN apt update
RUN apt install -y ncal python3-gpiozero
RUN apt install -y python3-numpy
COPY chime.py /home/pi
USER pi
WORKDIR /home/pi
CMD ["/bin/bash"]
----作成
$ cp /etc/apt/sources.list.d/raspi.list .

$ nano chime.py
...
from gpiozero import PWMOutputDevice
from time import sleep

buzzer = PWMOutputDevice(pin=19, frequency=440)  # 440 Hz is the frequency of the A4 note

try:
    print("Playing sound on buzzer...")
    while True:
        buzzer.value = 0.5  # 50% duty cycle for a continuous tone
        sleep(1)            # Play the tone for 1 second
        buzzer.off()        # Turn off the buzzer
        sleep(1)            # Wait for 1 second before playing again
except KeyboardInterrupt:
    print("Program stopped")
finally:
    buzzer.close()
...

$ podman build -t base .
 タグ名はdocker imagesで表示されるrepository名、Dockefileパスはカレントディレクトリであれば、ドット。
 Dockerよりpodmanのほうが作成に時間がかかる

$ podman run --privileged -ti --rm --network host base
 networkはホストのnetworkが見えるようになる

$ podman run --privileged --userns=keep-id  -ti --rm base python /home/pi/chime.py
  --- Buzzer OK --.
  chime.pyはコンテナ内にCOPYする。

 GPIO-19にピエゾを接続すること。(LED-抵抗でもよい)

$ podman run --privileged --userns=keep-id  -ti --rm base pinout
..
WARNING: image platform ({amd64 linux  [] }) does not match the expected platform ({arm64 linux  [] })
Description        : Raspberry Pi 5B rev 1.0
Revision           : c04170
SoC                : BCM2712
RAM                : 4GB
Storage            : MicroSD
USB ports          : 4 (of which 2 USB3)
Ethernet ports     : 1 (1000Mbps max. speed)
Wi-fi              : True
Bluetooth          : True
Camera ports (CSI) : 2
Display ports (DSI): 2

,--------------------------------.
| oooooooooooooooooooo J8   : +====
| 1ooooooooooooooooooo      : |USB2
|  Wi  Pi Model 5B  V1.0  fan +====
|  Fi     +---+      +---+       |
|         |RAM|      |RP1|    +====
||p       +---+      +---+    |USB3
||c      -------              +====
||i        SoC      |c|c J14     |
(        -------  J7|s|s 12 +======
|  J2 bat   uart   1|i|i oo |   Net
| pwr\..|hd|...|hd|o|1|0    +======
`-| |-1o|m0|---|m1|--------------'

J8:
   3V3  (1) (2)  5V    
 GPIO2  (3) (4)  5V    
 GPIO3  (5) (6)  GND   
 GPIO4  (7) (8)  GPIO14
   GND  (9) (10) GPIO15
GPIO17 (11) (12) GPIO18
GPIO27 (13) (14) GND   
GPIO22 (15) (16) GPIO23
   3V3 (17) (18) GPIO24
GPIO10 (19) (20) GND   
 GPIO9 (21) (22) GPIO25
GPIO11 (23) (24) GPIO8 
   GND (25) (26) GPIO7 
 GPIO0 (27) (28) GPIO1 
 GPIO5 (29) (30) GND   
 GPIO6 (31) (32) GPIO12
GPIO13 (33) (34) GND   
GPIO19 (35) (36) GPIO16
GPIO26 (37) (38) GPIO20
   GND (39) (40) GPIO21

J2:
RUN (1)
GND (2)

J7:
COMPOSITE (1)
      GND (2)

J14:
TR01 TAP (1) (2) TR00 TAP
TR03 TAP (3) (4) TR02 TAP

For further information, please refer to https://pinout.xyz/
...

PYTHON計算例

$ nano eig.py
..
import numpy as np
print(np.linalg.eig([[ 6, -3,  5],[-1,  4, -5],[-3,  3, -4]]))
..

$ podman run -v ./eig.py:/home/pi/eig.py -ti --rm base echo "--プログラム";cat eig.py;echo "--答え"; python eig.py
...
WARNING: image platform ({amd64 linux  [] }) does not match the expected platform ({arm64 linux  [] })
--プログラム
import numpy as np
print(np.linalg.eig([[ 6, -3,  5],[-1,  4, -5],[-3,  3, -4]]))
--答え
(array([3., 2., 1.]), array([[ 7.07106781e-01, -3.01511345e-01,  6.49055182e-16],
       [ 7.07106781e-01, -9.04534034e-01,  8.57492926e-01],
       [-2.46749603e-15, -3.01511345e-01,  5.14495755e-01]]))
...
2025-01-29 「ラジコ インストール」
参照:
http://mycc.s33.xrea.com/data/rpi/lis_radiko.html
Raspberry Pi用 radiko 簡易聴取スクリプト

http://mycc.s33.xrea.com/data/rpi/lis_radiko.tar.gz

$ env | grep -i runt
XDG_RUNTIME_DIR=/run/user/10xxx
これを覚えておく

lis_radiko.tar.gzを解凍して、修正。

$ nano list_radiko.sh
====
# $ env|grep -i runt で表示される環境変数と内容
export XDG_RUNTIME_DIR=/run/user/10xxx
... 追加

export SDL_AUDIODRIVER=''
export AUDIODEV=''        # 出力スピーカー指定を両方''にする

 ;;

mail='メールアドレス'					# ラジコプレミアム
pass='パスワード'					# ラジコプレミアム
 ;;

# 録音する場合はffplayコマンドを以下のように修正

    outputfnm="${savedir}/${pname}_$(date +%Y年%m月%d日%H時%M分).mp4"
    ffmpeg \
      -loglevel error \
      -fflags +discardcorrupt \
      -headers "X-Radiko-Authtoken: ${authtoken}" \
      -i "${suri}${pname}/_definst_/simul-stream.stream/playlist.m3u8" \
      -acodec copy \
      -vn \
      -bsf:a aac_adtstoasc \
      -y \
      -t 録音時間 \
      ${outputfnm}
====
使い方:
$ ./lis_radiko.sh LFR
    最初の引数に、 ラジコIDを指定。

サウンド出力設定はなしにすると、現在のデスクトップのalasa音量設定での音量となる。
export XDG_RUNTIME_DIRの指定は現在ユーザの環境でalsaの音量となる。ffplay, mplayerに有効。
.bashrc, crontab -eに記述する時に便利。
録音時間は"hh:mm:ss"の形式で指定。hh時間 mm分 ss秒。

上記、参照URLにおすすめのshellタイムフリー録音がある。
2025-02-26 「USB WIFI アダプタで、Wifi AP ルーター」
Raspberry pi 初版ボード,2B の古いボードで2.4GHz、5Ghz AP

      ▽
   |2.4GHz Wlan0 : 192.168.A.99 ==>> 192.168.A.xxx自動割当
   | ▽
   | |5GHz Wlan1 : 192.168.B.99 ==>> 192.168.B.xxx自動割当
  +--------+
    | router |
  +--------+
   |eth0 : 192.168.1.99

(1) Raspberry pi 
    OS Arm32 bookworm 2024-11-19 lite image , 8MB SD card
(2) 設定
  $ sudo raspi-config
  ...
  keyboard 
   user  -- password
   host  -- ホスト名
   ssh
   LOCALE ja_JP.UTF-8
   timezone Asia/Tokyo
   wifi     JP
  ...

(3) sudo reboot

(4) 固定IPアドレス
    $ nmcli con show
    $ sudo nmcli con mod "有線接続 1" ipv4.addresses 192.168.1.99/24 ipv4.gateway 192.168.1.xx ipv4.dns 192.168.1.xx ipv4.method manual


(5) UGREEN Wi-Fi 無線LAN 子機 AC650 433Mbps + 200Mbps 5GHz/2.4GHz USB ワイヤレス ネットワーク アダプター
    子機としては使えるが、WIFI APとしては使えないのでソースからのインストール。

  $ sudo apt install -y raspberrypi-kernel-headers build-essential bc dkms git
  $ git clone https://github.com/morrownr/8821cu-20210916.git
  $ cd 8821cu-20210916
  $ sudo ./install-driver.sh
    時間がかかる。途中で、
   /etc/modprobe.d/8821cu.conf 修正
  ....
   options 8821cu rtw_led_ctrl=1 rtw_country_code=JP
  ....            +++++++++++
  "rtw_country_code=JP"追加
  
  $ sudo reboot

  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 ◎ELECOM WDC-433SU2M2BK (5GHz)のとき
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  https://github.com/morrownr/8821au-20210708 より

  $ sudo apt install -y raspberrypi-kernel-headers build-essential bc dkms git
  $ mkdir src
  $ cd src
  $ git clone https://github.com/morrownr/8821au-20210708.git
  $ cd 8821au-20210708
  $ sudo ./install-driver.sh NoPrompt
    少し時間がかかる
  $ make clean
  $ make
    少し時間がかかる
  $ sudo make install
  $ sudo reboot


(6) Wifi wlan0 有効
   sudo nmcli radio wifi
   sudo nmcli radio wifi on
   sudo nmcli dev wifi list
      SSID一覧表示

(7) Wifi AP 作成

 $ nano wp1.sh
---- wp1.sh ----
#!/bin/sh
sudo nmcli con delete raspi-1
sudo nmcli con add type wifi ifname wlan0 mode ap con-name raspi-1 ssid "SSID 1 名前" autoconnect yes
sudo nmcli con modify raspi-1 wifi.band bg
sudo nmcli con modify raspi-1 wifi.channel 7
#  2.4Ghz = wifi.band bg , 5GHz = wifi.band a
sudo nmcli con modify raspi-1 wifi-sec.key-mgmt wpa-psk
sudo nmcli con modify raspi-1 wifi-sec.proto rsn
sudo nmcli con modify raspi-1 wifi-sec.group ccmp
sudo nmcli con modify raspi-1 wifi-sec.pairwise ccmp
sudo nmcli con modify raspi-1 wifi-sec.psk "パスワード 1"
sudo nmcli con modify raspi-1 ipv4.method shared ipv4.address 192.168.x.99/24
sudo nmcli con up raspi-1
----
   channel指定して1以外にする。1だと接続しない

  sudo nmcli con modify raspi-1 wifi-sec.proto rsn
  sudo nmcli con modify raspi-1 wifi-sec.group ccmp
  sudo nmcli con modify raspi-1 wifi-sec.pairwise ccmp
   Raspberry pi 内蔵2.4GHzWiFiを使うには上の3行はないほうが良い

  $ sh wp1.sh

 $ nano wp2.sh
---- wp2.sh ----
#!/bin/sh
sudo nmcli con delete raspi-2
sudo nmcli con add type wifi ifname wlan1 mode ap con-name raspi-2 ssid "SSID 2 名前" autoconnect yes
sudo nmcli con modify raspi-2 wifi.band a
sudo nmcli con modify raspi-2 wifi.channel 40
#  2.4Ghz = wifi.band bg , 5GHz = wifi.band a
sudo nmcli con modify raspi-2 wifi-sec.key-mgmt wpa-psk
sudo nmcli con modify raspi-2 wifi-sec.proto rsn
sudo nmcli con modify raspi-2 wifi-sec.group ccmp
sudo nmcli con modify raspi-2 wifi-sec.pairwise ccmp
sudo nmcli con modify raspi-2 wifi-sec.psk "パスワード 2"
sudo nmcli con modify raspi-2 ipv4.method shared ipv4.address 192.168.x.99/24
sudo nmcli con up raspi-2
----
  $ sh wp2.sh

 接続、raspi-1, 2  --- 情報は以下のディレクトリ
 /etc/NetworkManager/system-connections/
      nmcli type wifi ifname wlan0 mode ap で指定したcon-nameの
   raspi-1.nmconnection、raspi-2.nmconnection ファイルができる

 $ sudo nmcli con show "raspi-1"
    設定の確認
 
  USBアダプタに2.4GHz,5GHz片方しかない場合は、リブートしたときWLAN0,1が入れ替わる場合はUDEVで固定する
 必要がある。

(8) Firewall

  $ sudo nano /home/pi/nftables.sh
--- nftables.sh ----
#!/bin/sh
# (c) K.Shimomura (The MIT License)
WLAN_DEV=wlan0            # local lan device
WLAN2_DEV=wlan1
ETH_DEV=eth0              # global lan device
WLAN_ALLOW=192.168.x.0/24 # allow local ip addr (WLAN 0 IPアドレス)
WLAN2_ALLOW=192.168.x.0/24 #                    (WLAN 1 IPアドレス)
ETH_ALLOW=192.168.x.0/24  # allow eth ip addr   (eth0 IPアドレス)

echo "[NFTABLES.SH] **** start ****" > /dev/kmsg
nft flush ruleset
# === ipv6 initial ===
nft add table ip6 filter6
nft add chain ip6 filter6 INPUT { type filter hook input priority 0 \; policy drop \; }
nft add chain ip6 filter6 FORWARD {  type filter hook forward priority 0 \; policy drop \; }
nft add chain ip6 filter6 OUTPUT {  type filter hook output priority 0 \; policy accept \; }
nft add chain ip6 filter6 POSTROUTING { type nat hook postrouting priority 100 \; policy drop \; }
#nft add rule ip6 filter6 POSTROUTING log prefix \"[NFTABLES6 POST_R]\"
nft add rule ip6 filter6 POSTROUTING drop
#nft add rule ip6 filter6 FORWARD  log prefix \"[NFTABLES6 Forward]\"
nft add rule ip6 filter6 FORWARD drop
#nft add rule ip6 filter6 INPUT log prefix \"[NFTABLES6 INPUT]\"
nft add rule ip6 filter6 INPUT drop

# === ipv4 initial ===
nft add table ip filter
nft add chain ip filter INPUT { type filter hook input priority 0 \; policy drop \; }
nft add chain ip filter FORWARD {  type filter hook forward priority 0 \; policy drop \; }
nft add chain ip filter OUTPUT {  type filter hook output priority 0 \; policy accept \; }
nft add chain ip filter callsub
nft add chain ip filter POSTROUTING { type nat hook postrouting priority 100 \; policy drop \; }
nft add rule ip filter POSTROUTING oifname ${ETH_DEV} masquerade
nft add rule ip filter POSTROUTING oifname ${WLAN_DEV} masquerade
nft add rule ip filter POSTROUTING oifname ${WLAN2_DEV} masquerade
#nft add rule ip filter POSTROUTING log prefix \"[NFTABLES POST_R]\"

nft add rule ip filter FORWARD oifname { ${ETH_DEV} , ${WLAN_DEV}, ${WLAN2_DEV} } ct state related,established accept

nft add rule ip filter FORWARD ip saddr { ${WLAN_ALLOW},  ${WLAN2_ALLOW} } ip daddr { ${WLAN2_ALLOW},  ${WLAN_ALLOW} } accept
nft add rule ip filter FORWARD iifname ${ETH_DEV} ip saddr ${ETH_ALLOW} ip daddr { ${WLAN_ALLOW},  ${WLAN2_ALLOW} } accept
nft add rule ip filter FORWARD ip saddr { ${WLAN_ALLOW}, ${WLAN2_ALLOW} } oifname ${ETH_DEV} accept # for global address
#nft add rule ip filter FORWARD log prefix \"[NFTABLES Forward]\"

nft add rule ip filter INPUT iifname "lo" counter accept
nft add rule ip filter INPUT iifname ${ETH_DEV} ct state related,established accept
nft add rule ip filter INPUT iifname ${WLAN_DEV} ct state related,established accept
nft add rule ip filter INPUT iifname ${WLAN2_DEV} ct state related,established accept
nft add rule ip filter callsub 'tcp  flags & (fin|syn|rst|ack) == syn limit rate 5/second burst 5 packets accept'
nft add rule ip filter INPUT ip daddr { ${WLAN_ALLOW}, ${WLAN2_ALLOW}, ${ETH_ALLOW} } meta l4proto {tcp,udp} th dport { 43, 53,123, 443 } accept
nft add rule ip filter INPUT ip daddr { ${WLAN_ALLOW}, ${WLAN2_ALLOW}, ${ETH_ALLOW} } meta l4proto {tcp,udp} th sport 443 jump callsub
nft add rule ip filter INPUT iifname ${ETH_DEV} udp dport 138 jump callsub
nft add rule ip filter INPUT udp dport 5353 accept
nft add rule ip filter INPUT ip daddr { 224.0.0.0/8, 224.0.0.0/8 } accept
nft add rule ip filter INPUT ip daddr {255.255.255.255, ${WLAN_ALLOW}, ${WLAN2_ALLOW} } meta l4proto {tcp,udp} th dport 67-68 accept
nft add rule ip filter INPUT ip daddr { ${ETH_ALLOW}, ${WLAN_ALLOW}, ${WLAN2_ALLOW} } tcp dport 22  jump callsub
#nft add rule ip filter INPUT log prefix \"[NFTABLES INPUT callsub ext]\"
-----
   $ chmod +x /home/pi/nftables.sh


    192.168.1.xx   192.168.2.xx
   ▼ wifi-0     ▼ wifi-1
       |             |
     [   ]         [   ]    wifi-0 , wifi-1 へ接続
       |             |
       +=============+ 

  上記のnftコマンドのmasquerade設定では、wlan0,wlan1は相互接続可能にしているのでルート設定はいらない。
 eth0側でのルート設定をされたときの対策はとっていないので注意が必要。

(9) rc.local追加
  --- /etc/rc.local ---
  #!/bin/sh -e
  /home/pi/nftables.sh
  exit 0
  ----
  追加する。
  $ sudo chmod +x /etc/rc.local
  $ sudo systemctl restart rc-local
  $ sudo systemctl status rc-local
    動作確認
  $ sudo reboot



(10) クライアント側での確認

  $ sudo nmcli dev wifi list
  IN-USE  BSSID              SSID     MODE      CHAN  RATE        SIGNAL  BARS  SECURITY 
  *       xx:27:xx:CA:33:EE  SBxxxxx  インフラ  7     65 Mbit/s   75      ▂▄▆_  WPA1 WPA2     

参照:
https://github.com/brektrou/rtl8821CU

https://askubuntu.com/questions/1162974/wireless-usb-adapter-0bdac811-realtek-semiconductor-corp
Wireless USB Adapter 0bda:c811 Realtek Semiconductor Corp

◆参考:https://pilink.jp/wifi-ap_pl-r4/
    NetWorkManagerだけでラズパイをWi-Fiアクセスポイント化する方法
   より、
   wifi-sec.pairwise ccmp 、wifi-sec.proto rsn
   環認証方式がWPA2、プロトコルがRSN、暗号方式はAES(≒CCMP)設定
2025-01-20  「bookworm - Dockerインストール」
参考1:
https://docs.docker.com/engine/install/debian/
Install Docker Engine on Debian
  OS requirements
  To install Docker Engine, you need the 64-bit version of one of these Debian versions:
    Debian Bookworm 12 (stable)

https://docs.docker.com/engine/install/debian/
https://docs.docker.com/engine/install/raspberry-pi-os/
https://docs.docker.jp/linux/step_one.html
Docker のインストール

参考2:
http://docs.docker.jp/pdf-download.html#id1
Docker ドキュメント日本語版 PDF ダウンロード

SoftwareDesign 2015年12月号 第1特集 Docker自由自在 技術評論社
Dockerエキスパート養成読本  技術評論社

https://raspida.com/rpi4-docker-install/
Raspberry Pi 4でDockerのインストール方法 2023年度版

◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇

RAspberry pi 4BとRaspberry pi 5BとのGPIOのI/Oマップベースアドレスが違うのでDockerインストール後
のコンテナではRaspi-5BではGPIOにアクセスできない。

そのためにコンテナ作成手順を変更した。

◆◆◆◆◆ インストール方法 ◆◆◆◆◆

.... arm64 2024-11-19 Desktop イメージ使用

$ curl -fsSL https://get.docker.com -o get-docker.sh
$ sudo sh get-docker.sh

$ sudo usermod -aG docker `whoami`
$ newgrp docker
$ docker run hello-world
 ...
     ;;
Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (arm64v8)
     ;;
 ...
$ docker ps
  実行中のDockerコンテナはない。
 ユーザがdockerグループにはいっていないとエラーがでる。
$ docker ps -a

  5beaf08a627f   hello-world   "/hello"   About a minute ago   Exited (0) About a minute ago             jolly_golick
  hello-worldのDockerコンテナIDが表示。

$ docker run tiny69/raspberrysay:justsaying cowsay hello
 ...
    ;;
 _______
Digest: sha256:115eff34a19d0c8aa91a8677cf9431b85eaafe7864d55fc2a0524afd26d5b126
Status: Downloaded newer image for tiny69/raspberrysay:justsaying
 _______
< hello >
 -------
    \
     \
      \     
       .~~.   .~~.
      '. \ ' ' / .'
       .~ .~~~..~.
      : .~.'~'.~. :
     ~ (   ) (   ) ~
    ( : '~'.~.'~' : )
     ~ .~ (   ) ~. ~
      (  : '~' :  )  Raspberry Pi
       '~ .~~~. ~'
           '~'

$ docker run -it arm64v8/debian:bookworm /bin/bash
 ...

# cat /etc/os-release
...
PRETTY_NAME="Debian GNU/Linux 12 (bookworm)"
NAME="Debian GNU/Linux"
VERSION_ID="12"
VERSION="12 (bookworm)"
VERSION_CODENAME=bookworm
ID=debian
HOME_URL="https://www.debian.org/"
SUPPORT_URL="https://www.debian.org/support"
BUG_REPORT_URL="https://bugs.debian.org/"

# exit
これだとコンテナがいっぱいできる。
$ docker ps
動作中なし
$ docker ps -a
 ...
$ docker ps -a
CONTAINER ID   IMAGE                            COMMAND                   CREATED          STATUS                      PORTS     NAMES
a1448e7d4f45   arm64v8/debian                   "/bin/bash"               9 m......
ea7bd252d167   tiny69/raspberrysay:justsaying   "/usr/bin/entry.sh c…"   10 mi....
5beaf08a627f   hello-world                      "/hello"                  13 mi....
 ...
 残っている
$ docker rm xxxx表示しているコンテナID
$ docker ps -a
なし。

$ docker run --rm -it arm64v8/debian /bin/bash
--rmをつけて動かす。
どっちにしてもexitすると結果が残せない。ctrl+p, ctrl+q でdocker runを抜け、
$ docker ps
$ docker commit コンテナID イメージID
コンテナID、イメージIDはdocker ps で表示されたもの。
今の環境をイメージに残す時に使う。docker run に戻るには、
$ docker attach コンテナID

コンテナのもとになるdockerイメージ(docker hubにあるもの)を検索するには、
$ docker search キーワード
 キーワードはrpi, raspbian, bullseye等で検索して適当なイメージをdocker runで指定する。

自分用の環境を自動で作る。
ロケール日本、タイムゾーンJST, sshサーバ、ユーザpi の場合、以下の内容でテキストファイル名"Dockerfile”を作成する。
----Dockerfile-----------
# base/Dockerfile
FROM arm64v8/debian
ENV DEBIAN_FRONTEND=noninteractive
#           SIGNAL=37
STOPSIGNAL SIGRTMIN+3
# root パスワード設定
RUN printf "rootdocker\nrootdocker\n"| passwd > /dev/null 2>&1
RUN apt update
# ロケール設定
RUN apt install -y locales locales-all
ENV LC_ALL=ja_JP.UTF-8
ENV LANG=ja_JP.UTF-8
ENV LANGUAGE=ja_JP.UTF-8
ENV TZ=Asia/Tokyo
RUN echo 'export LC_ALL="ja_JP.UTF-8"' >> /etc/profile
RUN echo 'export LANG="ja_JP.UTF-8"' >> /etc/profile
RUN echo 'export LANGUAGE="ja_JP:jp"' >> /etc/profile
RUN echo 'export TZ="Asia/Tokyo"' >> /etc/profile
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
# PATH
RUN sed -i -e "s/^.*usr\/games\"$/    PATH=\"\/usr\/local\/sbin:\/usr\/local\/bin:\/usr\/sbin:\/usr\/bin:\/sbin:\/bin:\/usr\/local\/games:\/usr\/games\"/" /etc/profile
# GPIO 設定
RUN groupadd -g 998 i2c
RUN groupadd -g 999 spi
RUN groupadd -g 993 gpio

# ユーザ作成
RUN echo "pi:pidocker:1000:1000:,,,:/home/pi:/bin/bash"|newusers
# ユーザ 設定
RUN cp -r /etc/skel/.[a-z]* /home/pi
RUN chown -R pi:pi /home/pi
RUN adduser pi adm
RUN adduser pi gpio

# 動作環境
RUN apt install -y init
RUN apt install -y sudo
RUN printf 'pi ALL=(ALL) NOPASSWD: ALL\n' > /etc/sudoers.d/010_pi-nopasswd
RUN apt install -y openssh-server

# 開発環境のインストール
RUN apt install -y less nano python3
RUN apt install -y cdebconf net-tools iproute2 tree
RUN apt install -y bind9-host telnet mailutils tcpdump
RUN apt install -y python3-dev python3-pip
RUN apt install -y original-awk install-info
RUN apt install -y patch dpkg-dev build-essential autoconf 
RUN apt install -y minisat unzip # libvala-0.48-0
RUN apt install -y ncurses-dev valac valabind libncursesw5-dev
RUN apt install -y sip-dev libzzip-0-13 libzzip-dev zziplib-bin
RUN apt install -y python3-tk python3-setuptools python3-wheel shared-mime-info python3-xdg file python3-keyring
RUN apt install -y nfs-common
RUN apt install -y libi2c-dev git
RUN apt install -y libpython3-dev wget curl
RUN apt install -y python-is-python3
RUN apt install -y iputils-ping nftables
#RUN apt install -y cron

# install rc.local
RUN printf "#!/bin/sh -e\n\
\n\
echo \"[DOCKER rc.local] **** START ****\"\n\
exit 0\n" > /etc/rc.local
RUN chmod +x /etc/rc.local
RUN apt install -y apt-utils
COPY raspi.list /etc/apt/sources.list.d
COPY sources.list /etc/apt
RUN rm /etc/apt/sources.list.d/debian.sources
RUN wget  http://archive.raspberrypi.org/debian/raspberrypi.gpg.key
RUN apt-key add raspberrypi.gpg.key
RUN apt update
RUN apt install -y raspi-utils python3-gpiozero

CMD ["/sbin/init"]
----作成

参照: https://forums.raspberrypi.com/viewtopic.php?t=290058
      How do I Get public key for http://archive.raspberrypi.org/debian buster

 DeskTop OSでもRASPI 5BでDockerインストールし、そのままでgpiozero,rrpi.gpioをIMPORTしてもエラーとなる。
 Raspberry pi5B は、I/Oマップのベースアドレスエラーとなる。install方法を変更した。
 raspi-utils と python3-gpiozero のパッケージでコマンドpinout, pinctrlが使用できるようになる。
 raspi-5Bでは,rpi.GPIOはI/Oマップベースアドレスエラーとなるので使えない。
 raspi-4Bでは,gpiozero と rpi.GPIOは使える。

$ cp /etc/apt/sources.list.d/raspi.list .
$ cp /etc/apt/sources.list .

$ docker build -t base ./Dockerfileパス
タグ名はdocker imagesで表示されるrepository名、Dockefileパスはカレントディレクトリであれば、ドット。

$ docker run --privileged --cap-add SYS_ADMIN -ti --rm -p 222:22 コンテナイメージ名[:タグ名]
 login状態になるので、pi -> pidockerでログインできる。
 rootはrootdockerでログインできる。

SSHを使う場合は別 IPアドレスから、
$ ssh -p 222 pi@192.168.x.x
  パスワードpidockerでログインできる。

LED GPIO-5 PINを点滅

 GPIO 5 --[ 510Ω ]--▶‖-----> GND

参照:https://gpiozero.readthedocs.io/en/stable/recipes.html
      2. Basic Recipes

上記のDockefileで作成したコンテナをRUNし、pi でログインする。
----
$ docker run --privileged --cap-add SYS_ADMIN -ti --rm -p 222:22 タグ名
  user : pi -> password : pidocker

Dockerコンテナ内で、

$ nano led.py
--- led.py ------------
from gpiozero import PWMLED
from signal import pause
led = PWMLED(5)
led.pulse()
pause()
---

$ python led.py
 点滅する。
 Ctrl+C 終わり

$ sudo poweroff
Dockerコンテナ終了。

==== Docker プライベートレジストリ ====
参考:
https://docs.docker.com/registry/
 Docker registry
https://distribution.github.io/distribution/
 Docker registry ドキュメント
https://distribution.github.io/distribution/spec/api/
 HTTP API V2

https://distribution.github.io/distribution/about/deploying/
 Deploy a registry server
 (サーバーの使い方)

ドキュメントが詳しくなったからか量が多い。

https://github.com/AlekseyChudov/docker-registry
 Python script Docker Registry 一覧: 
・・・

プライベートレジストリになる自分のハードディスクに割り当てる。~/Dockerにコンテナイメージが残る。

$ mkdir -p ~/Docker

$ docker run -d -p 5000:5000  -v ${HOME}/Docker:/var/lib/registry -e REGISTRY_STORAGE_DELETE_ENABLED=true  --restart always --name registry registry

 レジストリイメージ実行
 -vはレジストリにアップロードされたイメージを消えないようにローカルマシンの世界へ持ってくるようにする。
 -v ${HOME}/Docker:/var/lib/registryの ~/DockerがDcokerホスト側で見えるアップロードされたコンテナが格納されるディレクトリ。


テストは、
$ docker run tiny69/raspberrysay:justsaying cowsay hello
前記で作ったHello コンテナで行う。

$ docker tag tiny69/raspberrysay:justsaying localhost:5000/tiny69/raspberrysay:justsaying
 プライベートレジストリの名前をつける。

$ docker push localhost:5000/tiny69/raspberrysay:justsaying
  pushするときはタグをつけるようにする。プライベートレジストリへ送る。

  Docker Registry コンテナ内のアップロード先ディレクトリの確認は、
 $ docker ps
 $ docker exec -ti registryコンテナID /bin/sh
  / # cat /etc/docker/registry/config.yml
  でストレージ・ファイルシステム・ルートディレクトリを見る。
  / # ls /var/lib/registry/docker/registry/v2/repositories
  tiny69がある。
 / # exit

手元にlocalhost:5000/tiny69/raspberrysay:justsayingがないことの確認。
$ docker ps -a
  localhost:5000/tiny69/raspberrysay, tiny69/raspberrysay コンテナないこと
$ docker images
$ docker rmi localhost:5000/tiny69/raspberrysay:justsaying
  localhost:5000/tiny69/raspberrysay, tiny69/raspberrysay イメージを消す
  (REPGITORY, TAG がないものは、IMAGE IDを指定する)

プライベートレジストリからのダウンロード。

$ docker run --rm localhost:5000/tiny69/raspberrysay:justsaying cowsay "Yahho"

 ________
< Yahho >;
 --------
    \
     \
      \     
       .~~.   .~~.
      '. \ ' ' / .'
       .~ .~~~..~.
      : .~.'~'.~. :
     ~ (   ) (   ) ~
    ( : '~'.~.'~' : )
     ~ .~ (   ) ~. ~
      (  : '~' :  )  Raspberry Pi
       '~ .~~~. ~'
           '~'


●プライベートレポジトリのレポジトリ登録一覧表示
$ curl http://localhost:5000/v2/_catalog
--
{"repositories":["tiny69/raspberrysay"]}
---
$ curl http://localhost:5000/v2/tiny69/raspberrysay/tags/list
--
{"name":"tiny69/raspberrysay","tags":["justsaying"]}
--

で表示できる。v2/よりあとはDocker Resistry API V2 コマンド仕様を参照。

●プライベートレポジトリの登録一覧表示のPythonスクリプトのインストール

$ git clone https://github.com/AlekseyChudov/docker-registry.git
$ cd docker-registry

このままでは動作しないので、以下の修正をする。
$ nano docker-registry
---
#!/usr/bin/env python     >>== python2をpythonにする
import urlparse <=この行を以下のように修正
from urllib.parse import urlparse >>== form urllib.parse 追加

class DockerRegistry(object):の最初
def __init__(self, args):
    self._args = args
    self._registry = urlparse(self._args.url).netloc >>==urlparseのみに修正
    self._session = self._create_session()
---

 使い方
    ./docker-registry catalog [name_regex] [tag_regex]
    ./docker-registry images [name_regex] [tag_regex]
    ./docker-registry manifest name tag
    ./docker-registry blob name layer_digest output_file
    ./docker-registry delete name image_digest

 ・sudo cp docker-registry /usr/local/sbin
   でコピーして使う。

$ ./docker-registry catalog
+----------------+---------------------+------------+
| REGISTRY       | NAME                | TAG        |
+----------------+---------------------+------------+
| localhost:5000 | tiny69/raspberrysay | justsaying |
+----------------+---------------------+------------+
|                                          Total: 1 |
+----------------+---------------------+------------+

$ ./docker-registry -l http://localhost:5000 catalog
+----------------+---------------------+------------+
| REGISTRY       | NAME                | TAG        |
+----------------+---------------------+------------+
| localhost:5000 | tiny69/raspberrysay | justsaying |
+----------------+---------------------+------------+
|                                          Total: 1 |
+----------------+---------------------+------------+

$ ./docker-registry images tiny69/raspberrysay
+----------------+---------------------+------------+------------------------------------------+----------+
| REGISTRY       | NAME                | TAG        | DIGEST                                   | SIZE     |
+----------------+---------------------+------------+------------------------------------------+----------+
| localhost:5000 | tiny69/raspberrysay | justsaying | sha256:5020d0a349654c6814720fe9f64506525 |          |
|                |                     |            |          3ca2b88ad7805355f794ae947b08966 | 63726689 |
+----------------+---------------------+------------+------------------------------------------+----------+
|                                                                                                Total: 1 |
+----------------+---------------------+------------+------------------------------------------+----------+

$ ./docker-registry delete tiny69/raspberrysay sha256:5020d0a349654c6814720fe9f645065253ca2b88ad7805355f794ae947b08966

$ ./docker-registry images tiny69/raspberrysay
+----------------+---------------------+--------+--------+--------+
| REGISTRY       | NAME                | TAG    | DIGEST | SIZE   |
+----------------+---------------------+--------+--------+--------+
| localhost:5000 | tiny69/raspberrysay | <none> | <none> | <none> |
+----------------+---------------------+--------+--------+--------+
|                                                        Total: 1 |
+----------------+---------------------+--------+--------+--------+

$ ./docker-registry catalog
+----------------+---------------------+--------+
| REGISTRY       | NAME                | TAG    |
+----------------+---------------------+--------+
| localhost:5000 | tiny69/raspberrysay | <none> |
+----------------+---------------------+--------+
|                                      Total: 1 |
+----------------+---------------------+--------+

●  プライベートレジストリとは別のクライアントから

 docker push するとPUSHしない。
  クライアント側のDOCKERサーバに、

 sudo nano /etc/docker/daemon.json
  ---
  { "insecure-registries":["192.168.1.xx:5000"] }
  ---作成 IPアドレスレポジトリサーバ側のアドレス
 sudo systemctl restart docker
  で docker push できる。

 参考:
  https://attonblog.blogspot.com/2018/07/save-my-image-using-docker-registry.html
  自前の Docker Registry を立てて、 Build した Image を保存する
  ・・・
$ docker tag tiny69/raspberrysay:justsaying 192.168.1.xx:5000/tiny69/raspberrysay:justsaying
  レポジトリIPアドレス指定

$ docker push 192.168.1.xx:5000/tiny69/raspberrysay:justsaying
  DOCKERコンテナイメージ PUSH

$ docker-registry -l http://192.168.1.xx:5000 catalog
  PUSH されたイメージがあること

$ docker run --rm 192.168.1.10:5000/tiny69/raspberrysay:justsaying cowsay "wooYahho"
 最初はLOGINしてないので実行されない
 $ docker login 192.168.1.xx:5000/Docker
    ユーザ名とパスワード入力
  ~/.docker/config.json ファイルができる
  あとはLOGINなしでもよい

 もう一度RUNすると実行する。

● DOCKER-COMPOSE

 参照:https://zenn.dev/sigma_tom/books/e905f2a57b9627/viewer/docker-compose
    docker-composeとdocker compose

        https://stackoverflow.com/questions/36249744/interactive-shell-using-docker-compose
        Interactive shell using Docker Compose

        https://stackoverflow.com/questions/45511956/remove-a-named-volume-with-docker-compose
        Remove a named volume with docker-compose?

  WEB検索でだいたいのコマンドがdocker-composeなので、やってみるとコマンドがないと出る。
  $ dpkg -l で
 docker-compose-plugin がある。
 docker compose コマンドでよい。

 ①最もシンプルなDockerfileなしのシングルコンテナ
 $ nano compose.yaml
  ...
  services:
   simple:
    container_name: raspisay
    image: tiny69/raspberrysay:justsaying
    command: cowsay "Yahho--!"
  ...
  $ docker compose up
  ...
  Recreating coeasy ... done
  Attaching to raspisay
  raspisay   |  __________
  raspisay   | < Yahho--! >
  raspisay   |  ----------
  raspisay   |     \
  raspisay   |      \
  raspisay   |       \     
  raspisay   |        .~~.   .~~.
  raspisay   |       '. \ ' ' / .'
  raspisay   |        .~ .~~~..~.
  raspisay   |       : .~.'~'.~. :
  raspisay   |      ~ (   ) (   ) ~
  raspisay   |     ( : '~'.~.'~' : )
  raspisay   |      ~ .~ (   ) ~. ~
  raspisay   |       (  : '~' :  )  Raspberry Pi
  raspisay   |        '~ .~~~. ~'
  raspisay   |            '~'
  raspisay   | 
  raspisay exited with code 0
  ...
  この後、docker ps -a でコンテナが残っている。
 $ docker compose down
  この後、docker ps -a でコンテナが消える。

 ②shell起動コンテナ
  $ nano compose.yaml
  ...
  services:
    my-test:
      image: arm64v8/debian:bookworm
      command: /bin/bash
      stdin_open: true
      tty: true
  ...
  この定義で以下のコマンド実行で
  "docker run -it arm64v8/debian /bin/bash" と同様になる。

  $ docker compose run my-test
  ...
  [+] Creating 1/1
   レ Network dc1_default  Created                                                                                                       
  0.2s 
  root@xxa1912a8:/# cat /etc/os-release
  PRETTY_NAME="Debian GNU/Linux 12 (bookworm)"
  NAME="Debian GNU/Linux"
  VERSION_ID="12"
  VERSION="12 (bookworm)"
  VERSION_CODENAME=bookworm
  ID=debian
  HOME_URL="https://www.debian.org/"
  SUPPORT_URL="https://www.debian.org/support"
  BUG_REPORT_URL="https://bugs.debian.org/"
  root@xxa1912a8:/# exit
  exit
  ...
  $ docker ps -a
    コンテナが残る。
 $ docker compose run --rm my-test
    でコンテナが残らない。

  $ docker compose down --remove-orphans
  docker ps -a で.yaml関連のコンテナが残っていたらこれで消える。
  残るものがある。

 ********************************************
  docker ps -a で表示されたコンテナを全部削除
  ********************************************
  $ nano rm-all
  ...
  #!/bin/sh
  for n in `docker ps -a|grep "^[0-9a-zA-Z][0-9a-fA-F]\+"| sed -e "s/[ ]\+/ /g"| cut -d ' ' -f 1`
  do
	docker stop $n
	docker rm $n
  done
  ...
  $ chmod +x rm-all

 はて?何で実行しないのと言う時, docker ps -aで確認。ポート、リソースが使われているから。
 そういう時は, ./rm-all で削除。
 =======================================================================================

 ③DockerfileありのLED点滅シングルコンテナ

   LED GPIO-5 PINに配線

   GPIO 5 --[ 510Ω ]--(▶led)-----> GND

  $ nano compose.yaml
  ...
  services:
    led2:
      build: .
      command: python3 led.py
      stdin_open: true
      tty: true
      privileged: true    # GPIO, i2c, SPIアクセスするための定義
  ...
  $ nano Dockerfile
  ...
  # base/Dockerfile
  FROM arm64v8/debian:bookworm
  RUN apt-get update
  RUN apt install -y apt-utils wget dpkg-dev
  COPY raspi.list /etc/apt/sources.list.d
  RUN wget  http://archive.raspberrypi.org/debian/raspberrypi.gpg.key
  RUN apt-key add raspberrypi.gpg.key
  RUN apt update
  RUN apt install -y raspi-utils
  RUN apt-get install -y python3 python3-gpiozero
  RUN echo "from gpiozero import LED\n\
  import time\n\
  led = LED(5)\n\
  \n\
  while(True):\n\
    led.on()\n\
    time.sleep(1)\n\
    led.off()\n\
    time.sleep(1)\n\
  " > led.py
  ...
   LED点滅プログラムは上記のものと同じ。

  $ cp /etc/apt/sources.list.d/raspi.list .

  $ docker compose run --rm led2
    LEDが点滅する。
  プログラムの終了はCTRL+C  

 ④シングルコンテナ複数実行

 .
 ├── .env
 ├── Dockerfile
 ├── compose.yaml
 ├── user1
 │      └── ユーザ1
 └── user2
        └── ユーザ2

  $ mkdir user1
  $ mkdir user1/ユーザ1
  $ mkdir user2
  $ mkdir user2/ユーザ2


 上記、自分用の環境を自動で作るDockefileでコンテナを作成する。
  $ docker build -t base .
  $ nano .env
  ...
  USER1=loginx1
  ROOT1=dXNlcjE6MDAxCg
  USER2=loginx2
  ROOT2=VVNFUjI6MDAxCg
  HOST=192.168.1.10
  U1SSH=2023              
  U2SSH=2024
  ...
  USER1,USER2,ROOT1,ROOT2は、サービス名1,2のユーザ、ルートのパスワード
 HOSTは、DOCKERホストのIPアドレス。 U1SSH,U2SSHは、サービス名1,2に割り当てるポート番号

 $ nano compose.yaml
  ...
  networks:
    mynet:
      ipam:
        config:
          - subnet: 172.20.3.0/24

  services:
    os1:
      image: base
      volumes:
       - ./user1:/home/pi/ex
      ports:
       - ${HOST}:${U1SSH}:22
      command: /bin/bash -c "echo -e \"pi:${USER1}\\nroot:${ROOT1}\" | chpasswd && /sbin/init"
      privileged: true
      restart: always
      networks:
        mynet:
          ipv4_address: 172.20.3.11

    os2:
      image: base
      volumes:
       - ./user2:/home/pi/ex
      ports:
       - ${HOST}:${U2SSH}:22
      command: /bin/bash -c "echo -e \"pi:${USER2}\\nroot:${ROOT2}\" | chpasswd && /sbin/init"
      privileged: true
      restart: always
      networks:
        mynet:
          ipv4_address: 172.20.3.22
  ...
  $ docker compose up -d
   2つコンテナが動作。

 同じか、違うPCで、
  $ ssh -p 2023 pi@192.168.1.10
   パスワード loginx1 , ポート2024は、loginx2
   raspberry pi LINUXコマンドが使える。
   cコンパイラ、pythonはインストールしてあるので使える。
  $ tree
   .           (ここは書き込んでもコンテナ停止で消える)
   └── ex       (ここ以下の書き込むと残る)
     └── ユーザ1 (どっちか判断するための名前)
  aptコマンドも使える。
   sudo poweroff してもコンテナは停止しない。

 $ docker compose down os1
   単独コンテナ停止
 $ docker compose up -d os1
   単独コンテナ起動
 $ docker compose down
   コンテナ全部停止

 コンテナ間通信をしてみる。
  コンテナイメージbaseを使って。
  $ nano compose.yaml
  ..
  services:
    netcap:
      image: base
      command: ping srv
    srv:
      image: base
      command: sleep infinity
  ..
  $ docker compose up
  ..
  Attaching to netcap-1, srv-1
  netcap-1  | PING srv (172.25.0.2) 56(84) bytes of data.
  netcap-1  | 64 bytes from dnet-srv-1.dnet_default (172.25.0.2): icmp_seq=1 ttl=64 time=0.201 ms
    ;;
  ..

 同じコンテナを起動する。
 $ nano compose.yaml
  ..
services:
  my-t1:
    image: base
    privileged: true
    ports:
     - 192.168.1.10:2025:22
    network_mode: bridge
  my-t2:
    image: base
    privileged: true
    ports:
     - 192.168.1.10:2026:22
    network_mode: bridge
  my-t3:
    image: base
    privileged: true
    ports:
     - 192.168.1.10:2027:22
    network_mode: bridge
  ..
  $ docker compose up -d
  $ docker compose ps
 NAME          IMAGE     COMMAND        SERVICE   CREATED         STATUS         PORTS
 ssh-my-t1-1   base      "/sbin/init"   my-t1     9 seconds ago   Up 8 seconds   192.168.1.10:2025->22/tcp
 ssh-my-t2-1   base      "/sbin/init"   my-t2     9 seconds ago   Up 8 seconds   192.168.1.10:2026->22/tcp
 ssh-my-t3-1   base      "/sbin/init"   my-t3     9 seconds ago   Up 8 seconds   192.168.1.10:2027->22/tcp
  $ docker inspect -f '{{.Name}} - {{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $(docker ps -aq)
  ..
  /ssh-my-t1-1 - 172.17.0.2
  /ssh-my-t3-1 - 172.17.0.4
  /ssh-my-t2-1 - 172.17.0.3
  ..
   docker run --privileged --cap-add SYS_ADMIN -ti --rm -p 192.168.1.10:2025:22 base
   docker run --privileged --cap-add SYS_ADMIN -ti --rm -p 192.168.1.10:2026:22 base
   docker run --privileged --cap-add SYS_ADMIN -ti --rm -p 192.168.1.10:2027:22 base
  3コマンドを実行したのと同じになる。
 "network_mode: bridge"がないとネットワーク周りが変わる。(Network ssh_default    Created が増える)
 他のPCより
 $ ssh -p 202x pi@192.168.1.10
   piユーザ、pidockerでログイン。
 $ sudo nft list ruleset
  を実行すると違いがわかる。

参照:https://github.com/docker/compose/issues/1259
   Docker-compose run command doesnt map ports #1259

  ++++
 $ docker run --privileged --cap-add SYS_ADMIN -ti --rm -p 192.168.1.10:8022:22 コンテナイメージ名[:タグ名]
 と同じことをdocker compose run で実行するには、

 --- compose.yaml -----
  services:
    myp:
      image: コンテナイメージ名[:タグ名]
      privileged: true
      ports:
       - 192.168.1.10:8022:22
      cap_add:
       - SYS_ADMIN
  ---
  コマンド:
 $ docker compose run -P --rm myp

  この時docker psでコンテナイメージがなく、ps -aでコンテナイメージが表示されていると、ポートが割つかない。
 $ docker compose run -P --remove-orphans --rm myp
  とするとps -a で表示されたコンテナイメージが削除された後にコンテナが実行されるようになり、
 ポートが割り当てられる。
  ++++

参照:https://stackoverflow.com/questions/38088279/communication-between-multiple-docker-compose-projects
   Communication between multiple docker-compose projects

      https://stackoverflow.com/questions/17157721/how-to-get-a-docker-containers-ip-address-from-the-host
      How to get a Docker container's IP address from the host
      より、
      $ docker inspect -f '{{.Name}} - {{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $(docker ps -aq)
      ..
      /os-os2-1 - 172.20.3.22
      /os-os1-1 - 172.20.3.11
      ..
   IPアドレスを得る。

      https://gist.github.com/natcl/3d881d00a56c8a961e6dab8ba51a5a37
      docker-compose static IP example

● DOCKERイメージのタグ表示

参考:https://stackoverflow.com/questions/28320134/how-can-i-list-all-tags-for-a-docker-image-on-a-remote-registry 
   How can I list all tags for a Docker image on a remote registry?

$ nano tags
...
#!/usr/bin/env bash
set -eu -o pipefail
docker_tags() {
    item="$1"
    case "$item" in
        */*) :;; # namespace/repository syntax, leave as is
        *) item="library/$item";; # bare repository name (docker official image); must convert to namespace/repository syntax
    esac
    authUrl="https://auth.docker.io/token?service=registry.docker.io&scope=repository:$item:pull"
    token="$(curl -fsSL "$authUrl" | jq --raw-output '.token')"
    tagsUrl="https://registry-1.docker.io/v2/$item/tags/list"
    curl -fsSL -H "Accept: application/json" -H "Authorization: Bearer $token" "$tagsUrl" | jq --raw-output '.tags[]'
}
docker_tags "$@"
...
$ chmod +x tags
$ sudo apt install jq
$ ./tags  registry
  タグ表示

● docker ファイアーウォール
 docker ホストはローカルIPでssh接続のみ許可。プライベートレジストリ登録用ポート5000は、localhost のみに開放。
 docker コンテナはコンテナ起動時のポート割当で行う。あとはコンテナ内で設定すること。

(1) dockerコンテナのファイアーウォール設定をする。

 $ nano nftables.sh 
 ....
 #!/bin/sh
 afterdkr () {
       nft insert rule ip filter DOCKER-USER ip saddr != 127.0.0.0/8 tcp dport 5000 drop 
       # プライベートレジストリをlocalhostのみ使えるようにする
 }

 n=0
 while [ $n -le 15 ]
 do
        DKRSRV=`nft list ruleset|grep 'DOCKER-USER'`
        if [ "$DKRSRV" != "" ]; then
                echo "NFT INSERT1"
                afterdkr
                exit 0
        fi
        n=`expr $n + 1`
        sleep 1
 done
 DKRSRV=`nft list ruleset|grep 'DOCKER'`
 if [ "$DKRSRV" != "" ]; then
        echo "NFT INSERT2"
        afterdkr
 fi
 ...
  $ chmod +x nftables.sh

(2) dockerサーバーが動作後、docker ホストのファイアーウォールを上書きされたあとに
  フィルタDOCKER-USER にコンテナ動作するときの制限を差し込む。
  dockerサーバーは、defaultではファイアーウォール上書き設定になっている。

(3) dockerホスト内ファイアウォール
 $ nano fw.sh
  ...
  #!/bin/sh
  DKR_HOST=192.168.1.xx  # ホストアドレス

 echo "[NFTABLES.SH] **** start ****" > /dev/kmsg
 # === initial ===
 nft flush ruleset
 # デフォルト
 # === ipv4 initial ===
 nft add table ip setwall
 nft add chain ip setwall input { type filter hook input priority 0 \; policy drop \; }
 nft add chain ip setwall callsub
 # === ipv4 set input wall ===
 nft add rule ip setwall input iifname lo accept
 nft add rule ip setwall input ct state { established, related } accept
 nft add rule ip setwall input ip protocol icmp accept
 nft add rule ip setwall input ct state invalid drop

 nft add rule ip setwall input ip daddr ${DKR_HOST} tcp dport 22 jump callsub
 nft add rule ip setwall input udp dport { 43, 53,138, 5353,123 }  accept
 #nft add rule ip setwall input log prefix \"[NFTABLES INPUT] : \"
 # --- call sub
 nft add rule ip setwall callsub 'tcp  flags & (fin|syn|rst|ack) == syn limit rate 5/second burst 5 packets counter accept'
 # ... END ...
 ...
  $ chmod +x fw.sh

(4) ファイアーウォール起動

 --- /etc/rc.local ---
  /xx/xx/fw.sh;  /xx/xx/nftables.sh &
  exit 0
  ---- 追加する
  $ sudo chmod +x /etc/rc.local
  $ sudo systemctl restart rc-local
  $ sudo reboot
2024-12-20  「ftpd インストール」
(1) vsftpd
 sudo apt install vsftpd
  sudo nano /etc/vsftpd.conf
  ...
listen=NO
listen_ipv6=YES
local_enable=YES
write_enable=YES
local_umask=022
dirmessage_enable=YES
use_localtime=YES
xferlog_enable=YES
ascii_upload_enable=YES
ascii_download_enable=YES
chroot_local_user=YES
local_root=ftp

secure_chroot_dir=/var/run/vsftpd/empty
rsa_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem
rsa_private_key_file=/etc/ssl/private/ssl-cert-snakeoil.key
ssl_enable=NO

allow_writeable_chroot=YES
#pasv_promiscuous=YES
#cmds_denied=EPSV,EPRT
pasv_min_port=3000
pasv_max_port=3010
...
  sudo systemctl restart vsftpd

 ftp サーバー ユーザルートディレクトリ ~/.ftp

 ftpクライアントは、
  $ ftp 192.xx.xx.xx
  ブラウザではFTP接続できなくなってきている。
 ファイル転送でEntering Extended Passive Modeになるのでpassive portの範囲を指定できるので
 DOCKERコンテナで使えるようになる。
 inetutils-ftpdは指定ができないのでDOCKERコンテナではつかえない。

(2) inetutils-ftpd

  sudo apt install ftpd
  sudo apt install inetutils-ftpd

  sudo nano /etc/ftpchroot
  ...

  pi
  ftpserver
  ...
   ユーザ ルートより上に cd できないユーザを設定

 sudo nano /etc/inetd.conf
  ...
  ftp             stream  tcp     nowait  root    /usr/sbin/tcpd  /usr/sbin/ftpd
  ...
   inetdで実行する場合

  sudo /usr/sbin/ftpd -4 -D
  手動実行する場合

  sudo apt install ftp
   ftp クライアントインストール
2024-12-17 「MIDIシンセサイザ」
サウンドドライバの確認方法
$ pactl info
 ...
 サーバー名: pulseaudio
 ... pulseaudioのとき
 サーバー名: PulseAudio (on PipeWire 1.2.4)
 ... pipewireのとき

サウンドフォント
/usr/share/sounds/sf2

DeskTop bookworm Arm64 image起動直後にサウンドフォントは入っていた。

/usr/share/sounds
├── sf2
│   ├── TimGM6mb.sf2
│   └── default-GM.sf2 -> /etc/alternatives/default-GM.sf2
└── sf3
    └── default-GM.sf3 -> /etc/alternatives/default-GM.sf3

タスクバーに音アイコンがなくなったら、音がでないので、
$ sudo raspi-config
  Advanced Option -> Audio Config -> PlusAudio
$ sudo reboot

 $ sudo raspi-config (pulsaudioのとき)
   Advanced Option -> Audio Config -> PlusAudio以外
 $ sudo reboot
   Advanced Option -> Audio Config -> PlusAudio
 $ sudo reboot
   2回リブート
 
(1)musescore -- MIDI 楽譜で作成ソフト

参照:https://ftp.osuosl.org/pub/musescore/handbook/MuseScore-2.0/MuseScore-ja.pdf
   日本語musescoreハンドブック2 PDF

$ sudo apt install musescore
  .midファイルを読ませると楽譜が表示される。
 ▶でプレイすると再生する。特に設定はなし。

音源は、https://musescore.com/sheetmusic
楽譜の画像をクリックしてダウンロードアイコンがウィンドウに表示されたら、
Chromeのウェブストアから、Music Score DownloaderをChromium拡張機能にインストールした
Music Score Downloader拡張機能をクリックして「Download MIDI」で.midファイルをダウンロードする。
それをmusescoreに読み込む。

/usr/share/sounds/
├── sf2
│   ├── TimGM6mb.sf2
│   └── default-GM.sf2 -> /etc/alternatives/default-GM.sf2
├── sf3
│   ├── MuseScore_General.sf3 -> /etc/alternatives/MuseScore_General.sf3
│   ├── MuseScore_General_Lite.sf3
│   └── default-GM.sf3 -> /etc/alternatives/default-GM.sf3
└── sfz

新規作成は、真っ白の楽譜をクリックして楽器を選んで楽譜を作成するか、既成楽譜を選ぶ。

(2)LMMS 音楽作成ソフト

$ sudo apt install lmms
 特に設定しなくても楽器音は出た。音が出ないときは、オーディオ設定を変えてみる。
  メニュー 編集 -> 設定 -> オーディオ設定 : Pulsaudio - default
 マウスでクリック、ドラッグで作れる。
 マイサンプル instruments piano01.ogg をソングディタウィンドウにドラッグ。
 トラックをダブルクリックでキーボードが表示されるので音階と長さをマウスで入力。
 マイサンプルウィンドウで音は聞くことができる。
 サウンドファイルにエクスポートすると再生音と同じになる。
  MIDIファイルはインポート・エクスポートできるが、エクスポートは楽器情報が付いていかないので他のMIDIソフト再生は注意。

(3)rosegarden : MIDI編集

$ sudo apt install vmpk
$ sudo apt install rosegarden

$ sudo reboot

 ①rosegarden起動
 ②vmpk起動
   vmpk -- edit -> MODI connection -> in ALSA rosegarden(2) : out SonivoxEAS

 ヴァーチャルキーボードに音源を割り当てないと曲が再生されない。
 うまく音量が制御できないとか音が出ない場合は設定、リブートを何度かやってみる。
2025-02-19 「USB SSDブート, NVMe SSD, SD card 切り替え」
参考:https://forums.raspberrypi.com/viewtopic.php?p=2198855&hilit=boot+order+gpio#p2198927
   Reducing Boot Time?

      https://www.raspberrypi.com/documentation/computers/raspberry-pi.html
      Raspberry Pi hardware
        Raspberry Pi bootloader configuration

スイッチ操作と設定の修正。

配線:
  GPIO 21,26 にオンでGNDへ接続するスイッチをつける

  GPIO-21 : ---------o/ o----> GND
  GPIO-26 : ---------o/ o----> GND

設定:
  SDカードBOOT
   GPIO-21 : ---------o/ o----> GND
   GPIO-26 : ---------o=o----> GND

  USB SSD BOOT
   GPIO-21 : ---------o=o----> GND
   GPIO-26 : ---------o/ o----> GND

  NVMe SSD BOOT
   GPIO-21 : ---------o/ o----> GND
   GPIO-26 : ---------o/ o----> GND

$ sudo rpi-eeprom-config -e
...
[all]
gpio=26=ip,pu
gpio=21=ip,pu

BOOT_UART=1
POWER_OFF_ON_HALT=1
PSU_MAX_CURRENT=5000

[gpio21=0]
BOOT_ORDER=0x4  # USB ssd
[gpio21=1]
BOOT_ORDER=0x6  # NVMe ssd

[gpio26=0]
BOOT_ORDER=0x1  # sd card
...
  (注)GPIO-26がオンの場合はGPIO-26オンが優先

$ sudo reboot

$ vcgencmd bootloader_config
  確認
[flask-window.png]
2024-12-03  「Apache + FLASK + Flask.BASIC.Auth」
Apache2、Flask , Flask・BASIC認証を使ってWEBアプリを作る。
ファイルアップロード追加。

・ディレクトリ構成
 /home/flask/
  └─f_app
     ├── application       # FLASK static directory
     │   ├── program       #  application program directory
     │   │   └── app1.py   #   application program
     │   └── upload        #  files upload directory
     ├── flask1.wsgi       # FLASK wsgi file
     ├── fmain.py          # FLASK Main program
     ├── form              # FLASK form directory
     │   ├── default.html  #  demo html
     │   └── index.html    #  opening html 
     ├── getlog.sh         #  get error log script
     ├── test.sh           #  check user mode script 
     └── test99.txt        # check UID=flask,GID=www-data
              UID,GIDがkbdb1.confで定義したユーザ、グループIDを確認すること

Raspberry Pi OS LiteはFLSKが入っていないので、
$ sudo apt install python3-flask
でインストールすること。

主な追加部分。
・・・・
html: <input type="file" name="sendfile" multiple="true" autocomplete="off" accept=".txt,.pdf">
fmain.py:
   POST後に、HTTP引数取り出し。
        POST引数リスト = request.form.to_dict(flat=False)
        POSTマルチファイルデータリスト = request.files.getlist('sendfile')
   ダウンロード。
    for file in POSTマルチファイルデータリスト:
        if file.filename == '':
            continue
        filename = file.filename
        file.save(os.path.join('/tmp', filename))
        filePath = mydir + '/' + file.filename
        newPath = cnv_name(filePath[:800])    # 長さ制限、HTML文字、'#'文字変換
        if not os.path.isdir(mydir):
            os.makedirs(mydir)          # Uploadディレクトリ作成
        shutil.move('/tmp/' + filename, newPath) # 新しい名前で移動

・・・・

・作成手順
----------- setup.sh -------------
#!/bin/bash

if [ "$1" != "" ]; then
	echo $1 > set.ini
else
	echo "0" > set.ini
fi
stp=`cat set.ini`
nxt=`expr $stp + 1`
echo $nxt > set.ini

case $stp in
10)
# ==========================================
# == FLASK ユーザ登録
# ==========================================
echo "=== ユーザ設定 ==="
echo "... flask ..."
echo "flask:nov04flask:::,,,:/home/flask:/bin/bash"|sudo newusers
# /home/flask の パーミッションビットが、rwxr-xr-xになる  
# $ sudo adduser flask コマンドでは、パーミッションビットが、rwx------になる
# adduserのあとでは、
# $ sudo chmod +x /home/flask コマンドを実行すること
#
sudo adduser flask adm
    ;;

20)
# ==========================================
# == APCHE2 INSTALL
# ==========================================
echo "apache2 install"
sudo apt install -y apache2
sudo apt install -y zip
echo "-apache2 settings"

sudo sed -i".org" -e "s/ServerTokens OS/ServerTokens Prod/" -e "s/#ServerSignature Off/ServerSignature Off/" -e "s/ServerSignature On/#ServerSignature On/" /etc/apache2/conf-enabled/security.conf

sudo systemctl enable apache2
sudo systemctl restart apache2
sudo systemctl status apache2

echo "-----APACHE TEST ---"
echo "ブラウザで確認。"
echo " http://localhost"
echo "--------------------"
echo ""
    ;;

30)
# ==========================================
# === INSTALL FLASK
# ==========================================
sudo adduser www-data adm
#               ^^^^^ ^^^ for apache2 error.log

sudo a2dissite 000-default
#              ^^^^^^^^^^^ Only flask1.conf

sudo apt install -y libapache2-mod-wsgi-py3
sudo apt install -y python3-flask-httpauth
NOTE_DIR="/home/flask"
NOTE_NAME="flask"
# ###### Flask directory #######
sudo mkdir -p ${NOTE_DIR}/f_app/
sudo mkdir -p ${NOTE_DIR}/f_app/form
sudo mkdir -p ${NOTE_DIR}/f_app/application
sudo mkdir -p ${NOTE_DIR}/f_app/application/program
# -------------------------------------
#/home/flask/
# └── f_app
#     ├── application       # FLASK static directory
#     │   ├── program       #  application program directory
#     │   │   └── app1.py   #   application program
#     │   └── upload        #  files upload directory
#     ├── flask1.wsgi       # FLASK wsgi file
#     ├── fmain.py          # FLASK Main program
#     ├── form              # FLASK form directory
#     │   ├── default.html  #  demo html
#     │   └── index.html    #  opening html 
#     ├── getlog.sh         #  get error log script
#     ├── test.sh           #  check user mode script 
#     └── test99.txt        # check UID=flask,GID=www-data
#                           # ^^^ http://localhost/who
# 
# ##########################################
# ## flask1.conf
# ##########################################
cat <<EOF | sudo tee /etc/apache2/sites-enabled/flask1.conf
<VirtualHost *:80>
    ServerAdmin webmaster@localhost
    DocumentRoot ${NOTE_DIR}/f_app
    WSGIDaemonProcess flask1 user=flask group=www-data threads=5 locale=ja_JP.UTF-8
    WSGIScriptAlias / ${NOTE_DIR}/f_app/flask1.wsgi
    WSGIPassAuthorization On
    <Directory ${NOTE_DIR}/f_app>
        WSGIProcessGroup flask1
        Options FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>

    ErrorLog \${APACHE_LOG_DIR}/error.log
    CustomLog \${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
EOF
# ##########################################
# ## flask1.wsgi
# ##########################################
sudo cp flask1.wsgi ${NOTE_DIR}/f_app

# ##########################################
# ###### fmain.py #######
# ##########################################
sudo cp fmain.py ${NOTE_DIR}/f_app/fmain.py
sudo cp app1.py ${NOTE_DIR}/f_app/application/program

# ##########################################
# ###### form/index.html #######
# ##########################################
sudo cp index.html ${NOTE_DIR}/f_app/form

# ##########################################
# ###### ./test.sh #######
# ##########################################
sudo cp default.html ${NOTE_DIR}/f_app/form

# ##########################################
# ###### ./test.sh #######
# ##########################################
sudo cp test.sh ${NOTE_DIR}/f_app

# ##########################################
# ###### getlog.sh #######
# ##########################################
sudo cp getlog.sh ${NOTE_DIR}/f_app

sudo chown -R ${NOTE_NAME}:${NOTE_NAME} ${NOTE_DIR}/f_app
sudo adduser flask www-data
sudo systemctl restart apache2
    ;;


100)
# ==========================================
# === List FLASK
# ==========================================
NOTE_DIR="/home/flask"

echo "%%%%%%%%%%%%%%% flask1.wsgi %%%%%%%%%%%%%%%%%%"
cat ${NOTE_DIR}/f_app/flask1.wsgi
echo ""
echo "%%%%%%%%%%%%%%% fmain.py %%%%%%%%%%%%%%%%%%"
cat ${NOTE_DIR}/f_app/fmain.py
echo ""
echo "%%%%%%%%%%%%%%% app1.py %%%%%%%%%%%%%%%%%%"
cat ${NOTE_DIR}/f_app/application/program/app1.py
echo ""
echo "%%%%%%%%%%%%%%% index.html %%%%%%%%%%%%%%%%%%"
cat ${NOTE_DIR}/f_app/form/index.html
echo ""
echo "%%%%%%%%%%%%%%% default.html %%%%%%%%%%%%%%%%%%"
cat ${NOTE_DIR}/f_app/form/default.html
echo ""
echo "%%%%%%%%%%%%%%% test.sh %%%%%%%%%%%%%%%%%%"
cat ${NOTE_DIR}/f_app/test.sh
echo ""
echo "%%%%%%%%%%%%%%% getlog.sh %%%%%%%%%%%%%%%%%%"
cat ${NOTE_DIR}/f_app/getlog.sh
echo ""
	;;
*)
	echo "none"
     ;;
esac
exit 0

ーーー ファイル一式 ーーーーー
%%%%%%%%%%%%%%% flask1.wsgi %%%%%%%%%%%%%%%%%%
#!/usr/bin/python
import sys
import logging
logging.basicConfig(stream=sys.stderr)
sys.path.insert(0,"/home/flask/f_app/")

from fmain import app as application

%%%%%%%%%%%%%%% fmain.py %%%%%%%%%%%%%%%%%%
#! /bin/usr/python

from flask import Flask,request,flash
from flask import render_template
from flask_httpauth import HTTPBasicAuth
from werkzeug.security import generate_password_hash, check_password_hash
import os
from subprocess import check_output
import subprocess
import application.program.app1 as appx

app = Flask(__name__, static_folder='application', template_folder='form')
auth = HTTPBasicAuth()

users = { "gozira": generate_password_hash("kingkong"),
          "tiger": generate_password_hash("doragon") }
do_dir = os.path.dirname(__file__)

@auth.verify_password
def verify_password(username, password):
    if username in users and \
            check_password_hash(users.get(username), password):
        return username

@app.route("/<string:path>")
@app.route("/<path:path>")
@app.route("/application/program/<path:path>")
@app.route('/')
def hello(path=None):
    return render_template('index.html',acomment=path)

@app.route('/open')
@auth.login_required
def homepage():
    bf = ['']
    appx.ddir(bf, do_dir + '/application/upload')
    return render_template('default.html',flist=bf[0])

@app.route('/who')
def whoami():
    cmd = do_dir + "/test.sh"
    result = subprocess.run(cmd,  stderr=subprocess.STDOUT, stdout=subprocess.PIPE, shell=True)
    return(result.stdout.decode('utf-8'))

@app.route("/get-req")
def get_request():
    prm = request.args.to_dict()
    retrn = "<html><body><pre>" + str(request.url) + chr(0x0a) + str(request.host_url) + chr(0x0a) + "</pre>"
    for k in prm:
        data = prm.get(k)
        if data != None:
            retrn += "P["+k+"]=" + str(data) + "<br>"
    retrn += "<br>config<br>"
    for k in app.config:
        retrn += k + "=" + str(app.config.get(k)) + "<br>"
    retrn += "<hr>"
    for x in os.environ:
        retrn += x + "= " + os.getenv(x) + "<br>"
    retrn += "<hr>"
    for x in app.config:
        retrn += str(x) + "= " + str(app.config[x]) + "<br>"
    retrn += "</body></html>"
    return retrn

@app.errorhandler(500)
@app.errorhandler(400)
@app.errorhandler(401)
@app.errorhandler(403)
@app.errorhandler(404)
def not_found(e):
    import re
    rhtml = """<!doctype html><html><html lang="ja"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">"""
    rhtml += "<title>"
    rhtml += str(e.code)
    rhtml += """</title><body><h1 style="color:red">"""
    rhtml += str(e.code)
    rhtml += """エラーが発生しました??</h1><br><h3 style="color:bule">"""
    rhtml += e.name
    rhtml += "</h3>"
    rhtml += request.url
    rhtml += "<hr>"
    prm = request.args.to_dict()
    for k in prm:
        rhtml += "[" + k + "]:" + prm.get(k) + "<br>"
    if e.code == 500:
        rhtml += "<hr>"
        cmd = do_dir + "/getlog.sh"
        elog = check_output(cmd,stderr=subprocess.STDOUT,shell=True)
        rhtml += elog.decode('utf-8',errors='replace').replace('\n','<br>')
    rhtml += "<br></body></html>"
    return rhtml,e.code

@app.route('/e40x')
def e40x():
    rhtml = """<!doctype html><html><html lang="ja"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">"""
    rhtml += "<title>Not Access</title><body><h1 style=\"color:red\">アクセスできません。</h1></body></html>"
    return rhtml

@app.route('/function/<name>',methods=['GET', 'POST'])
@auth.login_required
def call_subr(name):
    subcall = {'あいさつ':appx.aisatu,'あさ':appx.asa,'ゆうがた':appx.yuugata,
               'たのしい':appx.tanosi, 'これで':appx.korede,'おわり':appx.owari }

    if request.method == 'POST':
        prm = request.form.to_dict(flat=False)
        files = request.files.getlist('sendfile')
    else:
        prm = request.args.to_dict(flat=False)
    if name in subcall:
        if name == 'たのしい':
            return appx.tanosi(prm,files,do_dir + '/application/upload')
        return subcall[name](prm)
    else:
        return "関数:"+name+"なし"

@app.route('/logout')
def logout():
    auth = request.authorization
    if auth == None:
        return "ログアウト"
    else:
        return "LogOut, {}!".format(auth.username), 401

if __name__ == "__main__":
   app.run(host='0.0.0.0', port=5050)

%%%%%%%%%%%%%%% app1.py %%%%%%%%%%%%%%%%%%
#! /bin/usr/python

from werkzeug.utils import secure_filename
import os
import shutil

def cnv_name(s):
    nsf = s.replace('&','[ap]')
    nsf = nsf.replace('<','[lt]')
    nsf = nsf.replace('>','[gt]')
    nsf = nsf.replace('"','[qu]')
    nsf = nsf.replace('%22','[=]')
    nsf = nsf.replace('+','[2B]')
    nsf = nsf.replace('#','[23]')
    nsf = nsf.replace('`','[vq]')
    nsf = nsf.replace("'",'[sq]')
    nsf = nsf.replace('~','[ch]')
    return nsf

def Aprint(buf, strtxt):
    buf[0] += strtxt

def ddir(bf, mydir):
    if not os.path.isdir(mydir):
        os.makedirs(mydir)
    Aprint(bf, '<br>========<br>ファイル一覧<br>========<br>')
    for f in os.listdir(mydir):
        if os.path.isfile(os.path.join(mydir, f)):
            fsiz = os.path.getsize(os.path.join(mydir, f))
            if fsiz >= 1024:
                ss = "(%.1f KB)" % ((fsiz+103)/1024)
            else:
                ss = "(%d B)" % (fsiz)
            Aprint(bf, '<a href="/application/upload/' + f + '" target="_blanck" >['+f+ss+']</a><br>')

def btn():
    return "<br><br><button style=\"background-color: cyan;\" type=\"button\"  onclick=\"location.href='/open'\">戻   る</button><br><br><button style=\"background-color: yellow;\" type=\"button\"  onclick=\"location.href='/logout'\">ログアウト</button>"

def aisatu(p):
    return "はじめまして" + btn()

def asa(p):
    return "おはよう" + btn()

def yuugata(p):
    return "こんばんは" + btn()

def tanosi(p, files, mydir):
    for file in files:
        if file.filename == '':
            continue
        filename = file.filename
        file.save(os.path.join('/tmp', filename))
        filePath = mydir + '/' + file.filename
        newPath = cnv_name(filePath[:800])
        if not os.path.isdir(mydir):
            os.makedirs(mydir)
        shutil.move('/tmp/' + filename, newPath)

    retrn = '<pre>'
    for k in p:
        data = p.get(k)
        if data != None:
            retrn += "P["+k+"]:\n" + data[0] + "\n"
    bf = ['']
    ddir(bf, mydir)
    return retrn + bf[0] + "\nいいね !</pre>" + btn()

def korede(p):
   return "こんなんじゃ、もうおわりだ" + btn()

def owari(p):
    return "さようなら" + btn()

%%%%%%%%%%%%%%% index.html %%%%%%%%%%%%%%%%%%
<html>
<head>
<style type='text/css'>
<!--
body {
     margin:0px;
     padding:10px;
     text-align:center;
}
hr { width: 500px; }
-->
</style>
</head>
<body>
<h1>Welcome to My FLASK Server.</h1>

<form action="/open" method="get">
<p>BASIC認証を使ってみる</p>
<p>User: tiger, gozira</p>
<a href="/open"><input type="button" value="認   証"></a>
<p>
  {% if acomment %}
<br>こちらは見れません:{{ acomment | safe }}<br>
  {% endif %}
</p>
<hr>
<a href='/logout'><input style="background-color: yellow;" type="button" value="ログアウト"></a> 
</body>
</html>

%%%%%%%%%%%%%%% default.html %%%%%%%%%%%%%%%%%%
<!doctype html>
<html lang=ja>
<head>
<meta http-equiv='Content-Type' content='text/html; charset=UTF-8'>
<style type='text/css'>
<!--
body {
     margin: 0px;
     padding:0px;
     text-align:center;
}
.menu00 { text-align: right; margin: 5px; padding: 50px 5px 5px;}
.body00 { width: 70%; }
.main{ width: 800px; display: flex;}
h1, h3 { margin: auto;padding: 10px}
h1 { color: orange; }
h3 { color: blue; }
menu { list-style-type: none;}
li { witdh: 40px; margin: 10px;}
.menuX { background-color: cyan; }
.menuE { background-color: yellow; }
label { margin: 0; padding: 0;}
-->
</style>
<title>メイン</title>
</head>
<body style="width: 800px; margin: auto;">
<div class='main'>
 <div class='menu00'>
メニュー&emsp;  
  <menu>
  <li><button class="menuX" type="button"  onclick="location.href='/function/あいさつ'">挨   拶</button></li>
  <li><button class="menuX" type="button"  onclick="location.href='/function/あさ'">朝 で す</button></li>
  <li><button class="menuX" type="button"  onclick="location.href='/function/ゆうがた'">夕   方</button></li>
  <li><button class="menuX" type="button"  onclick="location.href='/function/これで'">どうした </button></li>
  <li><button class="menuX" type="button"  onclick="location.href='/function/おわり'">や め た</button></li>
  <li><button class="menuE" type="button"  onclick="location.href='/logout'">ログアウト</button></li>
  </menu>
 </div>
 <div class='body00'>
<h1>FLASK Server.</h1>
<h3>コメント</h3>
  <div style="display: inline-table;">
    <form method="post" action="/function/たのしい" enctype="multipart/form-data">
      <div style="display: inline-table;">
        <textarea name="comment" cols="90%"  rows="8"></textarea>
        <div style="display: flex;  justify-content: center; align-items: center;">
評価: <label><input type="radio" name="iiwaru" value="yoi">良かった</label>
             <label><input type="radio" name="iiwaru" value="futuu">普通</label>
             <label><input type="radio" name="iiwaru" value="warui">悪い</label>
        </div>
<p>添付ファイル(*.txt,*.pdf) <input type="file" name="sendfile" multiple="true" autocomplete="off" accept=".txt,.pdf"> コメント<input type="submit" value="送信"></p>
      </div>
    </form>
  </div>
  {% if flist %}
{{ flist | safe }}
  {% endif %}
 <div>
</div>
</body>
</html>

%%%%%%%%%%%%%%% test.sh %%%%%%%%%%%%%%%%%%
#!/bin/sh
echo "<!DOCTYPE html>"
echo "<html lang=ja>"
echo "<head>"
echo "<meta http-equiv='Content-Type' content='text/html; charset=UTF-8'>"
echo "<title>わお!</title>"
echo "</head>"
echo "<body>"
DATA=`whoami`
echo "<H1>user : $DATA</h1>"
WDIR=$(dirname -- "$0")
echo $DATA > ${WDIR}/test99.txt
echo "</body>"
echo "</html>"

%%%%%%%%%%%%%%% getlog.sh %%%%%%%%%%%%%%%%%%
#!/bin/sh
tail -n 10 /var/log/apache2/error.log
exit 0
2024-10-03  「行列式計算2」
順列と入れ替え回数計算を使って、行列式計算を公式どうりにやってみた。
行列が大きくなると遅いです。

参照:
数学ターミナル 新訂2版 線型代数の発想 小林幸夫 著 現代数学社 2008,2020,2023
1.6.2 行列式関数の性質 行列式関数detの定義
   その他、行列式に関する本より。

初等線形代数 --考え方と応用プログラム 石原辰雄・長谷川勝也 著 共立出版 1986,1988
       DET.DET

[改定新版]C言語による標準アルゴリズム事典 奥村晴彦著 技術評論社 1991,2018
       順列 nextperm()

https://ikatakos.com/pot/programming_algorithm/dynamic_programming/inversion
転倒数
========

実行:

実行結果: 答 = det_det() - 行列式計算
  参照:数学ターミナル 新訂2版 線型代数の発想 小林幸夫 著 現代数学社 2008,2020,2023
       1.6.2 行列式関数の性質 行列式関数detの定義
  参照:初等線形代数 --考え方と応用プログラム 石原辰雄・長谷川勝也 著 共立出版 1986,1988
       DET.DET
  参照:[改定新版]C言語による標準アルゴリズム事典 奥村晴彦著 技術評論社 1991,2018
       順列 nextperm()
  その他、行列式に関する本より。
  参照:https://ikatakos.com/pot/programming_algorithm/dynamic_programming/inversion
         転倒数
....

--- 行列計算 --- test-1
## 入力: ##
[[     5 ]]
ランク(A): 1  ,  1 x 1  行列
My det():  5.0000
Numpy det(): OK

--- 行列計算 --- test-2
## 入力: ##
[[     4     3 ]
 [     1     3 ]]
ランク(A): 2  ,  2 x 2  行列
My det():  9.0000
Numpy det(): OK

--- 行列計算 --- test-3
## 入力: ##
[[     0    -2     0 ]
 [    -1     5     2 ]
 [     0    -1     1 ]]
ランク(A): 3  ,  3 x 3  行列
My det(): -2.0000
Numpy det(): OK

--- 行列計算 --- test-4
## 入力: ##
[[     1    -1    -1 ]
 [    -1     1    -1 ]
 [    -1    -1     1 ]]
ランク(A): 3  ,  3 x 3  行列
My det(): -4.0000
Numpy det(): OK

--- 行列計算 --- test-5
## 入力: ##
[[     7     2    -4     2     3 ]
 [     1     5     2     0     3 ]
 [    -5    -6     3     1     2 ]
 [     0     2     7     4     3 ]
 [     4     2    -5    -3     5 ]]
ランク(A): 5  ,  5 x 5  行列
My det(): -2346.0000
Numpy det(): OK

--- 行列計算 --- test-6
## 入力: ##
[[     1     3     9 ]
 [    -1     1    -1 ]
 [     2    -4    -2 ]]
ランク(A): 2  ,  3 x 3  行列
My det():  0.0000
Numpy det(): OK

--- 行列計算 --- test-7
## 入力: ##
[[     1     9     2    12 ]
 [     3     2     5    10 ]
 [     2    -1     6     7 ]
 [     0     6     1     7 ]]
ランク(A): 3  ,  4 x 4  行列
My det():  0.0000
Numpy det(): OK

--- 行列計算 ---  生成行列 - 1 : 9 x 9 
## 入力: ##
[[   2.2    -1   3.3    -4    -5  -0.5   3.8  -4.2  -4.7 ]
 [   0.8    -4   0.7  -3.6   2.1  -4.9  -0.5   1.6   1.8 ]
 [  -0.5   3.2   4.8   2.8   0.7  -3.2  -4.9   2.9  -0.2 ]
 [   4.1   4.9  -2.5   4.1  -4.9  -0.4   2.8  -2.4     5 ]
 [   3.6  -0.7   4.5  -2.1   2.9  -1.8  -0.1   3.2   4.4 ]
 [   2.4  -3.2  -4.8     4  -1.6  -2.9   2.3   1.3  -0.5 ]
 [  -2.4    -1  -4.5   2.2     5   1.2    -5  -2.4   3.4 ]
 [   0.7  -2.6   3.2  -3.5   0.4   2.1   0.4    -2   3.6 ]
 [   0.1  -1.8   2.7   0.1  -4.6  -3.3   0.6    -4   1.5 ]]
ランク(A): 9  ,  9 x 9  行列
My det():  5497274.1853
Numpy det(): OK

--- 行列計算 ---  生成行列 - 2 : 8 x 8 
## 入力: ##
[[  -0.6  -1.1     5   4.4  -1.7   2.4     4   2.3 ]
 [     2   2.5   3.9   1.9   3.2  -4.8  -3.9  -3.9 ]
 [   1.4   2.6  -0.9  -4.2   1.6  -0.3   4.2   1.9 ]
 [   3.5  -2.6  -3.2   0.1  -1.3     0   1.2   3.6 ]
 [   1.4  -4.3  -3.5  -0.8  -2.2   0.6   3.1  -4.7 ]
 [  -2.6   4.6   0.2     5  -2.9   3.5   1.6   3.7 ]
 [   1.5  -1.9  -2.8   0.8  -3.6   1.3    -3  -1.2 ]
 [  -2.3  -3.7  -2.5   4.6   3.9  -0.2   0.7   3.3 ]]
ランク(A): 8  ,  8 x 8  行列
My det():  655590.1626
Numpy det(): OK

--- 行列計算 ---  生成行列 - 3 : 8 x 8 
## 入力: ##
[[     5   3.9     5   0.4  -2.4   4.3  -2.1   0.7 ]
 [  -4.3  -3.4   4.6   0.4  -0.4  -1.5     0  -1.3 ]
 [  -0.9  -3.5   1.9   0.1  -0.6  -0.2  -4.9     0 ]
 [  -3.3  -4.7   4.8  -1.1     2   1.9  -1.9  -4.3 ]
 [   3.2  -2.8  -1.3   2.9   1.4  -2.4   2.4     5 ]
 [   1.8   3.9  -4.4  -3.8   2.1  -2.6    -3  -0.4 ]
 [  -4.8   3.1   0.9  -0.1  -0.5   0.1  -3.3   1.2 ]
 [    -5   2.4    -3   2.4   3.5  -4.8  -0.5   3.7 ]]
ランク(A): 8  ,  8 x 8  行列
My det():  619456.4268
Numpy det(): OK
.......................

プログラム:
-------------- matrix2.py ------------------
"""
https://ikatakos.com/pot/programming_algorithm/dynamic_programming/inversion
転倒数
"""
def get_sgn(Z):
    cnt = 0
    n = len(Z)
    for i in range(1,n):
        for j in range(i+1,n):
            if Z[i] > Z[j]:
                cnt += 1
    return (-1)**(cnt&1)

"""
[改定新版]C言語による標準アルゴリズム事典 奥村晴彦著 技術評論社 1991,2018
  順列 nextperm()
"""
def nextperm(mP):
    """
     順列生成
    """
    N = len(mP) - 1
    i = N - 1
    mP[0] = 0
    while mP[i] >= mP[i+1]:
        i -= 1
    if i == 0:
        return 0
    j = N
    while mP[i] >= mP[j]:
        j -= 1
    t = mP[i]
    mP[i] = mP[j]
    mP[j] = t
    i += 1
    j = N
    while i < j:
        t = mP[i]
        mP[i] = mP[j]
        mP[j] = t
        i += 1
        j -= 1
    return 1

"""
数学ターミナル 新訂2版 線型代数の発想 小林幸夫 著 現代数学社 2008,2020,2023
1.6.2 行列式関数の性質 行列式関数detの定義

初等線形代数 --考え方と応用プログラム
  石原辰雄・長谷川勝也 著      共立出版 1986,1988
 DET.DET

その他、行列式に関する本より。
"""
def det_det(A):
    """
    行列式計算
    """
    #        x = N! 
    #          +--  +-- 
    #           \   \
    #            \  /  A[1][Q[1]] * A[2][Q[2] * ... * A[n][Q[n]] * sgn(Q)
    #   Det  =   /  +--
    #           /   Q = Z[x]
    #          +-- 
    #        N次順列 --> Z[N!] = [[1, 2, 3],[1, 3, 2],[2, 1, 3],[2, 3, 1],[3, 1, 2], [3, 2, 1]]
    #         x = 0           例えば3の場合、p[6][3]の配列となる
    #  
    
    n = len(A)
    Q = [ _ for _ in range(n+1)]  # 順列初期値
    det = 0
    while True:
        d = 1
        for j in range(n):
            d *= A[j][Q[j+1]-1]
        d *= get_sgn(Q)
        det += d
        if nextperm(Q) == 0:
            break
    return det

def gen_matrix(n=0, RMAX=50, DCP=-1):
    '''
        行列生成 N x N
          n = 0 : ランダムNxN , 9 : 9 x 9行列
          RMAX = 50 : (+-50)で要素データ、 99: (+-99)で要素データ
          DCP = 1 : 要素データ * 10,  +9 : 要素データ * (10**9) 、 -9 : 要素データ / (10**9)
    '''
    import random as r

    DC = 10**abs(DCP)
    if n == 0:
        N = r.randrange(4,10)  # 4x4 ~ 9x9の行列を作る
    else:
        N = n                  # n x n の行列を作る
    m = []
    for i in range(N):
        m.append([r.randrange(-RMAX,RMAX+1) for j in range(N)])
    for i in range(N):
        for j in range(N):
            if DCP < 0:
                m[i][j] /= DC
            else:
                m[i][j] *= DC
    return m

def pmatrix(msg, MAT):
    '''
     行列の印刷
    '''
    print("##",msg,"##")
    if MAT is None:
        print("  結果がありません")
        return
    n = len(MAT)
    m = len(MAT[0])
    for i in range(n):
        if i == 0:
            print("[[",end='')
        else:
            print(" [",end='')
        for j in range(m):
            print(" % 5.4g" % (MAT[i][j]), end='')
        if i == (n-1):
            print(" ]]")
        else:
            print(" ]")

# ##################################
if __name__ == '__main__':
    import numpy as np

    def p_header():
        print("実行結果: 答 = det_det() - 行列式計算")
        print("  参照:数学ターミナル 新訂2版 線型代数の発想 小林幸夫 著 現代数学社 2008,2020,2023")
        print("       1.6.2 行列式関数の性質 行列式関数detの定義")
        print("  参照:初等線形代数 --考え方と応用プログラム 石原辰雄・長谷川勝也 著 共立出版 1986,1988")
        print("       DET.DET")
        print("  参照:[改定新版]C言語による標準アルゴリズム事典 奥村晴彦著 技術評論社 1991,2018")
        print("       順列 nextperm()")
        print("  その他、行列式に関する本より。")
        print("  参照:https://ikatakos.com/pot/programming_algorithm/dynamic_programming/inversion")
        print("         転倒数")
        print("....")

    def ematrix(A):
        la = np.linalg.matrix_rank(A)
        print("ランク(A):",la, " , ",len(A) , "x",len(A[0])," 行列")

    def test(msg, A):
        print('')
        print("--- 行列計算 ---", msg)
        pmatrix("入力:",A)
        ematrix(A)
        mydet = det_det(A)
        print("My det(): % 5.4f" % (mydet))     
        ndet = np.linalg.det(A)
        if np.allclose(ndet,mydet):
            print("Numpy det(): OK")
        else:
            print("Numpy det(): NG??", ndet)

    p_header()
    test("test-1",[[5]])
    test("test-2",[[4,3],[1,3]])
    test("test-3",[[0,-2,0],[-1,5,2],[0,-1,1]])
    test("test-4",[[1,-1,-1],[-1,1,-1],[-1,-1,1]])
    test("test-5",[[7,2,-4,2,3],[1,5,2,0,3],[-5,-6,3,1,2],[0,2,7,4,3],[4,2,-5,-3,5]])
    test("test-6",[[1,3,9],[-1,1,-1],[2,-4,-2]])
    test("test-7",[[1,9,2,12],[3,2,5,10],[2,-1,6,7],[0,6,1,7]])
    #
    # マトリックスがおおきいとdet_det()遅い
    #
    for mi in range(1,4):
        mm = gen_matrix()
        mn = len(mm)
        m1 = " 生成行列 - %d : %d x %d " % (mi, mn, mn)
        test(m1, mm)
2024-09-18  「順列生成」
行列計算で順列生成が必要になったので検索してみた。
結構な種類が見つかった。
なかでも書く行数が少ないもの。

参照:
https://stackoverflow.com/questions/104420/how-do-i-generate-all-permutations-of-a-list/
How do I generate all permutations of a list?


実行:
実行結果: 順列 = permutations() - 順列生成
  参照:https://stackoverflow.com/questions/104420/how-do-i-generate-all-permutations-of-a-list/
         How do I generate all permutations of a list?
....
Python itertools.permutations() ["◁","△","▽","▷"]
('◁', '△', '▽', '▷')
('◁', '△', '▷', '▽')
('◁', '▽', '△', '▷')
('◁', '▽', '▷', '△')
('◁', '▷', '△', '▽')
('◁', '▷', '▽', '△')
('△', '◁', '▽', '▷')
('△', '◁', '▷', '▽')
('△', '▽', '◁', '▷')
('△', '▽', '▷', '◁')
('△', '▷', '◁', '▽')
('△', '▷', '▽', '◁')
('▽', '◁', '△', '▷')
('▽', '◁', '▷', '△')
('▽', '△', '◁', '▷')
('▽', '△', '▷', '◁')
('▽', '▷', '◁', '△')
('▽', '▷', '△', '◁')
('▷', '◁', '△', '▽')
('▷', '◁', '▽', '△')
('▷', '△', '◁', '▽')
('▷', '△', '▽', '◁')
('▷', '▽', '◁', '△')
('▷', '▽', '△', '◁')
%%%%.. テスト1  順列生成 ..%%%%
入力: [[0, 0, 3], [1, 5, 2], [0, 1, 0]]
順列:
No.  1 -  [[0, 0, 3], [1, 5, 2], [0, 1, 0]]
No.  2 -  [[0, 0, 3], [0, 1, 0], [1, 5, 2]]
No.  3 -  [[1, 5, 2], [0, 0, 3], [0, 1, 0]]
No.  4 -  [[1, 5, 2], [0, 1, 0], [0, 0, 3]]
No.  5 -  [[0, 1, 0], [1, 5, 2], [0, 0, 3]]
No.  6 -  [[0, 1, 0], [0, 0, 3], [1, 5, 2]]
%%%%.. テスト2  順列生成 ..%%%%
入力: [[0, 0, 3], [1, 5, 2], [0, 1, 0]]
順列:
No.  1 -  [[0, 0, 3], [1, 5, 2], [0, 1, 0]]
No.  2 -  [[0, 0, 3], [0, 1, 0], [1, 5, 2]]
No.  3 -  [[1, 5, 2], [0, 0, 3], [0, 1, 0]]
No.  4 -  [[1, 5, 2], [0, 1, 0], [0, 0, 3]]
No.  5 -  [[0, 1, 0], [0, 0, 3], [1, 5, 2]]
No.  6 -  [[0, 1, 0], [1, 5, 2], [0, 0, 3]]
%%%%.. テスト3  順列生成 ..%%%%
入力: [[0, 0, 3], [1, 5, 2], [0, 1, 0]]
順列:
No.  1 -  [[0, 0, 3], [1, 5, 2], [0, 1, 0]]
No.  2 -  [[1, 5, 2], [0, 0, 3], [0, 1, 0]]
No.  3 -  [[1, 5, 2], [0, 1, 0], [0, 0, 3]]
No.  4 -  [[0, 0, 3], [0, 1, 0], [1, 5, 2]]
No.  5 -  [[0, 1, 0], [0, 0, 3], [1, 5, 2]]
No.  6 -  [[0, 1, 0], [1, 5, 2], [0, 0, 3]]
%%%%.. テスト6  順列生成 ..%%%%
入力: 123
順列:
No.  1 -  ['1', '2', '3']
No.  2 -  ['2', '1', '3']
No.  3 -  ['2', '3', '1']
No.  4 -  ['1', '3', '2']
No.  5 -  ['3', '1', '2']
No.  6 -  ['3', '2', '1']
%%%%.. テスト7  順列生成 ..%%%%
入力: ABC
順列:
No.  1 -  ['A', 'B', 'C']
No.  2 -  ['B', 'A', 'C']
No.  3 -  ['B', 'C', 'A']
No.  4 -  ['A', 'C', 'B']
No.  5 -  ['C', 'A', 'B']
No.  6 -  ['C', 'B', 'A']
%%%%.. テスト8  順列生成 ..%%%%
入力: ['◁', '△', '▽', '▷']
順列:
No.  1 -  ['◁', '△', '▽', '▷']
No.  2 -  ['◁', '△', '▷', '▽']
No.  3 -  ['◁', '▽', '△', '▷']
No.  4 -  ['◁', '▽', '▷', '△']
No.  5 -  ['◁', '▷', '▽', '△']
No.  6 -  ['◁', '▷', '△', '▽']
No.  7 -  ['△', '◁', '▽', '▷']
No.  8 -  ['△', '◁', '▷', '▽']
No.  9 -  ['△', '▽', '◁', '▷']
No. 10 -  ['△', '▽', '▷', '◁']
No. 11 -  ['△', '▷', '▽', '◁']
No. 12 -  ['△', '▷', '◁', '▽']
No. 13 -  ['▽', '△', '◁', '▷']
No. 14 -  ['▽', '△', '▷', '◁']
No. 15 -  ['▽', '◁', '△', '▷']
No. 16 -  ['▽', '◁', '▷', '△']
No. 17 -  ['▽', '▷', '◁', '△']
No. 18 -  ['▽', '▷', '△', '◁']
No. 19 -  ['▷', '△', '▽', '◁']
No. 20 -  ['▷', '△', '◁', '▽']
No. 21 -  ['▷', '▽', '△', '◁']
No. 22 -  ['▷', '▽', '◁', '△']
No. 23 -  ['▷', '◁', '▽', '△']
No. 24 -  ['▷', '◁', '△', '▽']
%%%%.. テスト9  順列生成 ..%%%%
入力: ['◁', '△', '▽', '▷']
順列:
No.  1 -  ['◁', '△', '▽', '▷']
No.  2 -  ['◁', '△', '▷', '▽']
No.  3 -  ['◁', '▽', '△', '▷']
No.  4 -  ['◁', '▽', '▷', '△']
No.  5 -  ['◁', '▷', '△', '▽']
No.  6 -  ['◁', '▷', '▽', '△']
No.  7 -  ['△', '◁', '▽', '▷']
No.  8 -  ['△', '◁', '▷', '▽']
No.  9 -  ['△', '▽', '◁', '▷']
No. 10 -  ['△', '▽', '▷', '◁']
No. 11 -  ['△', '▷', '◁', '▽']
No. 12 -  ['△', '▷', '▽', '◁']
No. 13 -  ['▽', '◁', '△', '▷']
No. 14 -  ['▽', '◁', '▷', '△']
No. 15 -  ['▽', '△', '◁', '▷']
No. 16 -  ['▽', '△', '▷', '◁']
No. 17 -  ['▽', '▷', '◁', '△']
No. 18 -  ['▽', '▷', '△', '◁']
No. 19 -  ['▷', '◁', '△', '▽']
No. 20 -  ['▷', '◁', '▽', '△']
No. 21 -  ['▷', '△', '◁', '▽']
No. 22 -  ['▷', '△', '▽', '◁']
No. 23 -  ['▷', '▽', '◁', '△']
No. 24 -  ['▷', '▽', '△', '◁']
%%%%.. テスト10  順列生成 ..%%%%
入力: ['◁', '△', '▽', '▷']
順列:
No.  1 -  ['◁', '△', '▽', '▷']
No.  2 -  ['△', '◁', '▽', '▷']
No.  3 -  ['△', '▽', '◁', '▷']
No.  4 -  ['△', '▽', '▷', '◁']
No.  5 -  ['◁', '▽', '△', '▷']
No.  6 -  ['▽', '◁', '△', '▷']
No.  7 -  ['▽', '△', '◁', '▷']
No.  8 -  ['▽', '△', '▷', '◁']
No.  9 -  ['◁', '▽', '▷', '△']
No. 10 -  ['▽', '◁', '▷', '△']
No. 11 -  ['▽', '▷', '◁', '△']
No. 12 -  ['▽', '▷', '△', '◁']
No. 13 -  ['◁', '△', '▷', '▽']
No. 14 -  ['△', '◁', '▷', '▽']
No. 15 -  ['△', '▷', '◁', '▽']
No. 16 -  ['△', '▷', '▽', '◁']
No. 17 -  ['◁', '▷', '△', '▽']
No. 18 -  ['▷', '◁', '△', '▽']
No. 19 -  ['▷', '△', '◁', '▽']
No. 20 -  ['▷', '△', '▽', '◁']
No. 21 -  ['◁', '▷', '▽', '△']
No. 22 -  ['▷', '◁', '▽', '△']
No. 23 -  ['▷', '▽', '◁', '△']
No. 24 -  ['▷', '▽', '△', '◁']


プログラム:
--------------permute.py -----------
"""
https://stackoverflow.com/questions/104420/how-do-i-generate-all-permutations-of-a-list/
How do I generate all permutations of a list?
"""
# -1-
def permute(xs, low=0):
    if low + 1 >= len(xs):
        yield xs
    else:
        for p in permute(xs, low + 1):
            yield p        
        for i in range(low + 1, len(xs)):        
            xs[low], xs[i] = xs[i], xs[low]
            for p in permute(xs, low + 1):
                yield p        
            xs[low], xs[i] = xs[i], xs[low]

# -2-
def permutList(l):
    if not l:
            return [[]]
    res = []
    for e in l:
            temp = l[:]
            temp.remove(e)
            res.extend([[e] + r for r in permutList(temp)])

    return res

# -3-
def addperm(x,l):
    return [ l[0:i] + [x] + l[i:]  for i in range(len(l)+1) ]

def perm(l):
    if len(l) == 0:
        return [[]]
    return [x for y in perm(l[1:]) for x in addperm(l[0],y) ]

# ##################################################
if __name__ == '__main__':
    import itertools

    def p_header():
        print("実行結果: 順列 = permutations() - 順列生成")
        print("  参照:https://stackoverflow.com/questions/104420/how-do-i-generate-all-permutations-of-a-list/")
        print("         How do I generate all permutations of a list?")
        print("....")

    f_permutation = ( permute, permutList, perm)

    def test(f, msg, mL):
        print("%%%%..",msg," 順列生成 ..%%%%")
        print("入力:",mL)
        print("順列:")
        c = 1
        for p in f_permutation[f](mL):
            print("No.%3d - " % (c),p)
            c += 1

    p_header()
    print('Python itertools.permutations() ["◁","△","▽","▷"]') 
    for v  in itertools.permutations(["◁","△","▽","▷"]): print(v)
    test(0,"テスト1",[[0,0,3],[1,5,2],[0,1,0]])
    test(1,"テスト2",[[0,0,3],[1,5,2],[0,1,0]])
    test(2,"テスト3",[[0,0,3],[1,5,2],[0,1,0]])
    #test(0,"テスト4","123")
    #test(1,"テスト5","123")
    test(2,"テスト6","123")
    test(2,"テスト7","ABC")
    test(0,"テスト8",["◁","△","▽","▷"])
    test(1,"テスト9",["◁","△","▽","▷"])
    test(2,"テスト10",["◁","△","▽","▷"])

2024-09-17 「余因子展開逆行列計算2」
余因子展開と行列式計算を使って余因子行を作成し、それで逆行列を作る。

参照:
    https://wagtail.cds.tohoku.ac.jp/coda/python/p-8-function-part2-sup-matrix.html
    Pythonプログラミング(ステップ8・行列の計算) 1.行列式の計算  余因子展開による行列式計算

結果:

実行結果: 行列値 = determinant() - 行列式計算
    https://wagtail.cds.tohoku.ac.jp/coda/python/p-8-function-part2-sup-matrix.html
    Pythonプログラミング(ステップ8・行列の計算) 1.行列式の計算  余因子展開による行列式計算
....

■◎◎ test-1 ◎◎■
## 入力: ##
[[     4 ]]
ランク(A): 1  ,  1 x 1  行列
My det: 4
NUmpy det(): 4.0
Numpy det(): OK
## A余因子行列: ##
[[     1 ]]
## A逆行列: ##
[[  0.25 ]]
Numpy inv(): OK

■◎◎ test-2 ◎◎■
## 入力: ##
[[     1     2 ]
 [     3     4 ]]
ランク(A): 2  ,  2 x 2  行列
My det: -2
NUmpy det(): -2.0000000000000004
Numpy det(): OK
## A余因子行列: ##
[[     4    -2 ]
 [    -3     1 ]]
## A逆行列: ##
[[    -2     1 ]
 [   1.5  -0.5 ]]
Numpy inv(): OK

■◎◎ test-3 ◎◎■
## 入力: ##
[[     0    -1     2 ]
 [    -1     5     2 ]
 [     0     0     3 ]]
ランク(A): 3  ,  3 x 3  行列
My det: -3
NUmpy det(): -3.0000000000000004
Numpy det(): OK
## A余因子行列: ##
[[    15     3   -12 ]
 [     3     0    -2 ]
 [     0     0    -1 ]]
## A逆行列: ##
[[    -5    -1     4 ]
 [    -1    -0  0.6667 ]
 [    -0    -0  0.3333 ]]
Numpy inv(): OK

■◎◎ test-4 ◎◎■
## 入力: ##
[[     5    -2     2     7 ]
 [     1     0     0     3 ]
 [    -3     1     5     0 ]
 [     3    -1    -9     4 ]]
ランク(A): 4  ,  4 x 4  行列
My det: 88
NUmpy det(): 88.00000000000003
Numpy det(): OK
## A余因子行列: ##
[[   -12    76   -60   -36 ]
 [   -56   208   -82   -58 ]
 [     4     4    -2   -10 ]
 [     4     4    20    12 ]]
## A逆行列: ##
[[ -0.1364  0.8636 -0.6818 -0.4091 ]
 [ -0.6364  2.364 -0.9318 -0.6591 ]
 [  0.04545  0.04545 -0.02273 -0.1136 ]
 [  0.04545  0.04545  0.2273  0.1364 ]]
Numpy inv(): OK

■◎◎ test-5 ◎◎■
## 入力: ##
[[     1    -1    -1 ]
 [    -1     1    -1 ]
 [    -1    -1     1 ]]
ランク(A): 3  ,  3 x 3  行列
My det: -4
NUmpy det(): -4.0
Numpy det(): OK
## A余因子行列: ##
[[     0     2     2 ]
 [     2     0     2 ]
 [     2     2     0 ]]
## A逆行列: ##
[[    -0  -0.5  -0.5 ]
 [  -0.5    -0  -0.5 ]
 [  -0.5  -0.5    -0 ]]
Numpy inv(): OK

■◎◎ test-6 ◎◎■
## 入力: ##
[[    -1     1     1 ]
 [     1    -1     1 ]
 [     1     1    -1 ]]
ランク(A): 3  ,  3 x 3  行列
My det: 4
NUmpy det(): 4.0
Numpy det(): OK
## A余因子行列: ##
[[     0     2     2 ]
 [     2     0     2 ]
 [     2     2     0 ]]
## A逆行列: ##
[[     0   0.5   0.5 ]
 [   0.5     0   0.5 ]
 [   0.5   0.5     0 ]]
Numpy inv(): OK

■◎◎ test-7 ◎◎■
## 入力: ##
[[     1     3     9 ]
 [    -1     1    -1 ]
 [     2    -4    -2 ]]
ランク(A): 2  ,  3 x 3  行列
My det: 0
NUmpy det(): 1.1102230246251546e-15
Numpy det(): OK
逆行列はありません

■◎◎ test-8 ◎◎■
## 入力: ##
[[    -1     1     3 ]
 [     2     3    -1 ]
 [     3     4    -2 ]]
ランク(A): 2  ,  3 x 3  行列
My det: 0
NUmpy det(): -1.896631000401315e-15
Numpy det(): OK
逆行列はありません

■◎◎ testC-1 ◎◎■
## 入力: ##
[[     0     8    -5    13 ]
 [    -8    -7     7     8 ]
 [    11    -4    -3   -11 ]
 [     5     8   -11     8 ]]
ランク(A): 4  ,  4 x 4  行列
My det: 5317
NUmpy det(): 5317.000000000005
Numpy det(): OK
## A余因子行列: ##
[[  1167    -4   825  -758 ]
 [   689  -663  -169  -689 ]
 [  1417  -260   455 -1417 ]
 [   530   308   279  -121 ]]
## A逆行列: ##
[[  0.2195 -0.0007523  0.1552 -0.1426 ]
 [  0.1296 -0.1247 -0.03178 -0.1296 ]
 [  0.2665 -0.0489  0.08557 -0.2665 ]
 [  0.09968  0.05793  0.05247 -0.02276 ]]
Numpy inv(): OK

■◎◎ testC-2 ◎◎■
## 入力: ##
[[    11     9     8     2    -3    -7 ]
 [     7    13     5    -1   -10     8 ]
 [    -7    -7    -8     0     1    -4 ]
 [   -10    -5     4   -10    12    -2 ]
 [    12   -10    -4    11    13   -13 ]
 [    -6   -11     7   -11    -8     3 ]]
ランク(A): 6  ,  6 x 6  行列
My det: 2282655
NUmpy det(): 2282655.0
Numpy det(): OK
## A余因子行列: ##
[[ -6.789e+04  5.03e+05  2.516e+05  1.449e+05  2.633e+05  7.351e+04 ]
 [  7.202e+04  5.577e+04  7.532e+04  5.501e+04 -5.952e+04 -1.015e+05 ]
 [  8.831e+04 -5.115e+05 -4.866e+05 -1.523e+05 -1.856e+05  1.537e+04 ]
 [  1.95e+04 -6.802e+05 -5.253e+05 -3.196e+05 -2.393e+05 -9.087e+04 ]
 [ -7.346e+04  5.595e+04 -6.548e+04  1.156e+05  6.218e+04 -6.14e+04 ]
 [ -2.022e+05  5.92e+04 -1.859e+05 -1.642e+04  3.013e+04  2916 ]]
## A逆行列: ##
[[ -0.02974  0.2204  0.1102  0.0635  0.1154  0.0322 ]
 [  0.03155  0.02443  0.033  0.0241 -0.02608 -0.04447 ]
 [  0.03869 -0.2241 -0.2132 -0.06672 -0.08133  0.006732 ]
 [  0.008541 -0.298 -0.2301 -0.14 -0.1048 -0.03981 ]
 [ -0.03218  0.02451 -0.02869  0.05066  0.02724 -0.0269 ]
 [ -0.08858  0.02594 -0.08145 -0.007194  0.0132  0.001277 ]]
Numpy inv(): OK

■◎◎ testC-3 ◎◎■
## 入力: ##
[[    10    -6   -12     6 ]
 [     5   -11   -11    -8 ]
 [    -7     7    -7    -8 ]
 [   -10    13    -7   -11 ]]
ランク(A): 4  ,  4 x 4  行列
My det: -5760
NUmpy det(): -5759.999999999993
Numpy det(): OK
## A余因子行列: ##
[[  -270  -450  3630 -2460 ]
 [  -240    48  1840 -1504 ]
 [   270  -126  1170  -612 ]
 [  -210   546 -1870  1372 ]]
## A逆行列: ##
[[  0.04688  0.07812 -0.6302  0.4271 ]
 [  0.04167 -0.008333 -0.3194  0.2611 ]
 [ -0.04688  0.02187 -0.2031  0.1062 ]
 [  0.03646 -0.09479  0.3247 -0.2382 ]]
Numpy inv(): OK
----

プログラム:
--------------- inv-cof3.py --------
'''
https://wagtail.cds.tohoku.ac.jp/coda/python/p-8-function-part2-sup-matrix.html
Pythonプログラミング(ステップ8・行列の計算) 1.行列式の計算  余因子展開による行列式計算
'''

def submatrix(i,j,A):
    n = len(A[0])
    B = [ ]
    for k in range(n):
        if k==i:
            continue
        x=[ ] # gen row vector
        for l in range(n):
            if l==j:
                continue
            x.append(A[k][l])
        B.append(x)
    return B

# cofactor expansion
def determinant(A):
    n=len(A)
    if n==1:
        return A[0][0]
    det=0
    for i in range(n):
        det = det + (-1)**(i+0) * A[i][0] * determinant(submatrix(i,0,A))
    return det
# ---^^

def comatrix(A):
    """
    余因子行列を作る
    """
    c = len(A)
    if c == 1:
        # 余因子行列 1x1は、1
        return [[1]]
    acofctr = [[0] * c for _ in range(c)]
    for i in range(c):
        for j in range(c):
            # 余因子行列は転置
            acofctr[j][i] = (-1)**((i+j)&1) * determinant(submatrix(i, j, A))
    return acofctr

def coinv(A, det):
    """
    余因子行列より逆行列をつくる
    """
    c = len(A)
    inv = [[0] * c for _ in range(c)]
    for i in range(c):
        for j in range(c):
            inv[i][j] = A[i][j] / det
    return inv

def pmatrix(msg, MAT):
    '''
     行列の印刷
    '''
    print("##",msg,"##")
    if MAT is None:
        print("  結果がありません")
        return
    n = len(MAT)
    m = len(MAT[0])
    for i in range(n):
        if i == 0:
            print("[[",end='')
        else:
            print(" [",end='')
        for j in range(m):
            print(" % 5.4g" % (MAT[i][j]), end='')
        if i == (n-1):
            print(" ]]")
        else:
            print(" ]")

# ####################################
if ( __name__ == '__main__' ):
    import numpy as np

    def p_header():
        print("実行結果: 行列値 = determinant() - 行列式計算")
        print("    https://wagtail.cds.tohoku.ac.jp/coda/python/p-8-function-part2-sup-matrix.html")
        print("    Pythonプログラミング(ステップ8・行列の計算) 1.行列式の計算  余因子展開による行列式計算")
        print("....")

    def gen_matrix():
        '''
        行列生成 n x n
        '''
        import random as r
        RMAX = 13
        n = r.randrange(4,8)
        m = []
        for _ in range(n):
            m.append([r.randrange(-RMAX,RMAX+1) for j in range(n)])
        return m

    def ematrix(A):
        la = np.linalg.matrix_rank(A)
        print("ランク(A):",la, " , ",len(A) , "x",len(A[0])," 行列")

    def test(msg, A, EPS=1.0e-8):
        print('')
        print("■◎◎",msg,"◎◎■")
        pmatrix("入力:",A)
        ematrix(A)
        mydet = determinant(A)  # || ||
        print("My det:",mydet)
        print("NUmpy det():",np.linalg.det(A))
        ndet = np.linalg.det(A)
        if np.allclose(ndet,mydet):
            print("Numpy det(): OK")
        else:
            pmatrix("Numpy det(): NG ", ndet)
        if abs(mydet) < EPS:
            print("逆行列はありません")
            return
        mymatc = comatrix(A)
        pmatrix("A余因子行列:",mymatc)
        myinv = coinv(mymatc, mydet)
        pmatrix("A逆行列:",myinv)
        ninv = np.linalg.inv(A)
        if np.allclose(ninv,myinv):
            print("Numpy inv(): OK")
        else:
            pmatrix("Munpy inv(): NG", ninv)


    p_header()
    test("test-1", [[4]])
    test("test-2",[[1,2],[3,4]])
    test("test-3", [[0,-1,2],[-1,5,2],[0,0,3]])  
    test("test-4", [[5, -2, 2, 7], [1, 0, 0, 3], [-3, 1, 5, 0], [3, -1, -9, 4]])
    test("test-5", [[1, -1, -1],[-1, 1, -1],[-1, -1, 1]]) 
    test("test-6", [[-1, 1, 1],[1, -1, 1],[1, 1, -1]]) 
    test("test-7", [[1, 3, 9],[-1, 1, -1],[2, -4, -2]]) 
    test("test-8", [[-1, 1, 3],[2, 3, -1],[3, 4, -2]])
    for c in range(1,4):
        test("testC-%d" % c, gen_matrix())

2024-09-12  「Doolittle法でLU分解」
Doolittle法でLU分解をやってみた。
SCIPY linalg.lu()と比べるのも何なのですが比べてみました。
ある条件では同じになります。

SCILAB 結果

>> m = [3,5,2;2,3,7;1,2,-4]
m =

   3   5   2
   2   3   7
   1   2  -4

>> [l u p] = lu(m)
l =

   1.0000        0        0
   0.3333   1.0000        0
   0.6667  -1.0000   1.0000

u =

   3.0000   5.0000   2.0000
        0   0.3333  -4.6667
        0        0   1.0000

p =

Permutation Matrix

   1   0   0
   0   0   1
   0   1   0

実行:
........
実行結果: L,U,P = doolittle() - LU分解P
  https://johnfoster.pge.utexas.edu/numerical-methods-book/LinearAlgebra_LU.html
    doolittle()
....

[@@@@@@@@@@@@@@@@@@] testA-1,2,3 [@@@@@@@@@@@@@@@@@@]
入力:
[[3, 5, 2], [2, 3, 7], [1, 2, -4]]
答:
ランク(A): 3    3 x 3  行列
###  sci lu().U:  ###
  3.00000  5.00000  2.00000
  0.00000  0.33333 -4.66667
  0.00000  0.00000  1.00000
###  sci lu().U:  ###
  1.00000  0.00000  0.00000
  0.33333  1.00000  0.00000
  0.66667 -1.00000  1.00000
scipy lu()  Up: Ng?
scipy lu() Low: Ng?
###  U1:  ###
  3.00000  5.00000  2.00000
  0.00000 -0.33333  5.66667
  0.00000  0.00000  1.00000
###  L1:  ###
  1.00000  0.00000  0.00000
  0.66667  1.00000  0.00000
  0.33333 -1.00000  1.00000
[[ 3.  5.  2.]
 [ 2.  3.  7.]
 [ 1.  2. -4.]]
行入れ替え情報: [0, 1, 2]
DET: -1.000000000000007
Scipy lu() det: -1.000000000000007
numpy det: -1.0000000000000047
..検算..
 det() OK
 matrix OK

[@@@@@@@@@@@@@@@@@@] testA-1,3,2 [@@@@@@@@@@@@@@@@@@]
入力:
[[3, 5, 2], [1, 2, -4], [2, 3, 7]]
答:
ランク(A): 3    3 x 3  行列
###  sci lu().U:  ###
  3.00000  5.00000  2.00000
  0.00000  0.33333 -4.66667
  0.00000  0.00000  1.00000
###  sci lu().U:  ###
  1.00000  0.00000  0.00000
  0.33333  1.00000  0.00000
  0.66667 -1.00000  1.00000
scipy lu()  Up: OK
scipy lu() Low: OK
###  U1:  ###
  3.00000  5.00000  2.00000
  0.00000  0.33333 -4.66667
  0.00000  0.00000  1.00000
###  L1:  ###
  1.00000  0.00000  0.00000
  0.33333  1.00000  0.00000
  0.66667 -1.00000  1.00000
[[ 3.  5.  2.]
 [ 1.  2. -4.]
 [ 2.  3.  7.]]
行入れ替え情報: [0, 1, 2]
DET: 1.0000000000000067
Scipy lu() det: 1.0000000000000067
numpy det: 1.0000000000000047
..検算..
 det() OK
 matrix OK

[@@@@@@@@@@@@@@@@@@] testA-2,1,3 [@@@@@@@@@@@@@@@@@@]
入力:
[[2, 3, 7], [3, 5, 2], [1, 2, -4]]
答:
ランク(A): 3    3 x 3  行列
###  sci lu().U:  ###
  3.00000  5.00000  2.00000
  0.00000  0.33333 -4.66667
  0.00000  0.00000  1.00000
###  sci lu().U:  ###
  1.00000  0.00000  0.00000
  0.33333  1.00000  0.00000
  0.66667 -1.00000  1.00000
scipy lu()  Up: Ng?
scipy lu() Low: Ng?
###  U1:  ###
  3.00000  5.00000  2.00000
  0.00000 -0.33333  5.66667
  0.00000  0.00000  1.00000
###  L1:  ###
  1.00000  0.00000  0.00000
  0.66667  1.00000  0.00000
  0.33333 -1.00000  1.00000
[[ 3.  5.  2.]
 [ 2.  3.  7.]
 [ 1.  2. -4.]]
行入れ替え情報: [1, 0, 2]
DET: 1.000000000000007
Scipy lu() det: 1.000000000000007
numpy det: 1.0000000000000047
..検算..
 det() OK
 matrix OK

[@@@@@@@@@@@@@@@@@@] testA-2,3,1 [@@@@@@@@@@@@@@@@@@]
入力:
[[2, 3, 7], [1, 2, -4], [3, 5, 2]]
答:
ランク(A): 3    3 x 3  行列
###  sci lu().U:  ###
  3.00000  5.00000  2.00000
  0.00000  0.33333 -4.66667
  0.00000  0.00000  1.00000
###  sci lu().U:  ###
  1.00000  0.00000  0.00000
  0.33333  1.00000  0.00000
  0.66667 -1.00000  1.00000
scipy lu()  Up: OK
scipy lu() Low: OK
###  U1:  ###
  3.00000  5.00000  2.00000
  0.00000  0.33333 -4.66667
  0.00000  0.00000  1.00000
###  L1:  ###
  1.00000  0.00000  0.00000
  0.33333  1.00000  0.00000
  0.66667 -1.00000  1.00000
[[ 3.  5.  2.]
 [ 1.  2. -4.]
 [ 2.  3.  7.]]
行入れ替え情報: [2, 1, 0]
DET: -1.0000000000000067
Scipy lu() det: -1.0000000000000067
numpy det: -1.0000000000000047
..検算..
 det() OK
 matrix OK

[@@@@@@@@@@@@@@@@@@] testA-3,1,2 [@@@@@@@@@@@@@@@@@@]
入力:
[[1, 2, -4], [3, 5, 2], [2, 3, 7]]
答:
ランク(A): 3    3 x 3  行列
###  sci lu().U:  ###
  3.00000  5.00000  2.00000
  0.00000  0.33333 -4.66667
  0.00000  0.00000  1.00000
###  sci lu().U:  ###
  1.00000  0.00000  0.00000
  0.33333  1.00000  0.00000
  0.66667 -1.00000  1.00000
scipy lu()  Up: OK
scipy lu() Low: OK
###  U1:  ###
  3.00000  5.00000  2.00000
  0.00000  0.33333 -4.66667
  0.00000  0.00000  1.00000
###  L1:  ###
  1.00000  0.00000  0.00000
  0.33333  1.00000  0.00000
  0.66667 -1.00000  1.00000
[[ 3.  5.  2.]
 [ 1.  2. -4.]
 [ 2.  3.  7.]]
行入れ替え情報: [1, 0, 2]
DET: -1.0000000000000067
Scipy lu() det: -1.0000000000000067
numpy det: -1.0000000000000047
..検算..
 det() OK
 matrix OK

[@@@@@@@@@@@@@@@@@@] testA-3,2,1 [@@@@@@@@@@@@@@@@@@]
入力:
[[1, 2, -4], [2, 3, 7], [3, 5, 2]]
答:
ランク(A): 3    3 x 3  行列
###  sci lu().U:  ###
  3.00000  5.00000  2.00000
  0.00000  0.33333 -4.66667
  0.00000  0.00000  1.00000
###  sci lu().U:  ###
  1.00000  0.00000  0.00000
  0.33333  1.00000  0.00000
  0.66667 -1.00000  1.00000
scipy lu()  Up: Ng?
scipy lu() Low: Ng?
###  U1:  ###
  3.00000  5.00000  2.00000
  0.00000 -0.33333  5.66667
  0.00000  0.00000  1.00000
###  L1:  ###
  1.00000  0.00000  0.00000
  0.66667  1.00000  0.00000
  0.33333 -1.00000  1.00000
[[ 3.  5.  2.]
 [ 2.  3.  7.]
 [ 1.  2. -4.]]
行入れ替え情報: [2, 1, 0]
DET: 1.000000000000007
Scipy lu() det: 1.000000000000007
numpy det: 1.0000000000000047
..検算..
 det() OK
 matrix OK

TEST MATRIX No. 1
  15 x 15 行列
ランク(A): 15    15 x 15  行列
..検算:
scipy lu()  Up: OK
scipy lu() Low: OK
 det() OK
 scipy lu() det: OK
 matrix OK

TEST MATRIX No. 2
  19 x 19 行列
ランク(A): 19    19 x 19  行列
..検算:
scipy lu()  Up: OK
scipy lu() Low: OK
 det() OK
 scipy lu() det: OK
 matrix OK

TEST MATRIX No. 3
  18 x 18 行列
ランク(A): 18    18 x 18  行列
..検算:
scipy lu()  Up: OK
scipy lu() Low: OK
 det() OK
 scipy lu() det: OK
 matrix OK

TEST MATRIX No. 4
  17 x 17 行列
ランク(A): 17    17 x 17  行列
..検算:
scipy lu()  Up: OK
scipy lu() Low: OK
 det() OK
 scipy lu() det: OK
 matrix OK

TEST MATRIX No. 5
  28 x 28 行列
ランク(A): 28    28 x 28  行列
..検算:
scipy lu()  Up: OK
scipy lu() Low: OK
 det() OK
 scipy lu() det: OK
 matrix OK
....

プログラム:

'''
掃き出し法 上三角行列で行列式計算

https://stackoverflow.com/questions/40887409/numpy-matrix-determinant-precision-problems
Numpy matrix determinant precision problems
'''
def my_det(mX,n, EPS=1.0e-7):
    X = [mX[i][:n] for i in range(n)]
    s = 1
    for i in range(n):
        maxElement = abs(X[i][i])
        maxRow = i
        for k in range(i + 1, n):
            if abs(X[k][i]) > maxElement:
                maxElement = abs(X[k][i])
                maxRow = k
        if maxRow != i:
            s = -s
            for k in range(i, n):
                xt = X[i][k]
                X[i][k] = X[maxRow][k]
                X[maxRow][k] = xt
        if abs(X[i][i]) < EPS:
            return 0
        for k in range(i + 1, n):
            c = -X[k][i] / X[i][i]
            for j in range(i, n):
                if i == j:
                    X[k][j] = 0
                else:
                    X[k][j] += c * X[i][j]
    det = 1
    for i in range(n):
        det *= X[i][i]
    det *= s
    return det

def check_submatrix(A,P,n,eps):
    pv = abs(A[0][0])       # 先頭に絶対値最大設定
    ii = 0
    for x in range(1,n):
        ab = abs(A[x][0])
        if ab > pv:
            pv = ab
            ii = x
    if 0 != ii:
        for j in range(n):
            xx = A[0][j]
            A[0][j] = A[ii][j]
            A[ii][j] = xx
        xx = P[0]
        P[0] = P[ii]
        P[ii] = xx
    for i in range(1,n):    # 2行目以降、首座小行列式のゼロ検出したら行入れ替え
        sdet = my_det(A,i+1)
        if abs(sdet) < eps:
            if (i + 1) == n:
                return False
            for j in range(n):
                xx = A[i][j]
                A[i][j] = A[i+1][j]
                A[i+1][j] = xx
            xx = P[i]
            P[i] = P[i+1]
            P[i+1] = xx
    return True


'''
https://johnfoster.pge.utexas.edu/numerical-methods-book/LinearAlgebra_LU.html
'''
def exe_doolittle(A,P, n, eps):
    U = [ [0 for _ in range(n)] for _ in range(n)]
    L = [ [ 0 if i!=j else 1 for j in range(n)] for i in range(n) ]
    for k in range(n):
        #nU[k, k:] = nA[k, k:] - nL[k,:k] @ nU[:k,k:]
        for j in range(k, n):
            sum = 0
            for d in range(k):
                sum += L[k][d] * U[d][j]
            if k == j and (A[k][j] - sum) < eps:
                pass
            U[k][j] = A[k][j] - sum

        #nL[(k+1):,k] = (nA[(k+1):,k] - nL[(k+1):,:] @ nU[:,k]) / nU[k, k]
        if abs(U[k][k]) < eps:
            return None,None,None
        for i in range(k+1, n):
            sum = 0
            for d in range(n):
                sum += L[i][d] * U[d][k]
            L[i][k] = ( A[i][k] - sum) / U[k][k]
    return L,U,P

def doolittle(Amt, EPS=1.0e-7):
    n = len(Amt)
    A = [e.copy() for e in Amt]
    P = [_ for _ in range(n)]
    if check_submatrix(A,P,n,EPS):
        return exe_doolittle(A,P,n,EPS)
    return None,None,None

def doolittle_direct(Amt, EPS=1.0e-7):
    n = len(Amt)
    A = [e.copy() for e in Amt]
    P = [_ for _ in range(n)]
    return exe_doolittle(A,P,n,EPS)

'''
      ----^^^^^
'''

def matrix_dmp(msg, A):
    print("### ",msg," ###")
    n = len(A)
    for i in range(n):
        for j in range(n):
            print(" % 0.5f" % (A[i][j]), end='')
        print("")

def chk(a):
    if type(a) == list:
        if len(a) == 0:
            return None
        else:
            if type(a[0]) != list:
                A = [a.copy()]
            else: 
                A = [e.copy() for e in  a]
        n = len(A)
        m = len(A[0])
    else:
        n = 0
        m = 0
    if m != n or n == 0: # 正方行列のみ
        return None
    return A

if __name__ == '__main__':
    import numpy as np
    from scipy.linalg import lu as slu

    def p_header():
        print("実行結果: L,U,P = doolittle() - LU分解P")
        print("  https://johnfoster.pge.utexas.edu/numerical-methods-book/LinearAlgebra_LU.html")
        print("    doolittle()")
        print("....")

    def ematrix(PA):
        if type(PA) == list:
            if type(PA[0]) != list:
                A = [PA.copy()]
            else: 
                A = [e.copy() for e in  PA]
            n = len(A)
            m = len(A[0])
        else:
            n = 0
            m = 0
        if m != n or m == 0: # 右辺はなし、正方行列
            print("答なし ")
            return
        la = np.linalg.matrix_rank(A)
        print("ランク(A):",la, "  ",n,"x",n," 行列")

    def permutation(P, mat):
        '''
          順列 交換回数計算
        '''
        n = len(P)
        Z = [e for e in P]
        cnt = 0
        for i in range(n):
            if Z[i] != i:
                min = i
                for j in range(i+1,n):
                    if Z[j] < Z[min]:
                        min = j
                for j in range(n):
                    xx = mat[min][j]
                    mat[min][j] = mat[i][j]
                    mat[i][j] = xx 
                xx = Z[min]
                Z[min] = Z[i]
                Z[i] = xx
                cnt += 1
        return cnt

    def mpermutation(mP):
        '''
          順列行列 交換回数計算
        '''
        n = len(mP)
        P = [e.copy() for e in mP]
        cnt = 0
        for i in range(n):
            if P[i][i] != 1:
                cnt += 1
                for j in range(i+1,n):
                    if P[j][i] == 1:
                        for k in range(n):
                            ss = P[i][k]
                            P[i][k] = P[j][k]
                            P[j][k] = ss
                        break
        return cnt

    def gen_matrix(n=0, RMAX=50, DCP=1):
        '''
            行列生成 N x N
              n = 0 : ランダムNxN , 9 : 9 x 9行列
              RMAX = 50 : (+-50)で要素データ、 99: (+-99)で要素データ
              DCP = 1 : 要素データ * 10,  +9 : 要素データ * (10**9) 、 -9 : 要素データ / (10**9)
        '''
        import random as r
        DC = 10**abs(DCP)
        if n == 0:
            N = r.randrange(10,41) # 10x10 ~ 40x40の行列を作る
        else:
            N = n                  # n x n の行列を作る
        nx = r.randrange(N*4)  # 時々、対角優位行列でなくする
        m = []
        for i in range(N):
            m.append([r.randrange(-RMAX,RMAX+1) for j in range(N)])
        for i in range(N):
            if i != nx:
                ml = 0
                for j in range(N):
                    if i != j:
                        ml += abs(m[i][j])
                if m[i][i] < 0:
                    m[i][i] -= ml
                else:
                    m[i][i] += ml
        for i in range(N):
            for j in range(N):
                if DCP < 0:
                    m[i][j] /= DC
                else:
                    m[i][j] *= DC

        return m

    def testMatrix(nc, EPS=1.0e-7):
        for n in range(1, nc+1):
            print("")
            print("TEST MATRIX No.", n)
            A = gen_matrix(RMAX=360, DCP=-3)
            nn = len(A)
            print("  %d x %d 行列" % (nn,nn)) 
            ematrix(A)
            L1,U1,P1 = doolittle(A)
            if L1 is None:         # 左辺行列がない
                print(" 計算できません")
            else:
                print("..検算:")
                P2, L2,U2 = slu(A)
                sdet = 1
                for i in range(len(P2)):
                    sdet *= U2[i][i]
                sdet *= (-1)**mpermutation(P2)
                if np.allclose(U1,U2):
                    print("scipy lu()  Up: OK")
                else:
                    print("scipy lu()  Up: Ng?")
                if np.allclose(L1,L2):
                    print("scipy lu() Low: OK")
                else:
                    print("scipy lu() Low: Ng?")
                lxu = np.dot(L1,U1)
                det = 1
                for i in range(len(A)):
                    det *= U1[i][i]
                s = permutation(P1, lxu)
                if s & 1:
                    det = -det
                if abs(det) < EPS:
                    print(" DET() == ZERO")
                ndet = np.linalg.det(A)
                if np.allclose(det, ndet):
                    print(" det() OK")
                else:
                    print(" det() ??NG")
                if np.allclose(sdet, det):
                    print(" scipy lu() det: OK")
                else:
                    print(" scipy lu() det: ??NG")
                if np.allclose(A, lxu):
                    print(" matrix OK")
                else:
                    print(" matrix ??NG")
            
    def test(msg,mat, EPS=1.0e-7):
        print("")
        print("[@@@@@@@@@@@@@@@@@@]",msg,"[@@@@@@@@@@@@@@@@@@]")
        print("入力:")
        print(mat)
        print("答:")
        A = chk(mat)
        if A is None:               # 左辺行列がない
            print("計算できません")
            return
        ematrix(mat)
        L1,U1,P1 = doolittle(A)

        if L1 is None:              # 左辺行列が可逆行列でない
            print(" 計算できません")
        else:
            P2, L2,U2 = slu(A)
            matrix_dmp("sci lu().U:",U2)
            matrix_dmp("sci lu().U:",L2)
            det = 1
            for i in range(len(P2)):
                det *= U2[i][i]
            det *= (-1)**mpermutation(P2)
            if np.allclose(U1,U2):
                print("scipy lu()  Up: OK")
            else:
                print("scipy lu()  Up: Ng?")
            if np.allclose(L1,L2):
                print("scipy lu() Low: OK")
            else:
                print("scipy lu() Low: Ng?")
            matrix_dmp("U1:",U1)
            matrix_dmp("L1:",L1)
            lxu = np.dot(L1,U1)
            print(lxu)
            print("行入れ替え情報:", P1)
            det = 1
            for i in range(len(A)):
                det *= U1[i][i]
            s = permutation(P1, lxu)
            if s & 1:
                det = -det
            print("DET:",det)
            if abs(det) < EPS:
                print(" DET() == ZERO")
            print("Scipy lu() det:",det)
            ndet = np.linalg.det(A)
            print("numpy det:",ndet)
            print("..検算..")
            if np.allclose(det, ndet):
                print(" det() OK")
            else:
                print(" det() ??NG")
            #matrix_dmp("my L@U:",lxu)
            if np.allclose(A, lxu):
                print(" matrix OK")
            else:
                print(" matrix ??NG", lxu)

    p_header()
    test("testA-1,2,3",[[3,5,2],[2,3,7],[1,2,-4]]) # 1,2,3
    test("testA-1,3,2",[[3,5,2],[1,2,-4],[2,3,7]]) # 1,3,2
    test("testA-2,1,3",[[2,3,7],[3,5,2],[1,2,-4]]) # 2,1,3
    test("testA-2,3,1",[[2,3,7],[1,2,-4],[3,5,2]]) # 2,3,1
    test("testA-3,1,2",[[1,2,-4],[3,5,2],[2,3,7]]) # 3,1,2
    test("testA-3,2,1",[[1,2,-4],[2,3,7],[3,5,2]]) # 3,2,1
    testMatrix(5)
    #test("testB-1.2.3",[[0,0,3],[-1,5,2],[0,-1,0]]) # 1,2,3
    #test("testB-1,3,2",[[0,0,3],[0,-1,0],[-1,5,2]]) # 1,3,2
    #test("testB-2,1,3",[[-1,5,2],[0,0,3],[0,-1,0]]) # 2,1,3
    #test("testB-2,3,1",[[-1,5,2],[0,-1,0],[0,0,3]]) # 2,3,1
    #test("testB-3,1,2",[[0,-1,0],[0,0,3],[-1,5,2]]) # 3,1,2
    #test("testB-3,2,1",[[0,-1,0],[-1,5,2],[0,0,3]]) # 3,2,1

2024-09-03  「Gauss-Jordan消去・完全ピポッド法」
参照:パソコンBASIC数値計算Ⅰ  小島紀夫、町田東一著 東海大学出版会  1982,1994
      2.1.5 完全ピポッド法のプログラム

Gauss-Jordan消去法での完全ピポッドのプログラム。

実行:
...
実行結果: 答 = gl_complete_pivot(AB,DET=行列計算値) - Gauss-Jordan 完全ピボット
   本 パソコンBASIC数値計算Ⅰ  小島紀夫、町田東一著 東海大学出版会  1982,1994
       2.1.5 完全ピポッド法のプログラム
....
◆◆◆◆ 計算1 ◆◆◆◆
入力:  MATRIX:
[        2 |        3 ]
ランク (A): 1
ランク(AB): 1
答は一つ : ランク(A) == ランク(AB) == A行数  1 x 1  行列
  答:  MATRIX:
[      1.5 ]
  == numpy solve(): OK
◆◆◆◆ 計算2 ◆◆◆◆
入力:  MATRIX:
[        1     0.99 |     1.99 ]
[     0.99     0.98 |     1.97 ]
ランク (A): 2
ランク(AB): 2
答は一つ : ランク(A) == ランク(AB) == A行数  2 x 2  行列
  答:  MATRIX:
[        1 ]
[        1 ]
  == numpy solve(): OK
◆◆◆◆ 計算3 ◆◆◆◆
入力:  MATRIX:
[        0        1        3        0 |        1 ]
[        1        0        2        4 |        0 ]
[        0        0        0        1 |        0 ]
[        5       -4       -4        0 |        0 ]
ランク (A): 4
ランク(AB): 4
答は一つ : ランク(A) == ランク(AB) == A行数  4 x 4  行列
  答:  MATRIX:
[        4 ]
[        7 ]
[       -2 ]
[  2.78e-17 ]
  == numpy solve(): OK
◆◆◆◆ 計算4 ◆◆◆◆
入力:  MATRIX:
[     2.08      3.4     1.04    -0.28 |     1.28 ]
[    -1.68    -2.68    -0.84     0.16 |    -6.72 ]
[     5.14     3.12    -4.32     4.59 |     0.86 ]
[     3.12      2.8     1.56     1.88 |     4.62 ]
ランク (A): 3
ランク(AB): 4
答はなし : ランク(A) < ランク(AB) 4 x 4  行列
計算できません
◆◆◆◆ 逆行列計算1 ◆◆◆◆
入力:  MATRIX:
[        0        2 |        1        0 ]
[        5        0 |        0        1 ]
ランク (A): 2
ランク(AB): 2
答は一つ : ランク(A) == ランク(AB) == A行数  2 x 2  行列
  答:  MATRIX:
[        0      0.2 ]
[      0.5        0 ]
  == numpy inv(): OK
◆◆◆◆ 逆行列計算2 ◆◆◆◆
入力:  MATRIX:
[       -1        1        1 |        1        0        0 ]
[        1       -1        1 |        0        1        0 ]
[        1        1       -1 |        0        0        1 ]
ランク (A): 3
ランク(AB): 3
答は一つ : ランク(A) == ランク(AB) == A行数  3 x 3  行列
  答:  MATRIX:
[        0      0.5      0.5 ]
[      0.5        0      0.5 ]
[      0.5      0.5        0 ]
  == numpy inv(): OK
◆◆◆◆ 逆行列計算3 ◆◆◆◆
入力:  MATRIX:
[        1        3        9 |        1        0        0 ]
[       -1        1       -1 |        0        1        0 ]
[        2       -4       -2 |        0        0        1 ]
ランク (A): 2
ランク(AB): 3
答はなし : ランク(A) < ランク(AB) 3 x 3  行列
計算できません
◆◆◆◆ 逆行列計算4 ◆◆◆◆
入力:  MATRIX:
[        2 |        1 ]
ランク (A): 1
ランク(AB): 1
答は一つ : ランク(A) == ランク(AB) == A行数  1 x 1  行列
  答:  MATRIX:
[      0.5 ]
  == numpy inv(): OK
◆◆◆◆ 逆行列計算5 ◆◆◆◆
入力:  MATRIX:
[        2       -4        0 |        1        0        0 ]
[        3       -6       -2 |        0        1        0 ]
[        1       -2        1 |        0        0        1 ]
ランク (A): 2
ランク(AB): 3
答はなし : ランク(A) < ランク(AB) 3 x 3  行列
計算できません
◆◆◆◆ 逆行列計算6 ◆◆◆◆
入力:  MATRIX:
[       -6       -2       -9       -2 |        1        0        0        0 ]
[      -10        3       -8       11 |        0        1        0        0 ]
[        7       -9       -9        5 |        0        0        1        0 ]
[      -11        8        5        5 |        0        0        0        1 ]
ランク (A): 4
ランク(AB): 4
答は一つ : ランク(A) == ランク(AB) == A行数  4 x 4  行列
  答:  MATRIX:
[    -0.13    0.149   -0.137   -0.243 ]
[   -0.157    0.298   -0.326   -0.392 ]
[   0.0235    -0.17    0.148    0.236 ]
[  -0.0583   0.0213   0.0717   0.0581 ]
  == numpy inv(): OK
--------------------------

プログラム:
------------- gj-complete-pivot.py --------------
'''
   本 パソコンBASIC数値計算Ⅰ  小島紀夫、町田東一著 東海大学出版会  1982,1994
       2.1.5 完全ピポッド法のプログラム
'''
def gj_complete_pivot(PA,DET=None,E=1.0E-5):
    '''
      Gauss-Jordan消去法 完全ピポッド法
      
      入力: 左辺行列+右辺行列
            行列式計算結果域 []
      出力: 答行列
          行列式計算結果域に結果
    '''
    A = [e.copy() for e in PA]
    n = len(A)
    m = len(A[0]) 
    L = [_ for _ in range(n)]
    SD = 1
    for k in range(n):
        sw = abs(A[k][k])
        iw = k
        jw = k
        for j in range(k,n):
            for i in range(k,n):
                if sw < abs(A[i][j]):
                    sw = abs(A[i][j])
                    iw = i
                    jw = j
        if sw < E:
            return None
        if k != iw:
            SD = -SD
            for j in range(k,m):
                sw = A[k][j]
                A[k][j] = A[iw][j]
                A[iw][j] = sw
        if k != jw:
            SD = -SD
            for i in range(n):
                sw = A[i][k]
                A[i][k] = A[i][jw]
                A[i][jw] = sw
            mw = L[k]
            L[k] = L[jw]
            L[jw] = mw
        sw = A[k][k]
        if abs(sw) < E:
            return None
        
        SD *= sw
        kw = k +1
        for j in range(kw,m):
            A[k][j] /= sw
        for i in range(n):
            if i != k:
                sw = A[i][k]
                for j in range(kw,m):
                    A[i][j] -= sw * A[k][j]
    # 答を行入れ替え前に戻す
    nw = n
    for j in range(nw,m):
        sv = [e[j] for e in A]
        for i in range(n):
            ww = L[i]
            A[ww][j] = sv[i]
    if DET != None:
        DET[0] = SD
    return [e[n:] for e in A]

def matrix_dmp(msg, MAT):
    '''
     行列の印刷
    '''
    print(msg, " MATRIX:")
    if MAT is None:
        print("  結果がありません")
        return
    if len(MAT) == 0:
        A: list = [[]]
    else:
        if type(MAT[0]) == list:
            A = [e.copy() for e in MAT]
        else:
            A = [MAT]
    n = len(A)
    nm = len(A[0])
    for i in range(n):
        print("[",end='')
        if nm <= n:
            for j in range(nm):
                print(" % 8.3g" % (A[i][j]), end='')
        else:
            for j in range(n):
                print(" % 8.3g" % (A[i][j]), end='')
            print(" |",end='')
            for j in range(n,nm):
                print(" % 8.3g" % (A[i][j]), end='')
        print(" ]")

def chk(m):
    if type(m) == list:
        if len(m) == 0:
            return None
        else:
            if type(m[0]) != list:
                A = [m.copy()]
            else: 
                A = [e.copy() for e in  m]
        n = len(A)
        m = len(A[0])
    else:
        n = 0
        m = 0
    if m > (n*2) or m == 0: # 右辺は行数と同じ列数まで
        return None
    return A

if __name__ == '__main__':
    import numpy as np

    def p_header():
        print("実行結果: 答 = gl_complete_pivot(AB,DET=行列計算値) - Gauss-Jordan 完全ピボット")
        print("   本 パソコンBASIC数値計算Ⅰ  小島紀夫、町田東一著 東海大学出版会  1982,1994")
        print("       2.1.5 完全ピポッド法のプログラム")
        print("....")

    def ematrix(A):
        n = len(A)
        ma = []
        for i in range(n):
            ma.append(A[i][:n])
        la = np.linalg.matrix_rank(ma)
        lab = np.linalg.matrix_rank(A)
        print("ランク (A):",la)
        print("ランク(AB):",lab)
        if la == lab and la == n:
            print("答は一つ : ランク(A) == ランク(AB) == A行数 ",n,"x",n," 行列")
        elif la == lab and la < n:
            print("答は無限 : ランク(A) == ランク(AB) < A行数",n,"x",n," 行列")
        else:
            print("答はなし : ランク(A) < ランク(AB)",n,"x",n," 行列")

    def check_inv(A,am,det):
        n = len(A)
        if am is None or n == 0:
            return
        if type(A[0]) == list:
            MA = [e[:n] for e in A]
            Mb = [e[n:] for e in A]
        else:
            n = 1
            MA = [A[:n]]
            Mb = [A[n:]]
        if det != None:
            ndet = np.linalg.det(MA)
            if np.allclose(ndet,det):
                print("  == numpy det(): OK")
            else:
                print("  != numpy det() : NG??", ndet)
        ti = 1
        if len(MA[0]) == len(Mb[0]):
            #
            # (注意)同じ列数の右辺に単位列を定義したら逆行列として検算をする。
            #
            for i in range(n):
                if float(Mb[i][i]) != 1.0:
                    ti = 0
                    break
                for j in range(len(Mb[0])):
                    if i != j and float(Mb[i][j]) != 0.0:
                        ti = 0
                        break
        else:
            ti = 0
        if ti:
            ninv = np.linalg.inv(MA)
            if np.allclose(ninv, am):
                print("  == numpy inv(): OK")
            else:
                matrix_dmp("  != numpy inv(): NG??:",ninv)
        else:
            nslv = np.linalg.solve(MA,Mb)
            if np.allclose(nslv,am):
                print("  == numpy solve(): OK")
            else:
                matrix_dmp("  != numpy solve(): NG??", nslv.tolist())

    def test1(msg,A):
        print("◆◆◆◆",msg,"◆◆◆◆")
        matrix_dmp("入力:",A)
        A = chk(A)
        if A is None:
            print("計算できません")
            return
        if len(A) == len(A[0]):
            print("方程式の答はありません")
            return
        ematrix(A)
        det = None
        am = gj_complete_pivot(A,DET=det)
        if am is None:
            print("計算できません")
            return
        matrix_dmp("  答:", am)
        if det != None:
            adet = det[0]
            print("  Det: % .5f" % (adet))
            check_inv(A,am,adet)
        else:
            adet = 0;
            check_inv(A,am,None)

    p_header()
    test1("計算1",[[2,3]])
    test1("計算2",[[1,0.99,1.99],[0.99,0.98,1.97]])
    test1("計算3",[[0, 1, 3, 0,1], [1, 0, 2, 4,0], [0, 0, 0, 1,0], [5, -4, -4, 0,0]])
    test1("計算4",[[2.08,3.4,1.04,-0.28,1.28],[-1.68,-2.68,-0.84,0.16,-6.72],[5.14,3.12,-4.32,4.59,0.86],[3.12,2.8,1.56,1.88,4.62]])
    test1("逆行列計算1",[[0,2,1,0],[5,0,0,1]])
    test1("逆行列計算2",[[-1,1,1,1,0,0],[1,-1,1,0,1,0],[1,1,-1,0,0,1]])
    test1("逆行列計算3",[[1,3,9,1,0,0],[-1,1,-1,0,1,0],[2,-4,-2,0,0,1]])
    test1("逆行列計算4",[2,1])
    test1("逆行列計算5",[[2,-4,0,1,0,0],[3,-6,-2,0,1,0],[1,-2,1,0,0,1]])
    test1("逆行列計算6",[[-6,-2,-9,-2,1,0,0,0],[-10,3,-8,11,0,1,0,0],[7,-9,-9,5,0,0,1,0],[-11,8,5,5,0,0,0,1]])

2024-08-31 「CROUT法LU分解」
[crout-method.png]
参考:https://johnfoster.pge.utexas.edu/numerical-methods-book/LinearAlgebra_LU.html
   のなかの
   crout

     https://qiita.com/Sharkkii/items/47bbd6b0360a8431a316
     チョットワカル【LU分解】
        LU分解可能であるための条件(命題) 図を参照 

    Numerical Recipes in C     Second Edition
      Chapter 2. Solution of Linear Algebraic Equations
        ludcmp() , lubksb()

   https://stackoverflow.com/questions/5690010/lu-decomposition-from-numerical-recipes-not-working-what-am-i-doing-wrong
       LU Decomposition from Numerical Recipes not working; what am I doing wrong?

・・・
参考の1番目のcrout法のLU分解では、[[1, 2, 3], [2, 4, 8], [4, 1, 1]] の処理中にゼロデバイドでエラーになり分解されない。
....

import numpy as np

def crout(A):

    n = A.shape[0]

    U = np.zeros((n, n), dtype=np.double)
    L = np.zeros((n, n), dtype=np.double)

    for k in range(n):

        L[k, k] = A[k, k] - L[k, :] @ U[:, k]

        U[k, k:] = (A[k, k:] - L[k, :k] @ U[:k, k:]) / L[k, k]
        L[(k+1):, k] = (A[(k+1):, k] - L[(k+1):, :] @ U[:, k]) / U[k, k]

    return L, U

A = np.array([[1, 2, 3], [2, 4, 8], [4, 1, 1]])
L, U = crout(A)
print(L,U)
......
結果:

crout3.py:14: RuntimeWarning: divide by zero encountered in divide
  U[k, k:] = (A[k, k:] - L[k, :k] @ U[:k, k:]) / L[k, k]
crout3.py:14: RuntimeWarning: invalid value encountered in divide
  U[k, k:] = (A[k, k:] - L[k, :k] @ U[:k, k:]) / L[k, k]
[[ 1.  0.  0.]
 [ 2.  0.  0.]
 [ 4. nan nan]] [[ 1.  2.  3.]
 [ 0. nan inf]
 [ 0.  0. nan]]
...............

ほかのcrout法のプログラムもやってみたが同じようであった。

分解できない判定方法はあるのだろうか?
参考:チョットワカル【LU分解】 のLU分解可能であるための条件(命題)より
[LU-condition.png]
LU分解できる条件は首座小行列式が零でないということだそう。
[1, 2, 3] 1行目 [1], 2行目 [1,2]
[2, 4, 8]                       [2,4]
[4, 1, 1]        式=1         式= 0

[1, 2, 3] 1行目 [1], 2行目 [1,2], 3行目
[4, 1, 1]                       [4,1]
[2, 4, 8]        式=1         式= -7 式= -14

[0, 0, 3] 1行目 [0]
[-1,5, 2]             
[0,-1, 2]        式=0 

[-1,5, 2] 1行目 [-1], 2行目 [-1,5]
[ 0,0, 3]                        [ 0,0]
[0,-1, 2]        式=-1           式= 0

[-1,5, 2] 1行目 [-1], 2行目 [-1,5], 3行目
[0,-1, 2]                        [0,-1]
[0, 0, 3]        式=-1           式= 1  式= 3

ならば、行を入れ替えればLU分解はできるので納得。
もし結果がおかしいとなったら、行列の行入れ替えが起きたかどうかと、首座小行列式が零でないことをチェックする、

前のはあまりに良くなかったので、以下は定番のNumerical Recipeから。

実行:
------------
実行結果: LU,index,det-sign, ps, 行入れ替え = ludcmpt() - LU分解Mix
  (参照1) Numerical Recipes in C     Second Edition
       Chapter 2. Solution of Linear Algebraic Equations
        ludcmp() , lubksb()
  (参照2) https://stackoverflow.com/questions/5690010/lu-decomposition-from-numerical-recipes-not-working-what-am-i-doing-wrong
          LU Decomposition from Numerical Recipes not working; what am I doing wrong?
....

■◎◎ crout−1a ◎◎■
入力 A: [[1, 2, 3], [2, 4, 8], [4, 1, 1]]
ランク(A): 3  ,  3 x 3  行列
## My逆行列 ##
[ -0.2857  0.0714  0.2857 ]
[  2.1429 -0.7857 -0.1429 ]
[ -1.0000  0.5000  0.0000 ]
## 検算: ##
[  1.0000  0.0000  0.0000 ]
[  0.0000  1.0000  0.0000 ]
[  0.0000  0.0000  1.0000 ]
= numpy.inv()に等しい
My det(): 14.0
numpy det(): 14.000000000000004
..LU分離検算..
XA: [[1. 2. 3.]
 [2. 4. 8.]
 [4. 1. 1.]]
A: [[1, 2, 3], [2, 4, 8], [4, 1, 1]]
 P@L@U == A : OK

■◎◎ crout−1b ◎◎■
入力 A: [[2, 4, 8], [1, 2, 3], [4, 1, 1]]
ランク(A): 3  ,  3 x 3  行列
## My逆行列 ##
[  0.0714 -0.2857  0.2857 ]
[ -0.7857  2.1429 -0.1429 ]
[  0.5000 -1.0000  0.0000 ]
## 検算: ##
[  1.0000  0.0000  0.0000 ]
[  0.0000  1.0000 -0.0000 ]
[  0.0000  0.0000  1.0000 ]
= numpy.inv()に等しい
My det(): -14.0
numpy det(): -14.000000000000004
..LU分離検算..
XA: [[2. 4. 8.]
 [1. 2. 3.]
 [4. 1. 1.]]
A: [[2, 4, 8], [1, 2, 3], [4, 1, 1]]
 P@L@U == A : OK

■◎◎ crout−1c ◎◎■
入力 A: [[4, 1, 1], [1, 2, 3], [2, 4, 8]]
ランク(A): 3  ,  3 x 3  行列
## My逆行列 ##
[  0.2857 -0.2857  0.0714 ]
[ -0.1429  2.1429 -0.7857 ]
[  0.0000 -1.0000  0.5000 ]
## 検算: ##
[  1.0000  0.0000  0.0000 ]
[  0.0000  1.0000  0.0000 ]
[  0.0000  0.0000  1.0000 ]
= numpy.inv()に等しい
My det(): 14.0
numpy det(): 14.000000000000004
..LU分離検算..
XA: [[4. 1. 1.]
 [1. 2. 3.]
 [2. 4. 8.]]
A: [[4, 1, 1], [1, 2, 3], [2, 4, 8]]
 P@L@U == A : OK

■◎◎ crout−2A ◎◎■
入力 A: [[0, 0, 3], [-1, 5, 2], [0, -1, 2]]
ランク(A): 3  ,  3 x 3  行列
## My逆行列 ##
[  4.0000 -1.0000 -5.0000 ]
[  0.6667 -0.0000 -1.0000 ]
[  0.3333  0.0000  0.0000 ]
## 検算: ##
[  1.0000  0.0000 -0.0000 ]
[  0.0000  1.0000  0.0000 ]
[  0.0000  0.0000  1.0000 ]
= numpy.inv()に等しい
My det(): 3.0
numpy det(): 3.0000000000000004
..LU分離検算..
XA: [[ 0.  0.  3.]
 [-1.  5.  2.]
 [ 0. -1.  2.]]
A: [[0, 0, 3], [-1, 5, 2], [0, -1, 2]]
 P@L@U == A : OK

■◎◎ crout−2B ◎◎■
入力 A: [[-1, 5, 2], [0, -1, 2], [0, 0, 3]]
ランク(A): 3  ,  3 x 3  行列
## My逆行列 ##
[ -1.0000 -5.0000  4.0000 ]
[ -0.0000 -1.0000  0.6667 ]
[  0.0000  0.0000  0.3333 ]
## 検算: ##
[  1.0000  0.0000 -0.0000 ]
[  0.0000  1.0000 -0.0000 ]
[  0.0000  0.0000  1.0000 ]
= numpy.inv()に等しい
My det(): 3.0
numpy det(): 3.0000000000000004
..LU分離検算..
XA: [[-1.  5.  2.]
 [ 0. -1.  2.]
 [ 0.  0.  3.]]
A: [[-1, 5, 2], [0, -1, 2], [0, 0, 3]]
 P@L@U == A : OK

■◎◎ crout−2C ◎◎■
入力 A: [[0, -1, 2], [0, 0, 3], [-1, 5, 2]]
ランク(A): 3  ,  3 x 3  行列
## My逆行列 ##
[ -5.0000  4.0000 -1.0000 ]
[ -1.0000  0.6667 -0.0000 ]
[  0.0000  0.3333  0.0000 ]
## 検算: ##
[  1.0000  0.0000 -0.0000 ]
[  0.0000  1.0000 -0.0000 ]
[  0.0000  0.0000  1.0000 ]
= numpy.inv()に等しい
My det(): 3.0
numpy det(): 3.0000000000000004
..LU分離検算..
XA: [[ 0. -1.  2.]
 [ 0.  0.  3.]
 [-1.  5.  2.]]
A: [[0, -1, 2], [0, 0, 3], [-1, 5, 2]]
 P@L@U == A : OK

■◎◎ crout−3 ◎◎■
入力 A: [[0, 1, 3, 0], [1, 0, 2, 4], [0, 0, 0, 1], [5, -4, -4, 0]]
ランク(A): 4  ,  4 x 4  行列
## My逆行列 ##
[  4.0000 -4.0000  16.0000  1.0000 ]
[  7.0000 -7.5000  30.0000  1.5000 ]
[ -2.0000  2.5000 -10.0000 -0.5000 ]
[  0.0000  0.0000  1.0000  0.0000 ]
## 検算: ##
[  1.0000  0.0000 -0.0000  0.0000 ]
[ -0.0000  1.0000 -0.0000  0.0000 ]
[  0.0000  0.0000  1.0000  0.0000 ]
[  0.0000  0.0000  0.0000  1.0000 ]
= numpy.inv()に等しい
My det(): -1.9999999999999973
numpy det(): -1.9999999999999982
..LU分離検算..
XA: [[ 0.  1.  3.  0.]
 [ 1.  0.  2.  4.]
 [ 0.  0.  0.  1.]
 [ 5. -4. -4.  0.]]
A: [[0, 1, 3, 0], [1, 0, 2, 4], [0, 0, 0, 1], [5, -4, -4, 0]]
 P@L@U == A : OK

■◎◎ crout−4 ◎◎■
入力 A: [[0, 4, 1, 0], [1, 0, 2, 2], [0, 0, 0, 0], [0, 0, 0, 1]]
ランク(A): 3  ,  4 x 4  行列
## My逆行列 ##
  結果がありません
--- - - - - - - - - 

プログラム:
---- crout-lu3.py -----

'''
(参照1) Numerical Recipes in C     Second Edition
     Chapter 2. Solution of Linear Algebraic Equations
      ludcmp()
(参照2) https://stackoverflow.com/questions/5690010/lu-decomposition-from-numerical-recipes-not-working-what-am-i-doing-wrong
        LU Decomposition from Numerical Recipes not working; what am I doing wrong?
'''
def ludcmp(PA, EPS=1.0e-7):
    '''
     LU分解
    入力: A 行列
    出力: LU 形式 | xUU |
                      | LxU |
                      | LLx |
        INDEX
        Sign 行列式符号
             P     行の並び   [0,1,2,3]
    '''
    n = len(PA)
    m = len(PA[0])
    if type(PA) != list or type(PA[0]) != list or n != m:
        return None, None, None, None
    A = [e.copy() for e in PA]
    vv: list = [0] * n
    index: list = [0] * n
    P = [ _ for _ in range(n)]
    imax = -1
    d = 1.0
    for i in range(n):
        big = 0
        for j in range(n):
            temp = abs(A[i][j])
            if temp > big:
                big = temp
        if big < EPS:
            return None, None, None, None
        vv[i] = 1.0 / big
    for j in range(n):           # crout method Loop
        for i in range(j):
            sum = A[i][j]
            for k in range(i):
                sum -= A[i][k] * A[k][j]
            A[i][j] = sum
        big = 0
        for i in range(j,n):
            sum = A[i][j]
            for k in range(j):
                sum -= A[i][k] * A[k][j]
            A[i][j] = sum
            dum = vv[i] * abs(sum)
            if dum >= big:
                big = dum
                imax = i
        if j != imax:
            for k in range(n):
                dum = A[imax][k]
                A[imax][k] = A[j][k]
                A[j][k] = dum
            xs = P[imax]
            P[imax] = P[j]
            P[j] = xs
            d = -d
            vv[imax] = vv[j]
        index[j] = imax
        if j != (n-1):
            dum = 1.0 / A[j][j]
            for i in range(j+1,n):
                A[i][j] *= dum
    return A, index, d, P

def lubksb(A,index,Pb):
    n = len(A)
    b = [ e for e in Pb]
    for i in range(n):
        ip = index[i]
        sum = b[ip]
        b[ip] = b[i]
        for j in range(i):
            sum -= A[i][j] * b[j]
        b[i] = sum
    for i in range(n-1, -1, -1):
        sum = b[i]
        for j in range(i+1,n):
            sum -= A[i][j] * b[j]
        b[i] = sum / A[i][i]
    return b

#--^^^

def lu_inverse(PA):
    n = len(PA)
    INV = [[0 for _ in range(n)] for _ in range(n)]
    LU, P, _ , _ = ludcmp(PA)
    if LU is None:
        return None
    for i in range(n):
        b = [0.0 if k != i else 1 for k in range(n)]
        x = lubksb(LU,P,b)
        for ln in range(n):
            INV[ln][i] = x[ln]
    return INV

def get_low(A):
    '''                LOWmatrix
    A is mixed LU ==>> |1,0,0|
                       |9,1,0|
                       |9,9,1|
    '''
    n = len(A)
    low = [[0 if j != i else 1 for j in range(n)] for i in range(n)]
    for i in range(n):
        for j in range(n):
            if j < i:
                low[i][j] = A[i][j]
    return low

def get_up(A):
    '''                UPmatrix
    A is mixed LU ==>> |9,9,9|
                       |0,9,9|
                       |0,0,9|
    '''
    n = len(A)
    up = [[0 if j != i else 1 for j in range(n)] for i in range(n)]
    for i in range(n):
        for j in range(n):
            if j >= i:
                up[i][j] = A[i][j]
    return up

def get_liinf(P):
    '''              Pmatrix
    P:[0,1,2,3] ==>> |1,0,0|   使い方: (Pmatrix @ LOWmatrix @ UPmatrix) == A matrix 
                     |0,1,0|
                     |0,0,1|
    '''
    n = len(P)
    Pm: list = [[] for _ in range(n)]
    for i in range(n):
        Pm[P[i]] = [0 if j != i else 1 for j in range(n)]
    return Pm

def pmatrix(msg, MAT):
    '''
     行列の印刷
    '''
    print("##",msg,"##")
    if MAT is None:
        print("  結果がありません")
        return
    n = len(MAT)
    m = len(MAT[0])
    for i in range(n):
        print("[",end='')
        for j in range(m):
            print(" % .4f" % (MAT[i][j]), end='')
        print(" ]")

if __name__ == "__main__":
    import numpy as np

    def p_header():
        print("実行結果: LU,index,det-sign, ps, 行入れ替え = ludcmpt() - LU分解Mix")
        print("  (参照1) Numerical Recipes in C     Second Edition")
        print("       Chapter 2. Solution of Linear Algebraic Equations")
        print("        ludcmp() , lubksb()")
        print("  (参照2) https://stackoverflow.com/questions/5690010/lu-decomposition-from-numerical-recipes-not-working-what-am-i-doing-wrong")
        print("          LU Decomposition from Numerical Recipes not working; what am I doing wrong?")
        print("....")

    def ematrix(A):
        la = np.linalg.matrix_rank(A)
        print("ランク(A):",la, " , ",len(A) , "x",len(A[0])," 行列")

    def test_inv(msg, A):
        print('')
        print("■◎◎",msg,"◎◎■")
        print("入力 A:",A)
        ematrix(A)
        plu_inv = lu_inverse(A)
        pmatrix( "My逆行列", plu_inv)
        if plu_inv is not None:
            pmatrix("検算:",np.dot(plu_inv,A))
            ninv = np.linalg.inv(A)
            if np.allclose(plu_inv, ninv):
                print("= numpy.inv()に等しい")
            else:
                print("= numpy.inv()と違う??")
                pmatrix("numpy:",ninv)
            LU, _, ds, PP = ludcmp(A)
            det = 1
            for ti in range(len(A)):
                det *= LU[ti][ti]
            det *= ds
            print("My det():", det)
            print("numpy det():", np.linalg.det(A))
            print("..LU分離検算..")
            LU, _ , _ , PP = ludcmp(A)
            PMT = get_liinf(PP)
            XL= get_low(LU)
            XU = get_up(LU)
            XA = np.dot(np.dot(PMT,XL),XU)
            print("XA:",XA)
            print("A:",A)
            if np.allclose(XA,np.array(A)):
                print(" P@L@U == A : OK")
            else:
                print(" P@L@U == A : NG")

    p_header()
    test_inv("crout−1a",[[1,2,3],[2,4,8],[4,1,1]])
    test_inv("crout−1b",[[2,4,8],[1,2,3],[4,1,1]])
    test_inv("crout−1c",[[4,1,1],[1,2,3],[2,4,8]])
    test_inv("crout−2A",[[0,0,3],[-1,5,2],[0,-1,2]])
    test_inv("crout−2B",[[-1,5,2],[0,-1,2],[0,0,3]])
    test_inv("crout−2C",[[0,-1,2],[0,0,3],[-1,5,2]])
    test_inv("crout−3",[[0, 1, 3, 0], [1, 0, 2, 4], [0, 0, 0, 1], [5, -4, -4, 0]])
    test_inv("crout−4",[[0, 4, 1, 0], [1, 0, 2, 2], [0, 0, 0, 0], [0, 0, 0, 1]])

2024-09-14  「行列計算 ガウスザイディル計算」
ガウスザイディル法で、反復法の行列計算をやってみた。
直接法で答のでるものが反復法では出ないものがある。

対角優位行列判定をすればよいとあったが、判定が否であっても反復法で収束する場合がある。
計算途中で収束しなかったらエラー扱いとした。

                   n
                  +--
               >   \
      A[i][i]  =   /  | A[i][j] | (j=1,2,...,n && j != i) THEN "対角優位"
                  +--
                  j=1 
      ELSE:                                                    "対角優位でない"

実行:
$ python GSeidel20.py
実行結果: 答,行入れ替え,ワーニング,計算回数 = gauss_seidel2() - GMRES法
  参照:https://en.wikipedia.org/wiki/Gauss%E2%80%93Seidel_method
       Gauss–Seidel method
       http://nkl.cc.u-tokyo.ac.jp/15n/SolverIterative-25-29.pdf
      SolverIterative-25-29.pdf
      https://kishorkafle.medium.com/python-code-for-guass-seidel-method-fe948e4f46d2
      Python Code for Guass-Seidel Method
       数値計算    高橋大輔著  岩波 1996,2022
        SORアルゴリズムより ω=1でガウスディザイル法
....

 計算−1  ● ***Results***
A ---
[[8.0, 5.0, -3.0, 4.0], [4.0, 3.0, -1.0, 2.0], [2.0, 2.0, -1.0, 1.0], [3.0, 3.0, -2.0, 2.0]]
B ---
[12.0, 6.0, 4.0, 6.0]
**Answers**
行入れ替え情報: [0, 1, 2, 3]
答 --
 1
 1
 -1
 -1
..検算:
 -8.4957e-07
 -4.24588e-07
 -2.12152e-07
 0
..収束回数: 50
..警告: 1

 計算−2  ● ***Results***
A ---
[[3, 2, 1], [1, 4, 1], [2, 2, 5]]
B ---
[10, 12, 21]
**Answers**
行入れ替え情報: [0, 1, 2]
答 --
 1
 2
 3
..検算:
 8.41962e-08
 7.25989e-08
 0
..収束回数: 13
..警告: 0

 計算−3  ● ***Results***
A ---
[[0, -2, 0], [-1, 5, 2], [0, -1, 1]]
B ---
[1, 0, 0]
**Answers**
行入れ替え情報: [1, 0, 2]
答 --
 -3.5
 -0.5
 -0.5
..検算:
 0
 0
 0
..収束回数: 2
..警告: 3

 計算−4  ● ***Results***
A ---
[[0, 0, 3], [-1, 5, 2], [0, -1, 2]]
B ---
[1, 0, 0]
**Answers**
行入れ替え情報: [1, 2, 0]
答 --
 4
 0.666667
 0.333333
..検算:
 0
 -2.22045e-16
 0
..収束回数: 3
..警告: 5

 計算−5.  ● ***Results***
A ---
[[2, -1, -1], [-1, 3, -1], [-1, -1, 1]]
B ---
[1, 0, 0]
**Answers**
行入れ替え情報: [0, 1, 2]
 計算したが、収束しない
答 --
 168996
 134408
 303403
..収束回数: 45
..警告: -1001

 計算−6  ● ***Results***
A ---
[[0.0, 1.0], [1.0, 0.0]]
B ---
[1.0, 0.0]
**Answers**
行入れ替え情報: [1, 0]
答 --
 0
 1
..検算:
 0
 0
..収束回数: 1
..警告: 0

 計算−7  ● ***Results***
A ---
[0.0]
B ---
0
**Answers**
 計算できません
 警告: 200

 計算−8  ● ***Results***
A ---
[[4]]
B ---
[1]
**Answers**
行入れ替え情報: [0]
答 --
 0.25
..検算:
 0
..収束回数: 1
..警告: 0

oooooooooooooooooo
TEST MATRIX No. 1
  30 x 30 行列
..検算:
 OK
..収束回数: 12
..警告: 1

TEST MATRIX No. 2
  34 x 34 行列
..検算:
 OK
..収束回数: 8
..警告: 0

TEST MATRIX No. 3
  21 x 21 行列
..検算:
 OK
..収束回数: 8
..警告: 0

TEST MATRIX No. 4
  23 x 23 行列
..検算:
 OK
..収束回数: 8
..警告: 0

TEST MATRIX No. 5
  10 x 10 行列
..検算:
 OK
..収束回数: 33
..警告: 1

〜〜〜〜〜〜
プログラム:

---- GSeidel20.py ----
'''
参考:
   https://en.wikipedia.org/wiki/Gauss%E2%80%93Seidel_method
   Gauss–Seidel method

  http://nkl.cc.u-tokyo.ac.jp/15n/SolverIterative-25-29.pdf
  SolverIterative-25-29.pdf

  https://kishorkafle.medium.com/python-code-for-guass-seidel-method-fe948e4f46d2
  Python Code for Guass-Seidel Method

   数値計算    高橋大輔著  岩波 1996,2022
      SORアルゴリズムより ω=1でガウスディザイル法
'''
def check_d(A):
    '''
     対角優位行列判定  判定が否であっても反復法で収束する場合がある。注意事項の扱い。
                     計算途中で収束しなかったらエラー扱い。
                   n
                  +--
               >   \
      A[i][i]  =   /  | A[i][j] | (j=1,2,...,n && j != i) THEN return 0
                  +--
                  j=1 
      ELSE:                                                    return 1 # Worninng
    
    '''
    r = len(A)
    ok = 0
    for i in range(r):
        non_diagnl = 0
        for j in range(r):
            non_diagnl += abs(A[i][j])
        if abs(A[i][i]) < (non_diagnl-abs(A[i][i])):
            ok = 1
    return ok

def check_z(A, B):
    '''
     対角成分 ゼロチェック、ゼロならば行を入れ替える。対角成分にゼロがあると計算できない判定。
        対角成分は1行目から、1回しか見ない。

     A[i][i] == 0 THEN A[i] <=> A[x]; B[i] <=> B[x]; P[i] <=> P[x];
    '''
    r = len(A)
    m = len(A[0])
    P = [ _ for _ in range(r)]
    A0 = [e.copy() for e in A]
    B0 = [e for e in B]

    for i in range(r):
        if float(A0[i][i]) == 0.0:
            for j in range(i+1,r):
                if float(A0[j][i]) != 0.0:
                    for x in range(m):
                        xs = A0[i][x]
                        A0[i][x] = A0[j][x]
                        A0[j][x] = xs
                    xp = P[i]
                    P[i] = P[j]
                    P[j] = xp
                    xs = B0[i]
                    B0[i] = B0[j]
                    B0[j] = xs
                    break
            else:
                return None,None, None
    return A0, B0, P

def allclose(a,b,E=1e-8):
    '''
     ベクトル比較
    '''
    n = len(a)
    for i in range(n):
        if abs(a[i]-b[i]) >= E:
            return False
    return True

def gauss_seidel(A, B, EPS=1.0e-7, iterMax=100):
    '''
     GAUSS-SEIDEL Method
    '''
    n = len(A)
    if type(A[0]) != list:
        m = 1
    else:
        m = len(A[0])

    #initial value
    X = [0.0 for _ in range(n)]

    difference = [1.0 for _ in range(n)]
    error = 0.0

    A1 , B1, P = check_z(A,B)  
    if A1 is None:
        return None, None, 200, 0
    #
    #               n
    #              +--
    #           >   \
    #  A[i][i]  =   /  | A[i][j] | (j=1,2,...,n && j != i) THEN chkf = 0
    #              +--
    #              j=1 
    #  ELSE:                                                    chkf = 1  # Worning
    #                           ( 行入れ替えた後 )
    chkf = check_d(A1)
    if n == 1:
        if abs(A1[0][0]) < EPS:
            return None, None, 200, 1
        else:
            X[0] = B1[0] / A1[0][0]
        return X, [0], 0, 1

    ec = 0
    for iter in range(iterMax+1):
        x_new = [0.0 for _ in range(n)]
        for i in range(n):
            s1 = 0.0
            s2 = 0.0
            for j in range(i):
                s1 += A1[i][j] * x_new[j]
            for j in range(i+1,n):
                s2 += A1[i][j] * X[j]
            x_new[i] = (B1[i] - s1 - s2) / A1[i][i]
        if allclose(x_new, X, E=EPS):
            break
        if (abs(x_new[0]) - abs(X[0])) > 0:
            ec += 1
            if ec > iterMax:
                return X, P, -((chkf & 1)+1000), iter
        X = x_new
       
    else:
        return None, P, chkf, iter
    '''
     X : 答
     P : 行の入れ替え順列
     chkf : 「(chkf & 1) == 1」 対角優位行列でない, 「(chkf & 0xFFFE) == 999」 答が大きくなり続けることがあった
       「 chkf == -1000 or -1001」 答が計算できないことになった
     iter : 計算繰り返し数
    '''
    return X, P, chkf, iter

def gauss_seidel2(A, B, EPS=1.0e-7, iterMax=100):
    '''
     GAUSS-SEIDEL Method
    '''
    n = len(A)
    if type(A[0]) != list:
        m = 1
    else:
        m = len(A[0])

    #initial value
    X = [0.0 for _ in range(n)]

    difference = [1.0 for _ in range(n)]
    error = 0.0

    A1 , B1, P = check_z(A,B)  
    if A1 is None:
        return None, None, 200, 0
    #
    #               n
    #              +--
    #           >   \
    #  A[i][i]  =   /  | A[i][j] | (j=1,2,...,n && j != i) THEN chkf = 0
    #              +--
    #              j=1 
    #  ELSE:                                                    chkf = 1  # Worning
    #                           ( 行入れ替えた後 )
    chkf = check_d(A1)
    if n == 1:
        if abs(A1[0][0]) < EPS:
            return None, None, 200, 1
        else:
            X[0] = B1[0] / A1[0][0]
        return X, [0], 0, 1
    '''
     数値計算    高橋大輔著  岩波 1996,2022
      SORアルゴリズムより ω=1でガウスディザイル法
    '''
    cks = -1
    for iter in range(iterMax+1):
        error = 0
        sum = 0
        for i in range(n):
            sums = 0
            for j in range(m):
                if (i != j):
                    sums += A1[i][j] * X[j]
            new_ = (B1[i] - sums) / A1[i][i]
            sum += abs(new_)
            error += abs(new_ - X[i])
            X[i] = new_

        if error <= (EPS * sum):
            break
        if cks >= 0:
            if cks < error:
                chkf += 2
                if chkf > (iterMax-10):
                    return X, P, -((chkf & 1)+1000), iter
        cks = error
    else:
        return None, P, chkf, iter
    '''
     X : 答
     P : 行の入れ替え順列
     chkf : 「(chkf & 1) == 1」 対角優位行列でない, 「(chkf & 0xFFFE) == 999」 答が大きくなり続けることがあった
       「 chkf == -1000 or -1001」 答が計算できないことになった
     iter : 計算繰り返し数
    '''
    return X, P, chkf, iter

def chk(a,b):
    if type(a) == list:
        if len(a) == 0:
            return None
        else:
            if type(a[0]) != list:
                A = [a.copy()]
            else: 
                A = [e.copy() for e in  a]
        n = len(A)
        m = len(A[0])
    else:
        n = 0
        m = 0
    if m != n or n == 0: # 正方行列のみ
        return None, None
    if type(b) == list:
        if len(b) == 0:
            return None, None
        if type(b[0]) == list:
            return None, None
    else:
        b = [b]
    nb = len(b)
    if nb != n or nb == 0:
        return None, None

    return A,b

if __name__ == '__main__':
    import numpy as np

    def p_header():
        print("実行結果: 答,行入れ替え,ワーニング,計算回数 = gauss_seidel2() - GMRES法")
        print("  参照:https://en.wikipedia.org/wiki/Gauss%E2%80%93Seidel_method")
        print("       Gauss–Seidel method")
        print("       http://nkl.cc.u-tokyo.ac.jp/15n/SolverIterative-25-29.pdf")
        print("      SolverIterative-25-29.pdf")
        print("      https://kishorkafle.medium.com/python-code-for-guass-seidel-method-fe948e4f46d2")
        print("      Python Code for Guass-Seidel Method")
        print("       数値計算    高橋大輔著  岩波 1996,2022")
        print("        SORアルゴリズムより ω=1でガウスディザイル法")
        print("....")

    def gen_matrix(n=0, RMAX=50, DCP=1):
        '''
            行列生成 N x N
              n = 0 : ランダムNxN , 9 : 9 x 9行列
              RMAX = 50 : (+-50)で要素データ、 99: (+-99)で要素データ
              DCP = 1 : 要素データ * 10,  +9 : 要素データ * (10**9) 、 -9 : 要素データ / (10**9)
        '''
        import random as r
        DC = 10**abs(DCP)
        if n == 0:
            N = r.randrange(10,41) # 10x10 ~ 40x40の行列を作る
        else:
            N = n                  # n x n の行列を作る
        nx = r.randrange(N*4)  # 時々、対角優位行列でなくする
        m = []
        for i in range(N):
            m.append([r.randrange(-RMAX,RMAX+1) for j in range(N)])
        for i in range(N):
            if i != nx:
                ml = 0
                for j in range(N):
                    if i != j:
                        ml += abs(m[i][j])
                if m[i][i] < 0:
                    m[i][i] -= ml
                else:
                    m[i][i] += ml
        for i in range(N):
            for j in range(N):
                if DCP < 0:
                    m[i][j] /= DC
                else:
                    m[i][j] *= DC

        b = [0 if (j & 11) == 0 else r.randrange(-RMAX,RMAX+1) for j in range(N)]
        for i in range(N):
            if DCP < 0:
                b[i] /= DC
            else:
                b[i] *= DC
        return m,b

    def print_ans(a):
        print("答 --")
        for i in a:
            print(" %.6g" % (i))

    def testMatrix(nc):
        for n in range(1, nc+1):
            print("")
            print("TEST MATRIX No.", n)
            A, b = gen_matrix(RMAX=360, DCP=-2)
            nn = len(A)
            print("  %d x %d 行列" % (nn,nn)) 
            ret = gauss_seidel2(A,b)
            #ret = gauss_seidel(A, b)
            if ret[0] is None:         # 収束できない、左辺行列がない、左辺行列式が零
                print(" 計算できません")
                print(" 収束回数:", ret[3])
                print(" 警告:", ret[2])
            else:
                if ret[2] < 0:          # 計算しないとわからない収束しない左辺行列
                    print(" 計算したが、収束しない")
                    for i in ret[0]:
                        print(" %.6g" % (i))
                else:
                    print("..検算:")
                    Bb = np.array([ret[0]]).T
                    diff = np.dot(A,Bb)
                    dif = [b] - diff.T
                    for i in dif[0]:
                        if i >= 0.0001:
                            print(" NG??", i)
                            print("A ---N:", len(A))
                            print(A)
                            print("B ---")
                            print(b)
                            print_ans(ret[0])
                            break
                    else:
                        print(" OK")
                print("..収束回数:", ret[3])
                print("..警告:", ret[2])
            
    def test(msg,mat, mb):

        print("\n",msg," ● ***Results***")
        print("A ---")
        print(mat)
        print("B ---")
        print(mb)
        print("**Answers**")
        A, b = chk(mat,mb)
        if A is None:               # 左辺行列がない
            print("計算できません")
            return
        ret = gauss_seidel2(A, b)
        #ret = gauss_seidel(A, b)
        if ret[0] is None:          # 収束できない、左辺行列式が零
            print(" 計算できません")
            print(" 警告:", ret[2])
        else:
            print("行入れ替え情報:", ret[1])
            if ret[2] < 0:          # 計算しないとわからない収束しない左辺行列
                print(" 計算したが、収束しない")
                print_ans(ret[0])
            else:
                print_ans(ret[0])
                Bb = np.array([ret[0]]).T
                diff = np.dot(A,Bb)
                print("..検算:")
                dif = [b] - diff.T
                for i in dif[0]:
                    print(" %.6g" % (i))
            print("..収束回数:", ret[3])
            print("..警告:", ret[2])

    p_header()
    test("計算−1", [[8.0,5.0,-3.0,4.0],[4.0,3.0,-1.0,2.0],[2.0,2.0,-1.0,1.0],[3.0,3.0,-2.0,2.0]],[12.0,6.0,4.0,6.0]) # original
    test("計算−2",[[3,2,1],[1,4,1],[2,2,5]],[10,12,21])
    test("計算−3",[[0,-2,0],[-1,5,2],[0,-1,1]],[1,0,0])
    test("計算−4",[[0,0,3],[-1,5,2],[0,-1,2]],[1,0,0])
    test("計算−5.",[[2,-1,-1],[-1,3,-1],[-1,-1,1]],[1,0,0])
    test("計算−6",[ [0.0, 1.0],[1.0, 0.0] ], [1.,0.])
    test("計算−7",[0.0], 0)
    test("計算−8",[[4]],[1])
    print("\noooooooooooooooooo",end='')
    testMatrix(5)
---
2024-09-14  「逆行列計算2.1」
反復法 GMRES法で、逆行列計算をやってみた。
行列の内容によっては解法結果がでない場合がある。
いろいろやったみたら、行の絶対値の小さい順に行を並び替えたらできるようである。
やってみたらのことなのでそのつもりで見てください。

 参考:
    https://tech-commonplace.com/gmres_method/
    C言語によるGMRES法の実装

    https://medium.com/@giorgio.martinez1926/understanding-gmres-using-python-3c314fac1264
    Understanding GMRES using python

    https://stackoverflow.com/questions/52951533/following-code-i-have-made-an-sor-iteration-in-python
    following code I have made an SOR iteration in python


「C言語によるGMRES法の実装」より、C言語のプログラムをPYTHONに変換した。ありがとうございます。
ちょっと修正しました。

実行:
$ python cgmres.py
実行結果: 答 = gmres() - GMRES法
  参照:https://tech-commonplace.com/gmres_method/
         C言語によるGMRES法の実装
       https://medium.com/@giorgio.martinez1926/understanding-gmres-using-python-3c314fac1264
         Understanding GMRES using python
....
--- 逆行列計算 --- テスト1
A: [[2.0, 3.0, 1.0, -3.0], [-1.0, 2.0, 2.0, 4.0], [4.0, 1.0, -3.0, 5.0], [5.0, -4.0, -4.0, 1.0]]
ランク(A): 4    4 x 4 行列
--scipy.sparse.linalg.gmres 逆行列--
[[ 0.21052632  0.22807018 -0.10526316  0.24561404]
 [ 0.06140351 -0.16959064  0.21929825 -0.23391813]
 [ 0.18421053  0.49122807 -0.34210526  0.29824561]
 [-0.07017544  0.14619883  0.03508772  0.02923977]]
--My gmres 逆行列--
[[ 0.21052632  0.22807018 -0.10526316  0.24561404]
 [ 0.06140351 -0.16959064  0.21929825 -0.23391813]
 [ 0.18421053  0.49122807 -0.34210526  0.29824561]
 [-0.07017544  0.14619883  0.03508772  0.02923977]]
 scipy gmres() inv: OK

--- 逆行列計算 --- テスト2
A: [[2, 3], [4, 2]]
ランク(A): 2    2 x 2 行列
--scipy.sparse.linalg.gmres 逆行列--
[[-0.25   0.375]
 [ 0.5   -0.25 ]]
--My gmres 逆行列--
[[-0.25   0.375]
 [ 0.5   -0.25 ]]
 scipy gmres() inv: OK

--- 逆行列計算 --- テスト3
A: [[1, 2, 3], [2, 4, 8], [4, 1, 1]]
ランク(A): 3    3 x 3 行列
--scipy.sparse.linalg.gmres 逆行列--
[[-2.85714286e-01  7.14285714e-02  2.85714286e-01]
 [ 2.14285714e+00 -7.85714286e-01 -1.42857143e-01]
 [-1.00000000e+00  5.00000000e-01 -6.83650965e-17]]
--My gmres 逆行列--
[[-2.85714286e-01  7.14285714e-02  2.85714286e-01]
 [ 2.14285714e+00 -7.85714286e-01 -1.42857143e-01]
 [-1.00000000e+00  5.00000000e-01 -4.00401163e-16]]
 scipy gmres() inv: OK

--- 逆行列計算 --- テストB-1.2.3
A: [[0, 0, 3], [1, 5, 2], [0, 1, 0]]
ランク(A): 3    3 x 3 行列
--scipy.sparse.linalg.gmres 逆行列--
[[-6.66666667e-01  1.00000000e+00 -5.00000000e+00]
 [ 0.00000000e+00  0.00000000e+00  1.00000000e+00]
 [ 3.33333333e-01  0.00000000e+00  3.19211673e-16]]
--My gmres 逆行列--
[[-6.66666667e-01  1.00000000e+00 -5.00000000e+00]
 [ 1.22124533e-15 -3.89088944e-16  1.00000000e+00]
 [ 3.33333333e-01 -2.22044605e-16  1.08815408e-15]]
 scipy gmres() inv: OK

--- 逆行列計算 --- テストB-1,3,2
A: [[0, 0, 3], [0, 1, 0], [1, 5, 2]]
ランク(A): 3    3 x 3 行列
--scipy.sparse.linalg.gmres 逆行列--
[[-6.66666667e-01 -5.00000000e+00  1.00000000e+00]
 [ 0.00000000e+00  1.00000000e+00  0.00000000e+00]
 [ 3.33333333e-01 -7.46368420e-18  0.00000000e+00]]
--My gmres 逆行列--
[[-6.66666667e-01 -5.00000000e+00  1.00000000e+00]
 [ 1.22124533e-15  1.00000000e+00 -3.89088944e-16]
 [ 3.33333333e-01  1.08815408e-15 -2.22044605e-16]]
 scipy gmres() inv: OK

--- 逆行列計算 --- テストB-2,1,3
A: [[1, 5, 2], [0, 0, 3], [0, 1, 0]]
ランク(A): 3    3 x 3 行列
--scipy.sparse.linalg.gmres 逆行列--
[[ 1.00000000e+00 -6.66666667e-01 -5.00000000e+00]
 [ 0.00000000e+00 -1.46331040e-17  1.00000000e+00]
 [ 0.00000000e+00  3.33333333e-01  7.29780195e-17]]
--My gmres 逆行列--
[[ 1.00000000e+00 -6.66666667e-01 -5.00000000e+00]
 [-3.89088944e-16  1.22124533e-15  1.00000000e+00]
 [-2.22044605e-16  3.33333333e-01  1.08815408e-15]]
 scipy gmres() inv: OK

--- 逆行列計算 --- テストB-2,3,1
A: [[1, 5, 2], [0, 1, 0], [0, 0, 3]]
ランク(A): 3    3 x 3 行列
--scipy.sparse.linalg.gmres 逆行列--
[[ 1.         -5.         -0.66666667]
 [ 0.          1.          0.        ]
 [ 0.          0.          0.33333333]]
--My gmres 逆行列--
[[ 1.00000000e+00 -5.00000000e+00 -6.66666667e-01]
 [-3.89088944e-16  1.00000000e+00  1.22124533e-15]
 [-2.22044605e-16  1.08815408e-15  3.33333333e-01]]
 scipy gmres() inv: OK

--- 逆行列計算 --- テストB-3,1,2
A: [[0, 1, 0], [0, 0, 3], [1, 5, 2]]
ランク(A): 3    3 x 3 行列
--scipy.sparse.linalg.gmres 逆行列--
[[-5.00000000e+00 -6.66666667e-01  1.00000000e+00]
 [ 1.00000000e+00  1.37599254e-17  0.00000000e+00]
 [ 0.00000000e+00  3.33333333e-01  0.00000000e+00]]
--My gmres 逆行列--
[[-5.00000000e+00 -6.66666667e-01  1.00000000e+00]
 [ 1.00000000e+00  1.22124533e-15 -3.89088944e-16]
 [ 1.08815408e-15  3.33333333e-01 -2.22044605e-16]]
 scipy gmres() inv: OK

--- 逆行列計算 --- テストB-3,2,1
A: [[0, 1, 0], [1, 5, 2], [0, 0, 3]]
ランク(A): 3    3 x 3 行列
--scipy.sparse.linalg.gmres 逆行列--
[[-5.00000000e+00  1.00000000e+00 -6.66666667e-01]
 [ 1.00000000e+00  0.00000000e+00  1.39944079e-17]
 [ 0.00000000e+00  0.00000000e+00  3.33333333e-01]]
--My gmres 逆行列--
[[-5.00000000e+00  1.00000000e+00 -6.66666667e-01]
 [ 1.00000000e+00 -3.89088944e-16  1.22124533e-15]
 [ 1.08815408e-15 -2.22044605e-16  3.33333333e-01]]
 scipy gmres() inv: OK

... 方程式解法計算 ...
A: [[], []]
b: []
計算できません

... 方程式解法計算 ...
A: [0.0]
b: 0
ランク(A): 0    1 x 1 行列
方程式計算できません

... 方程式解法計算 ...
A: [[1, 2], [3, 4]]
b: [0, 1]
ランク(A): 2    2 x 2 行列
x = 
1.000000, -0.500000, 
--scipy.sparse.linalg.gmres 答:
1.000000, -0.500000, 

... 方程式解法計算 ...
A: [[1.0, 3.0, 9.0], [-1.0, 1.0, -1.0], [2.0, -4.0, -2.0]]
b: [1, 0, 0]
ランク(A): 2    3 x 3 行列
方程式計算できません
...

プログラム:

---- cgmres.py ----
'''
 参考:
    https://tech-commonplace.com/gmres_method/
    C言語によるGMRES法の実装

    https://medium.com/@giorgio.martinez1926/understanding-gmres-using-python-3c314fac1264
    Understanding GMRES using python

'''
import math

# 転置行列
def transpose(row, col, mat, mat_T):
    for i in range(row):
        for j in range(col):
            mat_T[j][i] = mat[i][j]

# k * vec = ans
def vec_multi(n, vec, k, ans):
    for i in range(n):
        ans[i] = vec[i] * k

# vec / k = ans
def vec_div(n,vec,k, ans):
    for i in range(n):
        ans[i] = vec[i] / k

# mat*vec = ans
def mat_multi_vec(row, col, mat, vec, ans):
    for i in range(row):
        ans[i] = 0.0
        for j in range(col):
            ans[i] += mat[i][j] * vec[j]

# vec1 + vec2 = ans
def vec_add_vec(n, vec1, vec2, ans):
    for i in range(n):
        ans[i] = vec1[i] + vec2[i]

# vec1 - vec2 = ans
def vec_sub_vec(n, vec1, vec2, ans):
    for i in range(n):
        ans[i] = vec1[i] - vec2[i]

# 代入
def vec_subs_vec(n, vec, ans):
    for i in range(n):
        ans[i] = vec[i]

# 内積
def dot(n, vec1, vec2):
    ans = 0.0;
    for i in range(n):
        ans += vec1[i] * vec2[i]
    return ans

# 0 ベクトルの生成
def zero_vec(n, vec):
    for i in range(n):
        vec[i] = 0.0

# ベクトルをprint
def print_vec(n, vec):
    for i in range(n):
        print("%4.6f, " % (vec[i]), end='')
    print("")

# 行列を print
def print_mat(row, col, mat):
    for i in range(row):
        for j in range(col):
            print("%4.6f, " % (mat[i][j]),end='')
        print("")

def gmres(A, b, k=10, EPS=1.0e-20):
    '''
     gmres 法を用いて A*x = b の解を求める
     入力: 左辺行列A N x N
            右辺行列b 1 x N
            作業域の大きさk
            マシンイプシロンEPS

     出力: 答ans  1 x N / エラー None
    '''
    row = len(A)
    col = len(A[0])
    ans = [0.0 for _ in range(row)]
    if row == 1:
        if abs(A[0][0]) < EPS:
            return None
        else:
            ans[0] = b[0] / A[0][0]
        return ans
    mx = max(row,col)
    if mx < k or (k - mx) < 5:
        m = max(row,col) + 10
    else:
        m = k
    # メモリ割当
    Avj = [0.0 for _ in range(row)]
    r0 = [0.0 for _ in range(row)]
    g = [0.0 for _ in range(m+1)]
    c = [0.0 for _ in range(m)]
    s = [0.0 for _ in range(m)]
    y = [0.0 for _ in range(m)]
    x0 = [d for d in b]
    delta_x = [0.0 for _ in range(row)]
    tmpvec = [0.0 for _ in range(row)]
    # 行列はすべて転置して定義
    Vm = [[0.0 for _ in range(row)] for _ in range(m+1)]
    Vm_T = [[0.0 for _ in range(m+1)] for _ in range(row)]
    Hm = [[0.0 for _ in range(m+1)] for _ in range(m+1)]
    Rm = [[0.0 for _ in range(m+1)] for _ in range(m)]
    mat_multi_vec(row, col, A, x0, Avj)
    vec_sub_vec(row,b,Avj,r0)
    r0_norm = math.sqrt(dot(row,r0,r0))
    if type(r0_norm) is complex or abs(r0_norm) < EPS:
    #if type(Hm[j][j+1]) is complex:
        return None
    vec_div(row,r0,r0_norm,Vm[0])
    g[0] = r0_norm
    for j in range(m):
        # Arnoldi 法
        mat_multi_vec(row,col,A,Vm[j],Avj)
        zero_vec(row, tmpvec)
        for i in range(j+1):
            Hm[j][i] = dot(row, Avj, Vm[i])
            vec_multi(row,Vm[i],Hm[j][i],Vm[j+1])
            vec_add_vec(row,tmpvec,Vm[j+1],tmpvec)
        vec_sub_vec(row, Avj, tmpvec, Vm[j+1])
        Hm[j][j+1] = math.sqrt(dot(row, Vm[j+1], Vm[j+1]))
        if type(Hm[j][j+1]) is complex or abs(Hm[j][j+1]) < EPS:
            return None
        vec_div(row, Vm[j+1],Hm[j][j+1],Vm[j+1])
        Rm[j][0] = Hm[j][0]
        # Givens 回転
        for i in range(j):
            tmp1 = c[i]*Rm[j][i] - s[i]*Hm[j][i+1]
            tmp2 = s[i]*Rm[j][i] + c[i]*Hm[j][i+1]
            Rm[j][i] = tmp1
            Rm[j][i+1] = tmp2
        deno = math.sqrt(Rm[j][j]*Rm[j][j] + Hm[j][j+1]*Hm[j][j+1])
        if type(deno) is complex or abs(deno) < EPS:
            return None
        c[j] = Rm[j][j] / deno
        s[j] = -Hm[j][j+1] / deno
        g[j+1] = s[j] * g[j]
        g[j] = c[j] * g[j]
        Rm[j][j] = c[j]*Rm[j][j] - s[j]*Hm[j][j+1]
    # 後退代入
    y[m-1] = g[m-1] / Rm[m-1][m-1]
    for i in range(m-2, -1, -1):
        tmp1 = 0.0
        for j in range(i, m-1):
            tmp1 += Rm[j][i]*y[j]
        if abs(Rm[i][i]) < EPS:
            break
        y[i] = (g[i] - tmp1) / Rm[i][i]
    else:
        transpose(m+1,row,Vm,Vm_T)
        mat_multi_vec(row,m,Vm_T,y,delta_x)
        vec_add_vec(row,x0,delta_x,ans)
        return ans
    return None

def check_l(A, B):
    '''
     行の入れ替え    要素の絶対値が小さい順に並べ替え
    '''
    r = len(A)
    m = len(A[0])
    P = [ _ for _ in range(r)]
    A0 = [e.copy() for e in A]
    B0 = [e for e in B]
    for k in range(r):
        ae = abs(A0[k][0])
        for j in range(1,r):
            if abs(A0[k][j]) > ae:
                ae = abs(A0[k][j])
        mi = k
        if k != (r-1):
            k1  = k + 1
            le = ae
            for i in range(k1,r):
                be = abs(A0[i][0])
                for j in range(1,r):
                    if abs(A0[i][j]) > be:
                        be = abs(A0[i][j])
                if le > be:
                    le = be
                    mi = i
        if mi != k:
            for j in range(m):
                ss = A0[k][j]
                A0[k][j] = A0[mi][j]
                A0[mi][j] = ss
                tt = P[k]
            P[k] = P[mi]
            P[mi] = tt
            tt = B0[k]
            B0[k] = B0[mi]
            B0[mi] = tt
    return A0, B0, P

def chk(a,b):
    """
     指定行列を2次元に、式右辺をリストに変換
    """
    if type(a) == list:
        if len(a) == 0:
            return None
        else:
            if type(a[0]) != list:
                A = [a.copy()]
            else: 
                A = [e.copy() for e in  a]
        n = len(A)
        m = len(A[0])
    else:
        n = 0
        m = 0
    if m != n or n == 0: # 正方行列のみ
        return None, None
    if type(b) == list:
        if len(b) == 0:
            return None, None
        if type(b[0]) == list:
            return None, None
    else:
        b = [b]
    nb = len(b)
    if nb != n or nb == 0:
        return None, None

    return A,b


if __name__ == '__main__':
    import numpy as np
    from scipy.sparse.linalg import gmres as sci_gmres

    def p_header():
        print("実行結果: 答 = gmres() - GMRES法")
        print("  参照:https://tech-commonplace.com/gmres_method/")
        print("         C言語によるGMRES法の実装")
        print("       https://medium.com/@giorgio.martinez1926/understanding-gmres-using-python-3c314fac1264")
        print("         Understanding GMRES using python")
        print("....")

    def test_inv(msg,Am):
        print("--- 逆行列計算 ---", msg)
        print("A:",Am)
        ma, b = chk(Am,Am[0])
        if ma is None:
            print("計算できません")
            return
        N = len(ma)
        lab = np.linalg.matrix_rank(np.array(ma))
        print("ランク(A):",lab, "  ",N,"x",N,"行列")
        if lab != N:
            print("逆行列計算できません")
            return
        INV = []
        for i in range(N):
            b = np.array([0.0] * N)
            b[i] = 1.0
            x, _ = sci_gmres(np.array(ma), b)
            INV.append(x.tolist())
        print("--scipy.sparse.linalg.gmres 逆行列--")
        sciinv = np.array(INV).T
        print(sciinv)
        INV = []
        for i in range(N):
            b = [0.0 for _ in range(N)]
            b[i] = 1.0
            m1, mb , _ = check_l(ma,b)
            ans = gmres(m1,mb)
            if ans  is None:
                print("計算できませんでした")
                return
            else:
                INV.append(ans)
        print("--My gmres 逆行列--")
        myinv = np.array(INV).T
        print(myinv)
        if np.allclose(myinv, sciinv):
            print(" scipy gmres() inv: OK")
        else:
            print(" scipy gmres() inv: NG??")
        print("")

    def test(Am,v0):
        print("... 方程式解法計算 ...")
        print("A:",Am)
        print("b:",v0)
        A, b = chk(Am,v0)
        if A is None:
            print("計算できません")
        else:
            N = len(A)
            lab = np.linalg.matrix_rank(A)
            print("ランク(A):",lab, "  ",N,"x",N,"行列")
            if lab != N:
                print("方程式計算できません")
            else:
                ans = gmres(A,b)
                if ans  is None:
                    print("計算できませんでした")
                else:
                    print("x = ")
                    print_vec(N,ans)
                x, _ = sci_gmres(np.array(A), b)
                print("--scipy.sparse.linalg.gmres 答:")
                print_vec(N,x)
        print("")

    p_header()
    test_inv("テスト1",[[2.0, 3.0, 1.0, -3.0],[-1.0, 2.0, 2.0, 4.0],[4.0, 1.0, -3.0, 5.0],[5.0, -4.0, -4.0, 1.0]])
    test_inv("テスト2",[[2,3],[4,2]])
    test_inv("テスト3",[[1, 2, 3], [2, 4, 8], [4, 1, 1]])
    test_inv("テストB-1.2.3",[[0,0,3],[1,5,2],[0,1,0]]) # 1,2,3
    test_inv("テストB-1,3,2",[[0,0,3],[0,1,0],[1,5,2]]) # 1,3,2
    test_inv("テストB-2,1,3",[[1,5,2],[0,0,3],[0,1,0]]) # 2,1,3
    test_inv("テストB-2,3,1",[[1,5,2],[0,1,0],[0,0,3]]) # 2,3,1
    test_inv("テストB-3,1,2",[[0,1,0],[0,0,3],[1,5,2]]) # 3,1,2
    test_inv("テストB-3,2,1",[[0,1,0],[1,5,2],[0,0,3]]) # 3,2,1
    test([[],[]], [])
    test([0.0], 0)
    test([[1,2],[3,4]], [0,1])
    test([[1.0, 3.0, 9.0],[-1.0, 1.0, -1.0],[2.0, -4.0, -2.0]], [1,0,0])
...
2024-08-21 「行列・方程式解法ー逆行列 その他手順2題」
消去法の手順 その他2題

方程式解法とランク
 行列 A : 係数行列
 行列 B : 拡大行列(係数行列と右辺)

 ランクA == ランクB == 係数行列行数 ・で・ 解ひとつ
 ランクA == ランクB <  係数行列行数 ・で・ 解無限
 ランクA <  ランクB           ・で・ 解なし

実行:
$ python another_elim.py

*************
*** TEST1 ***
*************
◆◆◆◆ gj1数値例(0) ◆◆◆◆
入力:  MATRIX:
[ ]
計算できません
◆◆◆◆ gj1数値例(1) ◆◆◆◆
入力:  MATRIX:
[  2.00000 |  3.00000 ]
rank{A}: 1
rank{B}: 1
答は一つ : ランク(A) == ランク(AB) == A行数
方程式の解法結果:  MATRIX:
[  1.50000 ]
行入れ替え: [0]
◆◆◆◆ gj1数値例(2) ◆◆◆◆
入力:  MATRIX:
[  1.00000  0.99000 |  1.99000 ]
[  0.99000  0.98000 |  1.97000 ]
rank{A}: 2
rank{B}: 2
答は一つ : ランク(A) == ランク(AB) == A行数
方程式の解法結果:  MATRIX:
[  1.00000 ]
[  1.00000 ]
行入れ替え: [0, 1]
◆◆◆◆ gj1数値例(3) ◆◆◆◆
入力:  MATRIX:
[  2.00000  3.00000  1.00000 -3.00000 |  1.00000 ]
[ -1.00000  2.00000  2.00000  4.00000 |  6.00000 ]
[  4.00000  1.00000 -3.00000  5.00000 |  3.00000 ]
[  5.00000 -4.00000 -4.00000  1.00000 |  3.00000 ]
rank{A}: 4
rank{B}: 4
答は一つ : ランク(A) == ランク(AB) == A行数
方程式の解法結果:  MATRIX:
[  2.00000 ]
[ -1.00000 ]
[  3.00000 ]
[  1.00000 ]
行入れ替え: [0, 1, 2, 3]
◆◆◆◆ gj1 Rank(A) == Rank(A,b合わせた行列) < 4  ◆◆◆◆
入力:  MATRIX:
[  1.00000  3.00000  1.00000 -2.00000 | -3.00000 ]
[  1.00000  4.00000  3.00000 -1.00000 | -4.00000 ]
[  2.00000  3.00000 -4.00000 -7.00000 | -3.00000 ]
[  3.00000  8.00000  1.00000 -7.00000 | -8.00000 ]
rank{A}: 2
rank{B}: 2
答は無限 : ランク(A) == ランク(AB) < A行数
計算できません
◆◆◆◆ gj1逆行列計算1 ◆◆◆◆
入力:  MATRIX:
[  2.00000 |  1.00000 ]
rank{A}: 1
rank{B}: 1
答は一つ : ランク(A) == ランク(AB) == A行数
方程式の解法結果:  MATRIX:
[  0.50000 ]
行入れ替え: [0]
..逆行列検算..
 numpy.inv() と同じ
◆◆◆◆ gj1逆行列計算2 ◆◆◆◆
入力:  MATRIX:
[ -1.00000  1.00000  1.00000 |  1.00000  0.00000  0.00000 ]
[  1.00000 -1.00000  1.00000 |  0.00000  1.00000  0.00000 ]
[  1.00000  1.00000 -1.00000 |  0.00000  0.00000  1.00000 ]
rank{A}: 3
rank{B}: 3
答は一つ : ランク(A) == ランク(AB) == A行数
方程式の解法結果:  MATRIX:
[  0.00000  0.50000  0.50000 ]
[  0.50000  0.00000  0.50000 ]
[  0.50000  0.50000  0.00000 ]
行入れ替え: [0, 2, 1]
..逆行列検算..
 numpy.inv() と同じ
◆◆◆◆ gj1逆行列計算3 ◆◆◆◆
入力:  MATRIX:
[  0.00000 -2.00000  0.00000 |  1.00000  0.00000  0.00000 ]
[ -1.00000  5.00000  2.00000 |  0.00000  1.00000  0.00000 ]
[  0.00000 -1.00000  1.00000 |  0.00000  0.00000  1.00000 ]
rank{A}: 3
rank{B}: 3
答は一つ : ランク(A) == ランク(AB) == A行数
方程式の解法結果:  MATRIX:
[ -3.50000 -1.00000  2.00000 ]
[ -0.50000  0.00000  0.00000 ]
[ -0.50000  0.00000  1.00000 ]
行入れ替え: [1, 0, 2]
..逆行列検算..
 numpy.inv() と同じ
◆◆◆◆ gj1逆行列計算4 ◆◆◆◆
入力:  MATRIX:
[  1.00000  3.00000  9.00000 |  1.00000  0.00000  0.00000 ]
[ -1.00000  1.00000 -1.00000 |  0.00000  1.00000  0.00000 ]
[  2.00000 -4.00000 -2.00000 |  0.00000  0.00000  1.00000 ]
rank{A}: 2
rank{B}: 3
答はなし : ランク(A) < ランク(AB)
計算できません

*************
*** TEST2 ***
*************
◆◆◆◆ 消去法・数値例(0) ◆◆◆◆
入力:  MATRIX:
[ ]
計算できません
◆◆◆◆ 消去法・数値例(1) ◆◆◆◆
入力:  MATRIX:
[  2.00000 |  3.00000 ]
rank{A}: 1
rank{B}: 1
答は一つ : ランク(A) == ランク(AB) == A行数
方程式の解法結果:  MATRIX:
[  1.50000 ]
行入れ替え: [0]
◆◆◆◆ 消去法・数値例(2) ◆◆◆◆
入力:  MATRIX:
[  1.00000  0.99000 |  1.99000 ]
[  0.99000  0.98000 |  1.97000 ]
rank{A}: 2
rank{B}: 2
答は一つ : ランク(A) == ランク(AB) == A行数
方程式の解法結果:  MATRIX:
[  1.00000 ]
[  1.00000 ]
行入れ替え: [0, 1]
◆◆◆◆ 消去法・数値例(3) ◆◆◆◆
入力:  MATRIX:
[  2.00000  3.00000  1.00000 -3.00000 |  1.00000 ]
[ -1.00000  2.00000  2.00000  4.00000 |  6.00000 ]
[  4.00000  1.00000 -3.00000  5.00000 |  3.00000 ]
[  5.00000 -4.00000 -4.00000  1.00000 |  3.00000 ]
rank{A}: 4
rank{B}: 4
答は一つ : ランク(A) == ランク(AB) == A行数
方程式の解法結果:  MATRIX:
[  2.00000 ]
[ -1.00000 ]
[  3.00000 ]
[  1.00000 ]
行入れ替え: [3, 0, 2, 1]
◆◆◆◆ 消去法・ Rank(A) == Rank(A,b合わせた行列) < 4  ◆◆◆◆
入力:  MATRIX:
[  1.00000  3.00000  1.00000 -2.00000 | -3.00000 ]
[  1.00000  4.00000  3.00000 -1.00000 | -4.00000 ]
[  2.00000  3.00000 -4.00000 -7.00000 | -3.00000 ]
[  3.00000  8.00000  1.00000 -7.00000 | -8.00000 ]
rank{A}: 2
rank{B}: 2
答は無限 : ランク(A) == ランク(AB) < A行数
計算できません
◆◆◆◆ 消去法・逆行列計算1 ◆◆◆◆
入力:  MATRIX:
[  2.00000 |  1.00000 ]
rank{A}: 1
rank{B}: 1
答は一つ : ランク(A) == ランク(AB) == A行数
方程式の解法結果:  MATRIX:
[  0.50000 ]
行入れ替え: [0]
..逆行列検算..
 numpy.inv() と同じ
◆◆◆◆ 消去法・逆行列計算2 ◆◆◆◆
入力:  MATRIX:
[ -1.00000  1.00000  1.00000 |  1.00000  0.00000  0.00000 ]
[  1.00000 -1.00000  1.00000 |  0.00000  1.00000  0.00000 ]
[  1.00000  1.00000 -1.00000 |  0.00000  0.00000  1.00000 ]
rank{A}: 3
rank{B}: 3
答は一つ : ランク(A) == ランク(AB) == A行数
方程式の解法結果:  MATRIX:
[ -0.00000  0.50000  0.50000 ]
[  0.50000  0.00000  0.50000 ]
[  0.50000  0.50000  0.00000 ]
行入れ替え: [0, 2, 1]
..逆行列検算..
 numpy.inv() と同じ
◆◆◆◆ 消去法・逆行列計算3 ◆◆◆◆
入力:  MATRIX:
[  0.00000 -2.00000  0.00000 |  1.00000  0.00000  0.00000 ]
[ -1.00000  5.00000  2.00000 |  0.00000  1.00000  0.00000 ]
[  0.00000 -1.00000  1.00000 |  0.00000  0.00000  1.00000 ]
rank{A}: 3
rank{B}: 3
答は一つ : ランク(A) == ランク(AB) == A行数
方程式の解法結果:  MATRIX:
[ -3.50000 -1.00000  2.00000 ]
[ -0.50000 -0.00000 -0.00000 ]
[ -0.50000  0.00000  1.00000 ]
行入れ替え: [1, 0, 2]
..逆行列検算..
 numpy.inv() と同じ
◆◆◆◆ 消去法・逆行列計算4 ◆◆◆◆
入力:  MATRIX:
[  1.00000  3.00000  9.00000 |  1.00000  0.00000  0.00000 ]
[ -1.00000  1.00000 -1.00000 |  0.00000  1.00000  0.00000 ]
[  2.00000 -4.00000 -2.00000 |  0.00000  0.00000  1.00000 ]
rank{A}: 2
rank{B}: 3
答はなし : ランク(A) < ランク(AB)
計算できません
. . . . . . . . . . 

---- another_elim.py ----
def chk(m):
    '''
     正方形、長方形行列 チェック
    '''
    if type(m) == list:
        if len(m) == 0:
            return None, 0, 0
        else:
            if type(m[0]) != list:
                A = [m.copy()]
            else: 
                A = [e.copy() for e in  m]
        n = len(A)
        m = len(A[0])
    else:
        n = 0
        m = 0
    if m < n: # 正方行列,長方行列のみ
        return None, 0, 0
    return A, n, m

'''
  参照:FORTRAN数値計算とプログラミング
       国井利泰監修 中村明子、伊藤文子著 1971 共立出版
      1.1 C 逆行列 EX1-1-C p-17 ~ 23
    より、Fortranの手順をPythonに修正したもの。

入力: 方程式左辺行列+右辺行列(方程式の解法を行う) または、
    方程式左辺行列+右辺単位行列(逆行列式計算を行う)

出力: 方程式回答結果行列
    行入れ替え順列

処理タイプ: 単位行列
           100    xxx
           010    xxx
           001    xxx
'''

def gj1(PA,n,m,E=1.0E-7):
    if PA == None: # 有効な行列ではない
        return None, None
    A = [e.copy() for e in PA]
    P = [_ for _ in range(n)] 
    for k in range(n): 
        # p is not zero 
        if abs(A[k][k]) < E:  # チェック ゼロデバイド
            for j in range(k+1, n):
                if abs(A[j][k]) > abs(A[k][k]):
                    for ix in range(m):
                        xx = A[j][ix]
                        A[j][ix] = A[k][ix]
                        A[k][ix] = xx     # 行を交換
                    xp = P[j]
                    P[j] = P[k]
                    P[k] = xp
                    break
            else:                      # for j to n. ---| 
                return None, P         # 逆行列なしエラー  V
        #
        p = A[k][k]
        for j in range(k,m):
            A[k][j] /= p
        for i in range(n):
            if i == k:
                continue
            aik = A[i][k]
            for j in range(k,m):
                A[i][j] = A[i][j] - aik * A[k][j]
    return [e[n:] for e in A], P

'''
参考:
  サイエンスライブラリ情報電算機=20
  FORTRANのよる 算法入門       一松信篇 一松信、伊藤二朗、管伊兵衛 著 サイエンス社 1974,1976
   プログラム8.1

   行列と行列式  古屋茂 著  培風館  1959,1966
     付録1   

入力: 方程式左辺行列+右辺行列(方程式の解法を行う) または、
    方程式左辺行列+右辺単位行列(逆行列式計算を行う)

出力: 方程式回答結果行列
    行入れ替え順列

処理タイプ: 1111 1..     4111 1.. X4.. # b1-([0,1]*X3+[0,2]*X2+[0,3]*X1)/{1} = X4
           1222 2.. ==> x322 2.. X3.. # b2-([1,2]*X2+[1,3]*X1)/{3} = X3
           1233 3..     xx23 3.. X2.. # b3-([2,3]*X1)/{2} = X2
           1234 4..     xxx1 4.. X1.. # b4/{1} = X1

'''
def eliminate(PA,n,n1,E=1.0E-7):
    if PA == None: # 有効な行列ではない
        return None, None
    if n1 > (n*2) or n == n1:
        return None,None
    A = [e.copy() for e in PA]
    X = [[0.0] * (n1-n) for _ in range(n)]
    P = [_ for _ in range(n)]
    for k in range(n):
        ae = abs(A[k][k])
        if k != (n-1):
            k1  = k + 1
            max = k
            for i in range(k1,n):
                if abs(A[i][k]) > ae:
                    max = i
                    ae = abs(A[i][k])
            if max != k:
                for j in range(k,n1):
                    ss = A[k][j]
                    A[k][j] = A[max][j]
                    A[max][j] = ss
                tt = P[k]
                P[k] = P[max]
                P[max] = tt
        if ae < E:
            return None,P
        pv = A[k][k]
        if k == (n-1):
            break
        for i in range(k1,n):
            w = A[i][k] / pv
            for j in range(k1,n1):
                A[i][j] -= (w * A[k][j])
    for y in range(n1-n):
        for l in range(n):
            i = (n-1) - l
            pv = A[i][i]
            if abs(pv) < E:
                return None,P
            i1 = i + 1
            w = A[i][n+y]
            if l != 0:
                for k in range(i1,n):
                    w -= (A[i][k] * X[k][y])
            X[i][y] = w / pv
    return X, P

def matrix_dmp(msg, MAT):
    '''
     行列の印刷
    '''
    print(msg, " MATRIX:")
    if MAT is None:
        print("  結果がありません")
        return
    if len(MAT) == 0:
        print("[ ]")
        return
    else:
        if type(MAT[0]) == list:
            A = [e.copy() for e in MAT]
        else:
            A = [MAT]
    n = len(A)
    nm = len(A[0])
    for i in range(n):
        print("[",end='')
        if nm <= n:
            for j in range(nm):
                print(" % .5f" % (A[i][j]), end='')
        else:
            for j in range(n):
                print(" % .5f" % (A[i][j]), end='')
            print(" |",end='')
            for j in range(n,nm):
                print(" % .5f" % (A[i][j]), end='')
        print(" ]")

if __name__ == "__main__":
    import numpy as np

    def ematrix(A):
        n = len(A)
        ma = []
        for e in A:
            ma.append(e[:n])
        la = np.linalg.matrix_rank(ma)
        lab = np.linalg.matrix_rank(A)
        print("rank{A}:",la)
        print("rank{B}:",lab)
        if la == lab and la == n:
            print("答は一つ : ランク(A) == ランク(AB) == A行数")
        elif la == lab and la < n:
            print("答は無限 : ランク(A) == ランク(AB) < A行数")
        else:
            print("答はなし : ランク(A) < ランク(AB)")

    def check_inv(A,am):
        n = len(A)
        if n == 0:
            return
        if type(A[0]) == list:
            MA = [e[:n] for e in A]
            Mb = [e[n:] for e in A]
        else:
            n = 1
            MA = [A[:n]]
            Mb = [A[n:]]
        if am != None:
            if len(MA[0]) == len(Mb[0]):
                #
                # (注意)同じ列数の右辺に単位列を定義したら逆行列として検算をする。
                #
                ti = 1
                for i in range(n):
                    if float(Mb[i][i]) != 1.0:
                        ti = 0
                        break
                    for j in range(len(Mb[0])):
                        if i != j and float(Mb[i][j]) != 0.0:
                            ti = 0
                            break
                if ti:
                    print("..逆行列検算..")
                    if np.allclose(np.linalg.inv(MA), am):
                        print(" numpy.inv() と同じ")
                    else:
                        print(" 逆行列でない")

    def test1(f,msg,A):
        print("◆◆◆◆",msg,"◆◆◆◆")
        matrix_dmp("入力:",A)
        mA, n, m = chk(A)
        if mA is not None:
            ematrix(mA)
        else:
            print("計算できません")
            return
        am, cx = (eliminate(mA,n,m) if f == 1 else gj1(mA,n,m))
        if am is None:
            print("計算できません")
        else:
            matrix_dmp("方程式の解法結果:", am)
            print("行入れ替え:", cx)
            check_inv(mA,am)


    print("")
    print("*************")
    print("*** TEST1 ***")
    print("*************")
    test1(0,"gj1数値例(0)",[])
    test1(0,"gj1数値例(1)",[[2,3]])
    test1(0,"gj1数値例(2)",[[1,0.99,1.99],[0.99,0.98,1.97]])
    test1(0,"gj1数値例(3)",[[2,3,1,-3,1],[-1,2,2,4,6],[4,1,-3,5,3],[5,-4,-4,1,3]])
    test1(0,"gj1 Rank(A) == Rank(A,b合わせた行列) < 4 ",[[1,3,1,-2,-3],[1,4,3,-1,-4],[2,3,-4,-7,-3],[3,8,1,-7,-8]])
    test1(0,"gj1逆行列計算1",[2,1]) # 逆行列 右辺部分は単位行列のこと
    test1(0,"gj1逆行列計算2",[[-1,1,1,1,0,0],[1,-1,1,0,1,0],[1,1,-1,0,0,1]]) # 逆行列 右辺部分は単位行列のこと
    test1(0,"gj1逆行列計算3",[[0,-2,0,1,0,0],[-1,5,2,0,1,0],[0,-1,1,0,0,1]]) # 逆行列 右辺部分は単位行列のこと
    test1(0,"gj1逆行列計算4",[[1,3,9,1,0,0],[-1,1,-1,0,1,0],[2,-4,-2,0,0,1]]) # 逆行列 右辺部分は単位行列のこと
    #test1(0,"gj1逆行列計算5",[[2,3,1,-3,1,0,0,0],[-1,2,2,4,0,1,0,0],[4,1,-3,5,0,0,1,0],[5,-4,-4,1,0,0,0,1]]) # 逆行列 右辺部分は単位行列のこと
    #test1(0,"gj1数値例(4)",[[]])
    #test1(0,"gj1数値例(5)",[[1,2,3,2,2],[2,4,8,5,6],[4,1,1,7,7]])
    #test1(0,"gj1数値例(6)",[[2.08,3.4,1.04,-0.28,1.28],[-1.68,-2.68,-0.84,0.16,-6.72],[5.14,3.12,-4.32,4.59,0.86],[3.12,2.8,1.56,1.88,4.62]])
    print("")
    print("*************")
    print("*** TEST2 ***")
    print("*************")
    test1(1,"消去法・数値例(0)",[])
    test1(1,"消去法・数値例(1)",[[2,3]])
    test1(1,"消去法・数値例(2)",[[1,0.99,1.99],[0.99,0.98,1.97]])
    test1(1,"消去法・数値例(3)",[[2,3,1,-3,1],[-1,2,2,4,6],[4,1,-3,5,3],[5,-4,-4,1,3]])
    test1(1,"消去法・ Rank(A) == Rank(A,b合わせた行列) < 4 ",[[1,3,1,-2,-3],[1,4,3,-1,-4],[2,3,-4,-7,-3],[3,8,1,-7,-8]])
    test1(1,"消去法・逆行列計算1",[2,1]) # 逆行列 右辺部分は単位行列のこと
    test1(1,"消去法・逆行列計算2",[[-1,1,1,1,0,0],[1,-1,1,0,1,0],[1,1,-1,0,0,1]]) # 逆行列 右辺部分は単位行列のこと
    test1(1,"消去法・逆行列計算3",[[0,-2,0,1,0,0],[-1,5,2,0,1,0],[0,-1,1,0,0,1]]) # 逆行列 右辺部分は単位行列のこと
    test1(1,"消去法・逆行列計算4",[[1,3,9,1,0,0],[-1,1,-1,0,1,0],[2,-4,-2,0,0,1]]) # 逆行列 右辺部分は単位行列のこと
    #test1(1,"消去法・逆行列計算5",[[2,3,1,-3,1,0,0,0],[-1,2,2,4,0,1,0,0],[4,1,-3,5,0,0,1,0],[5,-4,-4,1,0,0,0,1]]) # 逆行列 右辺部分は単位行列のこと
    #test1(1,"消去法・数値例(4)",[[]])
    #test1(1,"消去法・数値例(5)",[[1,2,3,2,2],[2,4,8,5,6],[4,1,1,7,7]])
    #test1(1,"消去法・数値例(6)",[[2.08,3.4,1.04,-0.28,1.28],[-1.68,-2.68,-0.84,0.16,-6.72],[5.14,3.12,-4.32,4.59,0.86],[3.12,2.8,1.56,1.88,4.62]])
---------
2024-07-25 「mouspad メニューがない」
mousepadでメニューバーが消えてしまった。
CTRL+m を押したからでした。

キーバインドの設定は  ~/.config/Mousepad/accels.scm にあり。

コマンドでは
gsettings list-recursively org.xfce.mousepad.preferences
で設定の一覧がでる。
gsettings set org.xfce.mousepad.preferences.window menubar-visible true
でメニューバーが表示され、mausepad実行中でもtrue/false で表示/非表示となる。

参照:
https://docs.xfce.org/apps/mousepad/start#keybindings
mousepadのヘルプページ

https://forum.xfce.org/viewtopic.php?id=9515
» [Solved] mousepad view menu option

2024-07-28  「行列・ガウスの消去法で方程式の解法」
ガウスの消去法で方程式の解法を試した。
WEB検索するといっぱい出てくるが、そのままではなかなか思っているようにはうまく行かない。
手で計算することを考えるとnumpy,scipyライブラリを使うと手順がよく見えなくなるので、
ライブラリを使わないで試した。
方程式の解法と逆行列,行列計算を計算した。
行列変形のかたちは色々あるが、行列計算もできる上三角行列をやってみた。

>>> a
array([[ 1,  3,  1, -2, -3],
       [ 1,  4,  3, -1, -4],
       [ 2,  3, -4, -7, -3],
       [ 3,  8,  1, -7, -8]])
>>> np.linalg.matrix_rank(a)
2

>>> a
array([[ 1,  3,  1, -2],
       [ 1,  4,  3, -1],
       [ 2,  3, -4, -7],
       [ 3,  8,  1, -7]])
>>> np.linalg.matrix_rank(a)
2

>>> a
array([[ 1,  3,  1, -2],
       [ 1,  4,  3, -1],
       [ 2,  3, -4, -7],
       [ 3,  8,  1, -7]])
>>> b
array([-3, -4, -3, -8])
>>> np.linalg.solve(a,b)
array([ 2.04971182, -3.48414986,  2.07420749, -1.66426513])

Rank(A) == Rank(A,b合わせた行列) < len(A) の場合は、結果がでない。

実行:

$ python gauss1.py

◆◆◆◆ 数値例(1) ◆◆◆◆
入力:  MATRIX:
[ ]
計算できません
関数内部:  MATRIX:
[ ]
行入れ替え: [0]
My det():  0.00000
numpy det(): None
◆◆◆◆ 数値例(2) ◆◆◆◆
入力:  MATRIX:
[  2.00000 |  3.00000 ]
方程式の解法結果:  MATRIX:
[  1.50000 ]
関数内部:  MATRIX:
[  2.00000 ]
行入れ替え: [0]
My det():  2.00000
numpy det():  2.00000
◆◆◆◆ 数値例(3) ◆◆◆◆
入力:  MATRIX:
[  1.00000  2.00000  3.00000 |  2.00000  2.00000 ]
[  2.00000  4.00000  8.00000 |  5.00000  6.00000 ]
[  4.00000  1.00000  1.00000 |  7.00000  7.00000 ]
方程式の解法結果:  MATRIX:
[  1.78571  1.85714 ]
[ -0.64286 -1.42857 ]
[  0.50000  1.00000 ]
関数内部:  MATRIX:
[  4.00000  1.00000  1.00000 ]
[  0.00000  3.50000  7.50000 ]
[  0.00000  0.00000 -1.00000 ]
行入れ替え: [2, 1, 0]
My det():  14.00000
numpy det():  14.00000
◆◆◆◆ 数値例(4) ◆◆◆◆
入力:  MATRIX:
[  1.00000  0.99000 |  1.99000 ]
[  0.99000  0.98000 |  1.97000 ]
方程式の解法結果:  MATRIX:
[  1.00000 ]
[  1.00000 ]
関数内部:  MATRIX:
[  1.00000  0.99000 ]
[  0.00000 -0.00010 ]
行入れ替え: [0, 1]
My det(): -0.00010
numpy det(): -0.00010
◆◆◆◆ 数値例(5) ◆◆◆◆
入力:  MATRIX:
[  2.08000  3.40000  1.04000 -0.28000 |  1.28000 ]
[ -1.68000 -2.68000 -0.84000  0.16000 | -6.72000 ]
[  5.14000  3.12000 -4.32000  4.59000 |  0.86000 ]
[  3.12000  2.80000  1.56000  1.88000 |  4.62000 ]
計算できません
関数内部:  MATRIX:
[  5.14000  3.12000 -4.32000  4.59000 ]
[  0.00000  2.13743  2.78817 -2.13743 ]
[  0.00000  0.00000  3.00023 -0.00000 ]
[  0.00000  0.00000  0.00000 -0.00000 ]
行入れ替え: [2, 0, 3, 1]
My det():  0.00000
numpy det():  0.00000
◆◆◆◆ Rank(A) == Rank(A,b合わせた行列) < 4  ◆◆◆◆
入力:  MATRIX:
[  1.00000  3.00000  1.00000 -2.00000 | -3.00000 ]
[  1.00000  4.00000  3.00000 -1.00000 | -4.00000 ]
[  2.00000  3.00000 -4.00000 -7.00000 | -3.00000 ]
[  3.00000  8.00000  1.00000 -7.00000 | -8.00000 ]
計算できません
関数内部:  MATRIX:
[  3.00000  8.00000  1.00000 -7.00000 ]
[  0.00000 -2.33333 -4.66667 -2.33333 ]
[  0.00000 -0.00000 -0.00000 -0.00000 ]
[  0.00000  0.00000 -0.00000 -0.00000 ]
行入れ替え: [3, 2, 1, 0]
My det():  0.00000
numpy det(): -0.00000
◆◆◆◆ 逆行列計算1 ◆◆◆◆
入力:  MATRIX:
[  2.00000 |  1.00000 ]
方程式の解法結果:  MATRIX:
[  0.50000 ]
関数内部:  MATRIX:
[  2.00000 ]
行入れ替え: [0]
My det():  2.00000
numpy det():  2.00000
逆行列検算 A@INV:  MATRIX:
[  1.00000 ]
numpy 逆行列:  MATRIX:
[  0.50000 ]
◆◆◆◆ 逆行列計算2 ◆◆◆◆
入力:  MATRIX:
[  0.00000 -2.00000  0.00000 |  1.00000  0.00000  0.00000 ]
[ -1.00000  5.00000  2.00000 |  0.00000  1.00000  0.00000 ]
[  0.00000 -1.00000  1.00000 |  0.00000  0.00000  1.00000 ]
方程式の解法結果:  MATRIX:
[ -3.50000 -1.00000  2.00000 ]
[ -0.50000 -0.00000 -0.00000 ]
[ -0.50000  0.00000  1.00000 ]
関数内部:  MATRIX:
[ -1.00000  5.00000  2.00000 ]
[  0.00000 -2.00000  0.00000 ]
[  0.00000  0.00000  1.00000 ]
行入れ替え: [1, 0, 2]
My det(): -2.00000
numpy det(): -2.00000
◆◆◆◆ 逆行列計算3 ◆◆◆◆
入力:  MATRIX:
[  2.00000  3.00000  1.00000 -3.00000 |  1.00000  0.00000  0.00000  0.00000 ]
[ -1.00000  2.00000  2.00000  4.00000 |  0.00000  1.00000  0.00000  0.00000 ]
[  4.00000  1.00000 -3.00000  5.00000 |  0.00000  0.00000  1.00000  0.00000 ]
[  5.00000 -4.00000 -4.00000  1.00000 |  0.00000  0.00000  0.00000  1.00000 ]
方程式の解法結果:  MATRIX:
[  0.21053  0.22807 -0.10526  0.24561 ]
[  0.06140 -0.16959  0.21930 -0.23392 ]
[  0.18421  0.49123 -0.34211  0.29825 ]
[ -0.07018  0.14620  0.03509  0.02924 ]
関数内部:  MATRIX:
[  5.00000 -4.00000 -4.00000  1.00000 ]
[  0.00000  4.60000  2.60000 -3.40000 ]
[  0.00000  0.00000 -2.17391  7.30435 ]
[  0.00000  0.00000  0.00000  6.84000 ]
行入れ替え: [3, 0, 2, 1]
My det(): -342.00000
numpy det(): -342.00000
◆◆◆◆ 逆行列計算4 ◆◆◆◆
入力:  MATRIX:
[  0.00000 -2.00000  0.00000 |  1.00000  0.00000  0.00000 ]
[ -1.00000  5.00000  2.00000 |  0.00000  1.00000  0.00000 ]
[  0.00000 -1.00000  1.00000 |  0.00000  0.00000  1.00000 ]
方程式の解法結果:  MATRIX:
[ -3.50000 -1.00000  2.00000 ]
[ -0.50000 -0.00000 -0.00000 ]
[ -0.50000  0.00000  1.00000 ]
関数内部:  MATRIX:
[ -1.00000  5.00000  2.00000 ]
[  0.00000 -2.00000  0.00000 ]
[  0.00000  0.00000  1.00000 ]
行入れ替え: [1, 0, 2]
My det(): -2.00000
numpy det(): -2.00000
◆◆◆◆ 逆行列計算5 ◆◆◆◆
入力:  MATRIX:
[  1.00000  3.00000  9.00000 |  1.00000  0.00000  0.00000 ]
[ -1.00000  1.00000 -1.00000 |  0.00000  1.00000  0.00000 ]
[  2.00000 -4.00000 -2.00000 |  0.00000  0.00000  1.00000 ]
計算できません
関数内部:  MATRIX:
[  2.00000 -4.00000 -2.00000 ]
[  0.00000  5.00000  10.00000 ]
[  0.00000  0.00000  0.00000 ]
行入れ替え: [2, 0, 1]
My det():  0.00000
numpy det():  0.00000
◆◆◆◆ 行列計算1 ◆◆◆◆
入力:  MATRIX:
[ -6.00000 -2.00000 -9.00000 -2.00000 ]
[ -10.00000  3.00000 -8.00000  11.00000 ]
[  7.00000 -9.00000 -9.00000  5.00000 ]
[ -11.00000  8.00000  5.00000  5.00000 ]
方程式の解法結果:  MATRIX:
[ ]
[ ]
[ ]
[ ]
関数内部:  MATRIX:
[ -11.00000  8.00000  5.00000  5.00000 ]
[  0.00000 -6.36364 -11.72727 -4.72727 ]
[  0.00000  0.00000 -4.67143  9.62857 ]
[  0.00000  0.00000  0.00000  13.94190 ]
行入れ替え: [3, 0, 1, 2]
My det():  4559.00000
numpy det():  4559.00000
◆◆◆◆ 行列計算2 ◆◆◆◆
入力:  MATRIX:
[  1.00000 -1.00000 -1.00000 ]
[ -1.00000  1.00000 -1.00000 ]
[ -1.00000 -1.00000  1.00000 ]
方程式の解法結果:  MATRIX:
[ ]
[ ]
[ ]
関数内部:  MATRIX:
[  1.00000 -1.00000 -1.00000 ]
[  0.00000 -2.00000  0.00000 ]
[  0.00000  0.00000 -2.00000 ]
行入れ替え: [0, 2, 1]
My det(): -4.00000
numpy det(): -4.00000
◆◆◆◆ 行列計算3 ◆◆◆◆
入力:  MATRIX:
[ -1.00000  1.00000  3.00000 ]
[  2.00000  3.00000 -1.00000 ]
[  3.00000  4.00000 -2.00000 ]
計算できません
関数内部:  MATRIX:
[  3.00000  4.00000 -2.00000 ]
[  0.00000  2.33333  2.33333 ]
[  0.00000  0.00000 -0.00000 ]
行入れ替え: [2, 0, 1]
My det():  0.00000
numpy det(): -0.00000
............................

---- gauss1.py --------
'''
参考:
http://www.nct9.ne.jp/m_hiroi/light/numpy03.html
お気楽 NumPy プログラミング超入門

サイエンスライブラリ情報電算機=20 FORTRANによる算法入門 / 一松信篇 一松信、伊藤二朗、管伊兵衛 著 サイエンス社 1974,1976
   プログラム 8.1, 8.2

入力: 方程式左辺行列+右辺行列(方程式の解法を行う) または、
    方程式左辺行列+右辺単位行列(逆行列式計算を行う) または、 
    方程式左辺行列(行列式計算を行う)

出力: 方程式回答結果行列
    関数内部Matrix行列
    行入れ替え順列
    行列式の値

処理タイプ 上三角行列
           xxx 
           0xx
           00x
'''
def pivot(xs, i, n, m, P):
    '''
     行入れ替え
    '''
    c = 0
    p = i
    q = abs(xs[i][i])
    for s in range(i,n):
        if q < abs(xs[s][i]):
            p = s
            q = abs(xs[s][i])
    if p != i:
        for j in range(m):
            temp = xs[i][j]
            xs[i][j] = xs[p][j]
            xs[p][j] = temp
        temp = P[i]    # 行入れ替え情報
        P[i] = P[p]
        P[p] = temp
        c += 1
    return c

def gauss1(PA, E=1.0E-5):
    '''
     ガウスの消去法
    '''
    if type(PA) == list:
        if type(PA[0]) != list:
            zs = [PA.copy()]
        else: 
            zs = [e.copy() for e in  PA]
        n = len(zs)
        m = len(zs[0])
        P = [_ for _ in range(n)] 
    else:
        n = 0
        m = 0
    if m > (n*2) or m == 0: # 右辺は行数と同じ列数まで
        return None, None, None, 0.0
    cc = 0
    for i in range(n - 1):
        cc += pivot(zs, i, n, m, P)
        if abs(zs[i][i]) < E:
            return None, [e[:n] for e in zs], P, 0.0
        for j in range(i + 1, n):
            temp = zs[j][i] / zs[i][i]
            for s in range(i,m):
                zs[j][s] -= temp * zs[i][s]

    det = 1;
    for i in range(n):
        if abs(zs[i][i]) < E:
            return None,[e[:n] for e in zs], P, 0.0
        det *= zs[i][i]
    if cc & 1:
        det *= -1
    for c in range(n,m):
        for i in range(n - 1, -1, -1):
            if (i+1) < n:
                for j in range(i,n-1):
                    zs[i][c] -= zs[i][j+1] * zs[j+1][c]
            zs[i][c] /= zs[i][i]
    return [e[n:] for e in zs],[e[:n] for e in zs], P, det

def matrix_dmp(msg, MAT):
    '''
     行列の印刷
    '''
    print(msg, " MATRIX:")
    if MAT is None:
        print("  結果がありません")
        return
    if type(MAT[0]) == list:
        A = [e.copy() for e in MAT]
    else:
        A = [MAT]
    n = len(A)
    nm = len(A[0])
    for i in range(n):
        print("[",end='')
        if nm <= n:
            for j in range(nm):
                print(" % .5f" % (A[i][j]), end='')
        else:
            for j in range(n):
                print(" % .5f" % (A[i][j]), end='')
            print(" |",end='')
            for j in range(n,nm):
                print(" % .5f" % (A[i][j]), end='')
        print(" ]")

if __name__ == "__main__":
    import numpy as np

    def permutation(P):
        '''
          順列 交換回数計算
        '''
        n = len(P)
        Z = [e for e in P]
        cnt = 0
        for i in range(n):
            if Z[i] != i:
                min = i
                for j in range(i+1,n):
                    if Z[j] < Z[min]:
                        min = j
                xx = Z[min]
                Z[min] = Z[i]
                Z[i] = xx
                cnt += 1
        return cnt

    def test(msg,A):
        print("◆◆◆◆",msg,"◆◆◆◆")
        matrix_dmp("入力:",A)
        am, im, cx, det = gauss1(A)
        if am is None:
            print("計算できません")
        else:
            matrix_dmp("方程式の解法結果:", am)
        matrix_dmp("関数内部:", im)
        print("行入れ替え:", cx)
        print("My det(): % .5f" % (det))
        n = len(A)
        if type(A[0]) == list:
            MA = [e[:n] for e in A]
            Mb = [e[n:] for e in A]
        else:
            n = 1
            MA = [A[:n]]
            Mb = [A[n:]]
        if len(MA[0]) > 0:
            print("numpy det(): % .5f" % (np.linalg.det(MA)))
        else:
            print("numpy det(): None")
        if im != None and det > 0.0:
            if len(MA[0]) == len(Mb[0]):
                #
                # (注意)同じ列数の右辺に単位列を定義したら逆行列として検算をする。
                #
                ti = 1
                for i in range(n):
                    if float(Mb[i][i]) != 1.0:
                        ti = 0
                        break
                    for j in range(len(Mb[0])):
                        if i != j and float(Mb[i][j]) != 0.0:
                            ti = 0
                            break
                if ti:
                    kn = np.dot(MA,am).tolist()
                    matrix_dmp("逆行列検算 A@INV:",kn)
                    matrix_dmp("numpy 逆行列:", np.linalg.inv(MA).tolist())

    test("数値例(1)",[[]])
    test("数値例(2)",[[2,3]])
    test("数値例(3)",[[1,2,3,2,2],[2,4,8,5,6],[4,1,1,7,7]])
    test("数値例(4)",[[1,0.99,1.99],[0.99,0.98,1.97]])
    test("数値例(5)",[[2.08,3.4,1.04,-0.28,1.28],[-1.68,-2.68,-0.84,0.16,-6.72],[5.14,3.12,-4.32,4.59,0.86],[3.12,2.8,1.56,1.88,4.62]])
    test("Rank(A) == Rank(A,b合わせた行列) < 4 ",[[1,3,1,-2,-3],[1,4,3,-1,-4],[2,3,-4,-7,-3],[3,8,1,-7,-8]])
    test("逆行列計算1",[2,1]) # 逆行列 右辺部分は単位行列のこと
    test("逆行列計算2",[[0,-2,0,1,0,0],[-1,5,2,0,1,0],[0,-1,1,0,0,1]]) # 逆行列 右辺部分は単位行列のこと
    test("逆行列計算3",[[2,3,1,-3,1,0,0,0],[-1,2,2,4,0,1,0,0],[4,1,-3,5,0,0,1,0],[5,-4,-4,1,0,0,0,1]]) # 逆行列 右辺部分は単位行列のこと
    test("逆行列計算4",[[0,-2,0,1,0,0], [-1,5,2,0,1,0], [0,-1, 1,0,0,1]]) # 逆行列 右辺部分は単位行列のこと
    test("逆行列計算5",[[1,3,9,1,0,0],[-1,1,-1,0,1,0],[2,-4,-2,0,0,1]]) # 逆行列 右辺部分は単位行列のこと
    test("行列計算1",[[-6,-2,-9,-2],[-10,3,-8,11],[7,-9,-9,5],[-11,8,5,5]]) # 
    test("行列計算2",[[1,-1,-1],[-1,1,-1],[-1,-1,1]])
    test("行列計算3",[[-1,1,3],[2,3,-1],[3,4,-2]])
....................................................................................................
2024-07-26   「行列・階数(Rank)計算」
階数
 方程式 AX=b
    A:      b:
    2  3  1 -3 |  1
   -1  2  2  4 |  6
    4  1 -3  5 |  3
    5 -4 -4  1 |  3

  Rank(A) == Rank(A,b合わせた行列) == len(A)
  解が1組
  Rank(A) == Rank(A,b合わせた行列) < len(A)
  解が多い
  Rank(A) != Rank(A,b合わせた行列)
    解がない
  Rank(A) < len(A)
  逆行列がない

行列の階数計算をやってみた。

実行:
$ python rank10n.py
--
Matrix:  -  2  x  0
[  ]
[  ]
Rank is: 0
--
Matrix:  -  1  x  1
[ 1 ]
Rank is: 1
np.rank: 1
--
Matrix:  -  1  x  1
[ 2 ]
Rank is: 1
np.rank: 1
--
Matrix:  -  1  x  2
[ 2 , 3 ]
Rank is: 1
np.rank: 1
--
Matrix:  -  1  x  0
[  ]
Rank is: 0
--
Matrix:  -  3  x  3
[ 0 , 0 , 0 ]
[ 0 , 0 , 0 ]
[ 0 , 0 , 0 ]
Rank is: 0
np.rank: 0

--
Matrix:  -  3  x  3
[ 0 , 0 , 1 ]
[ 0 , 0 , 0 ]
[ 1 , 0 , 0 ]
Rank is: 2
np.rank: 2
--
Matrix:  -  3  x  3
[ 1 , 0 , 0 ]
[ 0 , 1 , 0 ]
[ 0 , 0 , 1 ]
Rank is: 3
np.rank: 3
--
Matrix:  -  3  x  3
[ 0 , -2 , 0 ]
[ -1 , 5 , 2 ]
[ 0 , -1 , 1 ]
Rank is: 3
np.rank: 3
--
Matrix:  -  3  x  3
[ 1 , 3 , 9 ]
[ -1 , 1 , -1 ]
[ 2 , -4 , -2 ]
Matrix in Rank Function:  -  3  x  3
[ 1.0 , 0.0 , 3.0 ]
[ 0.0 , 4.0 , 8.0 ]
[ 0.0 , 0.0 , 0.0 ]
Rank is: 2
np.rank: 2
--
Matrix:  -  4  x  5
[ 1 , 3 , 1 , -2 , -3 ]
[ 1 , 4 , 3 , -1 , -4 ]
[ 2 , 3 , -4 , -7 , -3 ]
[ 3 , 8 , 1 , -7 , -8 ]
Matrix in Rank Function:  -  4  x  5
[ 1.0 , 0.0 , 0.0 , -5.0 , 0.0 ]
[ 0.0 , 1.0 , -1.0 , 1.0 , -1.0 ]
[ 0.0 , 0.0 , 0.0 , 0.0 , 0.0 ]
[ 0.0 , 0.0 , 0.0 , 0.0 , 0.0 ]
Rank is: 2
np.rank: 2
--
Matrix:  -  3  x  4
[ 1 , 1 , -2 , 1 ]
[ 1 , -2 , 1 , 1 ]
[ -2 , 1 , 1 , 1 ]
Matrix in Rank Function:  -  3  x  4
[ 1.0 , 0.0 , 0.0 , 1.0 ]
[ 0.0 , -3.0 , 0.0 , 0.0 ]
[ 0.0 , 0.0 , 0.0 , 3.0 ]
Rank is: 3
np.rank: 3
--
Matrix:  -  3  x  3
[ 1 , 1 , -2 ]
[ 1 , -2 , 1 ]
[ -2 , 1 , 1 ]
Rank is: 2
np.rank: 2
--
Matrix:  -  2  x  3
[ 1 , 2 , 3 ]
[ 4 , 5 , 6 ]
Matrix in Function:  -  2  x  3
[ 1.0 , 0.5 , 0.0 ]
[ 0.0 , 0.0 , 0.0 ]  <<===3行目だとして処理した結果
Rank is: 2
np.rank: 2

...

---- rank10n.py ---
'''
参照:
https://www.geeksforgeeks.org/program-for-rank-of-matrix/
Program for Rank of Matrix
'''
# ----------------------
# Exchange Row in matrix
#
def swap(Matrix, row1, row2, col):
    for i in range(col):
        temp = Matrix[row1][i]
        Matrix[row1][i] = Matrix[row2][i]
        Matrix[row2][i] = temp
            
# ----------------
# Display matrix
#
def Display(msg, Mtx):
    if type(Mtx[0]) == list:
        Matrix = [e.copy() for e in Mtx]
    else:
        Matrix = [Mtx]
        col = 1
    row = len(Matrix)
    col = len(Matrix[0])
    print(msg," - ",row," x ",col)
    for i in range(row):
        print("[ ", end='')
        for j in range(col):
            if j != 0:
                print(" , ",end='')
            print (str(Matrix[i][j]),end='')
        print (' ]')

# ----------------
# Rank of a matrix
#
def rank2fMatrix(A, inf=0):
    if type(A) != list:
        return 0
    if type(A[0]) != list:
        Matrix = [A.copy()]
    else: 
        Matrix = [e.copy() for e in  A]
    rank = len(Matrix[0])
    C = rank
    R = len(Matrix)
    ###Matrix = [e.copy() for e in  A]
    for row in range(0, rank, 1):
        if row >= R:
            row1 = R-1
            if Matrix[row1][row] != 0:
                for col in range(0, R, 1):
                    if col != row:
                        multiplier = (Matrix[col][row] / Matrix[row1][row])
                        for i in range(rank):
                            Matrix[col][i] -= (multiplier * Matrix[row1][i])
            if Matrix[row1][row] == 0 and row == (C-1):
                rank -= 1
            continue
        if Matrix[row][row] != 0:
            for col in range(0, R, 1):
                if col != row:
                    multiplier = (Matrix[col][row] / Matrix[row][row])
                    for i in range(rank):
                        Matrix[col][i] -= (multiplier * Matrix[row][i])
        else:
            reduce = True
            for i in range(row + 1, R, 1):
                if Matrix[i][row] != 0:
                    swap(Matrix, row, i, rank)
                    reduce = False
                    break
            if reduce:
                rank -= 1
                # copy the last column here
                for i in range(0, R, 1):
                    Matrix[i][row] = Matrix[i][rank]
            row -= 1
    if inf == 1:
        return rank, Matrix
    else:
        return (rank)

# -------------------
# Test Main
#
if __name__ == '__main__':
    import numpy as np
    
    m = [[],[]]
    Display("--\nMatrix:",m) 
    print ("Rank is:", (rank2fMatrix(m)))
    #print("np.rank:",np.linalg.matrix_rank(m))

    m = [[1]]
    Display("--\nMatrix:",m) 
    print ("Rank is:", (rank2fMatrix(m)))
    print("np.rank:",np.linalg.matrix_rank(m))
    
    m = [2]
    Display("--\nMatrix:",m) 
    print ("Rank is:", (rank2fMatrix(m)))
    print("np.rank:",np.linalg.matrix_rank(m))

    m = [2,3]
    Display("--\nMatrix:",m) 
    print ("Rank is:", (rank2fMatrix(m)))
    print("np.rank:",np.linalg.matrix_rank(m))

    m = [[]]
    Display("--\nMatrix:",m) 
    print ("Rank is:", (rank2fMatrix(m)))
    #print("np.rank:",np.linalg.matrix_rank(m))

    m = [[0,0,0],[0,0,0],[0,0,0]]
    Display("--\nMatrix:",m) 
    print ("Rank is:", (rank2fMatrix(m)))
    print("np.rank:",np.linalg.matrix_rank(m))

    m = [[0,0,1],[0,0,0],[1,0,0]]
    Display("\n--\nMatrix:",m) 
    print ("Rank is:", (rank2fMatrix(m)))
    print("np.rank:",np.linalg.matrix_rank(m))

    m = [[1,0,0],[0,1,0],[0,0,1]]
    Display("--\nMatrix:",m) 
    print ("Rank is:", (rank2fMatrix(m)))
    print("np.rank:",np.linalg.matrix_rank(m))

    m = [[0,-2,0],[-1,5,2],[0,-1,1]]
    Display("--\nMatrix:",m) 
    print ("Rank is:", (rank2fMatrix(m)))
    print("np.rank:",np.linalg.matrix_rank(m))

    m = [[1,3,9],[-1,1,-1],[2,-4,-2]]
    Display("--\nMatrix:",m) 
    rnk , mat = rank2fMatrix(m, inf=1)
    Display("Matrix in Rank Function:",mat) 
    print("Rank is:",rnk) 
    print("np.rank:",np.linalg.matrix_rank(m))

    m = [[1, 3, 1, -2, -3], [1, 4, 3, -1, -4], [2, 3, -4, -7, -3], [3, 8, 1, -7, -8]]
    Display("--\nMatrix:",m) 
    rnk , mat = rank2fMatrix(m, inf=1)
    Display("Matrix in Rank Function:",mat) 
    print("Rank is:",rnk) 
    print("np.rank:",np.linalg.matrix_rank(m))

    m = [[1, 1, -2, 1], [1, -2, 1, 1], [-2, 1, 1, 1]]
    Display("--\nMatrix:",m) 
    rnk, mat  = rank2fMatrix(m, inf=1)
    Display("Matrix in Rank Function:",mat) 
    print("Rank is:",rnk) 
    print("np.rank:",np.linalg.matrix_rank(m))

    m = [[1, 1, -2], [1, -2, 1], [-2, 1, 1]]
    Display("--\nMatrix:",m) 
    rnk  = rank2fMatrix(m)
    print("Rank is:",rnk) 
    print("np.rank:",np.linalg.matrix_rank(m))

    m = [[1,2,3],[4,5,6]]
    Display("--\nMatrix:",m) 
    rnk, mat  = rank2fMatrix(m, inf=1)
    Display("Matrix in Function:",mat) 
    print("Rank is:",rnk)
    print("np.rank:",np.linalg.matrix_rank(m))
---
参照:
https://www.geeksforgeeks.org/program-for-rank-of-matrix/
Program for Rank of Matrix

https://github.com/TheAlgorithms/Python/tree/master/linear_algebra
Linear algebra library for Python
src/rank_of_matrix.py

技術者のための空学の要点1 線形数学・計算法  唐沢英雄 著  理工図書 1982,1984
2024-08-26    「行列 LU分解・行列式計算・方程式解法」
参考:
(1)初等線形代数 --考え方と応用プログラム
  石原辰雄・長谷川勝也 著      共立出版 1986,1988
(2)https://stackoverflow.com/questions/28441509/how-to-implement-lu-decomposition-with-partial-pivoting-in-python
   How to implement LU decomposition with partial pivoting in Python?
(3)https://nttdocomo-developers.jp/entry/2024/02/17/090000
   スバラしき逆行列の世界 (LU分解)

行列のLU分解と同時に行列式計算もやってみた。
10x10行列以上の大きいものは計算方法によってはものすごく遅くなる。

追加機能:
 方程式解法、逆行列

プログラム追加分
---
"""
https://johnfoster.pge.utexas.edu/numerical-methods-book/LinearAlgebra_LU.html
のなかの
lu_solve
"""
def forward_substitution(L, b):
    
    #Get number of rows
    n = len(L)
    
    #Allocating space for the solution vector
    #y = np.zeros_like(b, dtype=np.double);
    y = [0 for _ in range(n)]
    
    #Here we perform the forward-substitution.  
    #Initializing  with the first row.
    y[0] = b[0] / L[0][0]
    
    #Looping over rows in reverse (from the bottom  up),
    #starting with the second to last row, because  the 
    #last row solve was completed in the last step.
    for i in range(1, n):
        # y[i] = (b[i] - np.dot(L[i,:i], y[:i])) / L[i,i]
        sum = 0
        for j in range(i):
            sum += L[i][j] * y[j]
        y[i] = (b[i] - sum) / L[i][i]
    return y

def back_substitution(U, y):
    #UU = U.tolist()    
    #Number of rows
    n = len(U)
  
    #Allocating space for the solution vector
    x = [0 for _ in range(n)]

    #Here we perform the back-substitution.  
    #Initializing with the last row.
    x[n-1] = y[n-1] / U[n-1][n-1]
    
    #Looping over rows in reverse (from the bottom up), 
    #starting with the second to last row, because the 
    #last row solve was completed in the last step.
    for i in range(n-2, -1, -1):
        #x[i] = (y[i] - np.dot(U[i,i:], x[i:])) / U[i,i]
        sum = 0
        for j in range(i+1,n):
            sum += U[i][j] * x[j]
        x[i] = (y[i] - sum) / U[i][i]
        
    return x

def lu_solve(A, b):
    n = len(A)
    P, L, U = lu(A,n)
    if L == None:
        return None, None
    mb = [e for e in b]
    xchange(mb, P)
    y = forward_substitution(L, mb)
    
    x = back_substitution(U, y)
    return x

#     ^^^^^^^^^^^^

def xchange(B, P):
    '''
      順列 交換回数計算
    '''
    n = len(B)
    Z = [e for e in P]
    cnt = 0
    for i in range(n):
        if Z[i] != i:
            min = i
            for j in range(i+1,n):
                if Z[j] < Z[min]:
                    min = j
            xx = Z[min]
            Z[min] = Z[i]
            Z[i] = xx
            cnt += 1
    bb = [e for e in B]
    for i in range(n):
        B[i] = bb[P[i]]
    return cnt


def plu_inverse(PA):
    n = len(PA)
    INV = [[0 for _ in range(n)] for _ in range(n)]
    for i in range(n):
        b = [0.0 if k != i else 1 for k in range(n)]
        x = lu_solve(PA, b)
        if x is None:
            return None
        for ln in range(n):
            INV[ln][i] = x[ln]
    return INV

# ------

x = lu_solve([[1,2,3],[2,4,8],[4,1,1]],[2,5,7])
print("答:",x)
print("逆行列")
print( plu_inverse([[1,2,3],[2,4,8],[4,1,1]]) )
---

結果
...
答: [1.7857142857142858, -0.6428571428571429, 0.5]
逆行列
[[-0.2857142857142857, 0.07142857142857142, 0.2857142857142857], [2.142857142857143, -0.7857142857142857, -0.14285714285714285], [-1.0, 0.5, -0.0]]
...

python では、
>>> import numpy as np
>>> a = [[1, 2, 3], [2, 4, 8], [4, 1, 1]]
>>> b = [2, 5, 7]
>>> np.linalg.solve(a,b)
array([ 1.78571429, -0.64285714,  0.5       ])
>>> np.linalg.inv(a)
array([[-0.28571429,  0.07142857,  0.28571429],
       [ 2.14285714, -0.78571429, -0.14285714],
       [-1.        ,  0.5       , -0.        ]])
................................................

上記の追加プログラムは以下のソースプログラムに追加する。

実行:
$ python TYP-LU-det.py

 計算−1  ● ***Results***
Used A ---
[[2, 3, 1, -3], [-1, 2, 2, 4], [4, 1, -3, 5], [5, -4, -4, 1]]
**Answers**
  numpy RANK: 4
L1:  MATRIX:
  1.0000  0.0000  0.0000  0.0000
  0.4000  1.0000  0.0000  0.0000
  0.8000  0.9130  1.0000  0.0000
 -0.2000  0.2609 -0.2400  1.0000
U1:  MATRIX:
  5.0000 -4.0000 -4.0000  1.0000
  0.0000  4.6000  2.6000 -3.4000
  0.0000  0.0000 -2.1739  7.3043
  0.0000  0.0000  0.0000  6.8400
行入れ替え情報: [3, 0, 2, 1]
DET: -342.00000000000006
numpy det: -342.00000000000017
..検算..
 det() OK
 matrix OK

 計算−2  ● ***Results***
Used A ---
[[2, 0], [0, 5]]
**Answers**
  numpy RANK: 2
L1:  MATRIX:
  1.0000  0.0000
  0.0000  1.0000
U1:  MATRIX:
  2.0000  0.0000
  0.0000  5.0000
行入れ替え情報: [0, 1]
DET: 10.0
numpy det: 9.999999999999998
..検算..
 det() OK
 matrix OK

 計算−3  ● ***Results***
Used A ---
[[0.0, 1.0], [1.0, 0.0]]
**Answers**
  numpy RANK: 2
L1:  MATRIX:
  1.0000  0.0000
  0.0000  1.0000
U1:  MATRIX:
  1.0000  0.0000
  0.0000  1.0000
行入れ替え情報: [1, 0]
DET: -1.0
numpy det: -1.0
..検算..
 det() OK
 matrix OK

 計算−4  ● ***Results***
Used A ---
[[4]]
**Answers**
  numpy RANK: 1
L1:  MATRIX:
  1.0000
U1:  MATRIX:
  4.0000
行入れ替え情報: [0]
DET: 4
numpy det: 4.0
..検算..
 det() OK
 matrix OK

 計算−5  ● ***Results***
Used A ---
[0.0]
**Answers**
  numpy RANK: 0
L1:  MATRIX:
  1.0000
U1:  MATRIX:
  0.0000
行入れ替え情報: [0]
DET: 0.0
 DET() == ZERO
numpy det: 0.0
..検算..
 det() OK
 matrix OK

 計算−6  ● ***Results***
Used A ---
[[-1, 1, 3], [2, 3, -1], [3, 4, -2]]
**Answers**
  numpy RANK: 2
L1:  MATRIX:
  1.0000  0.0000  0.0000
 -0.3333  1.0000  0.0000
  0.6667  0.1429  1.0000
U1:  MATRIX:
  3.0000  4.0000 -2.0000
  0.0000  2.3333  2.3333
  0.0000  0.0000 -0.0000
行入れ替え情報: [2, 0, 1]
DET: -1.9428902930940236e-15
 DET() == ZERO
numpy det: -1.896631000401315e-15
..検算..
 det() OK
 matrix OK

 計算−7  ● ***Results***
Used A ---
[[1, 3, 9], [-1, 1, -1], [2, -4, -2]]
**Answers**
  numpy RANK: 2
L1:  MATRIX:
  1.0000  0.0000  0.0000
  0.5000  1.0000  0.0000
 -0.5000 -0.2000  1.0000
U1:  MATRIX:
  2.0000 -4.0000 -2.0000
  0.0000  5.0000  10.0000
  0.0000  0.0000  0.0000
行入れ替え情報: [2, 0, 1]
DET: 0.0
 DET() == ZERO
numpy det: 1.1102230246251546e-15
..検算..
 det() OK
 matrix OK

 計算−8  ● ***Results***
Used A ---
[[1, -1, -1], [-1, 1, -1], [-1, -1, 1]]
**Answers**
  numpy RANK: 3
L1:  MATRIX:
  1.0000  0.0000  0.0000
 -1.0000  1.0000  0.0000
 -1.0000 -0.0000  1.0000
U1:  MATRIX:
  1.0000 -1.0000 -1.0000
  0.0000 -2.0000  0.0000
  0.0000  0.0000 -2.0000
行入れ替え情報: [0, 2, 1]
DET: -4.0
numpy det: -4.0
..検算..
 det() OK
 matrix OK

 計算-9  ● ***Results***
Used A ---
[[-5, -1, 10, -10], [-9, 3, -9, -7], [9, -4, -10, 0], [-3, 7, 7, -9]]
**Answers**
  numpy RANK: 4
L1:  MATRIX:
  1.0000  0.0000  0.0000  0.0000
  0.3333  1.0000  0.0000  0.0000
  0.5556 -0.4444  1.0000  0.0000
 -1.0000 -0.1667 -0.8914  1.0000
U1:  MATRIX:
 -9.0000  3.0000 -9.0000 -7.0000
  0.0000  6.0000  10.0000 -6.6667
  0.0000  0.0000  19.4444 -9.0741
  0.0000  0.0000  0.0000 -16.2000
行入れ替え情報: [1, 3, 0, 2]
DET: -17010.0
numpy det: -17010.000000000004
..検算..
 det() OK
 matrix OK

 計算−10  ● ***Results***
Used A ---
[[0, -2, 0], [-1, 5, 2], [0, -1, 1]]
**Answers**
  numpy RANK: 3
L1:  MATRIX:
  1.0000  0.0000  0.0000
 -0.0000  1.0000  0.0000
 -0.0000  0.5000  1.0000
U1:  MATRIX:
 -1.0000  5.0000  2.0000
  0.0000 -2.0000  0.0000
  0.0000  0.0000  1.0000
行入れ替え情報: [1, 0, 2]
DET: -2.0
numpy det: -2.0
..検算..
 det() OK
 matrix OK

 計算−11  ● ***Results***
Used A ---
[[0, 0, 3], [-1, 5, 2], [0, -1, 2]]
**Answers**
  numpy RANK: 3
L1:  MATRIX:
  1.0000  0.0000  0.0000
 -0.0000  1.0000  0.0000
 -0.0000 -0.0000  1.0000
U1:  MATRIX:
 -1.0000  5.0000  2.0000
  0.0000 -1.0000  2.0000
  0.0000  0.0000  3.0000
行入れ替え情報: [1, 2, 0]
DET: 3.0
numpy det: 3.0000000000000004
..検算..
 det() OK
 matrix OK

 計算−12  ● ***Results***
Used A ---
[[1, 2, 2], [2, 1, 2], [2, 2, 1]]
**Answers**
  numpy RANK: 3
L1:  MATRIX:
  1.0000  0.0000  0.0000
  0.5000  1.0000  0.0000
  1.0000  0.6667  1.0000
U1:  MATRIX:
  2.0000  1.0000  2.0000
  0.0000  1.5000  1.0000
  0.0000  0.0000 -1.6667
行入れ替え情報: [1, 0, 2]
DET: 5.0
numpy det: 4.999999999999998
..検算..
 det() OK
 matrix OK

 計算−13  ● ***Results***
Used A ---
[[0.0, -1.0, 1.0, 0.0, -1.0], [4.0, 4.0, 2.0, 1.0, 1.0], [4.0, 1.0, 1.0, 3.0, 2.0], [0.0, 3.0, -1.0, 4.0, -2.0], [-1.0, -1.0, -1.0, -1.0, -1.0]]
**Answers**
  numpy RANK: 5
L1:  MATRIX:
  1.0000  0.0000  0.0000  0.0000  0.0000
  1.0000  1.0000  0.0000  0.0000  0.0000
  0.0000 -1.0000  1.0000  0.0000  0.0000
  0.0000  0.3333 -0.6667  1.0000  0.0000
 -0.2500 -0.0000  0.2500 -0.6750  1.0000
U1:  MATRIX:
  4.0000  4.0000  2.0000  1.0000  1.0000
  0.0000 -3.0000 -1.0000  2.0000  1.0000
  0.0000  0.0000 -2.0000  6.0000 -1.0000
  0.0000  0.0000  0.0000  3.3333 -2.0000
  0.0000  0.0000  0.0000  0.0000 -1.8500
行入れ替え情報: [1, 2, 3, 0, 4]
DET: 148.0
numpy det: 147.99999999999994
..検算..
 det() OK
 matrix OK

o o o o o o o

TEST MATRIX No. 1
  38 x 38 行列
  numpy RANK: 38
..検算:
 det() OK
 matrix OK

TEST MATRIX No. 2
  19 x 19 行列
  numpy RANK: 19
..検算:
 det() OK
 matrix OK

TEST MATRIX No. 3
  34 x 34 行列
  numpy RANK: 34
..検算:
 det() OK
 matrix OK

TEST MATRIX No. 4
  38 x 38 行列
  numpy RANK: 38
..検算:
 det() OK
 matrix OK

TEST MATRIX No. 5
  19 x 19 行列
  numpy RANK: 19
..検算:
 det() OK
 matrix OK

〜〜〜〜〜〜〜〜〜〜〜〜〜

プログラム:

--- TYP-LU-det.py ----
'''
(1)初等線形代数 --考え方と応用プログラム
  石原辰雄・長谷川勝也 著      共立出版 1986,1988

  LU分解 *LU

(2)https://stackoverflow.com/questions/28441509/how-to-implement-lu-decomposition-with-partial-pivoting-in-python
   How to implement LU decomposition with partial pivoting in Python?

   lu_factor()
'''

def lu(m,EPS=1.0e-7):
    A = [e.copy() for e in m]
    n = len(A)
    PZ = [i for i in range(n)]
    for i in range(n-1):
        amax = abs(A[i][i])
        kmax = i
        for k in range(i+1,n):
            ww = abs(A[k][i])
            if ww > amax:
                amax = ww
                kmax = k
        if amax < EPS:
            return None, None, None

        if kmax != i:
            for j in range(n):
                xx = A[i][j]
                A[i][j] = A[kmax][j]
                A[kmax][j] = xx
            xx = PZ[i]
            PZ[i] = PZ[kmax]
            PZ[kmax] = xx
        aii = A[i][i]
        for k in range(i+1,n):
            mm = A[k][i] / aii
            A[k][i] = mm
            for j in range(i+1,n):
                A[k][j] = A[k][j] - mm * A[i][j]
    # U
    U = [e.copy() for e in A]
    for i in range(n):
        for j in range(i):
            U[i][j] = 0.0
    # L
    L = [e.copy() for e in A]
    for i in range(n):
        for j in range(n-1,i,-1):
            L[i][j] = 0.0
        L[i][i] = 1.0
    return PZ, L, U

'''
https://nttdocomo-developers.jp/entry/2024/02/17/090000
スバラしき逆行列の世界

・LU分解 三角行列

'''
def lu_decomposition_with_partial_pivoting(mA, EPS=1.0e-7):
    n = len(mA)
    A = [e.copy() for e in mA]
    L = [ [0 for _ in range(n)] for _ in range(n)]
    U = [ [0 for _ in range(n)] for _ in range(n)]
    P = [_ for _ in range(n)]
    if n == 1:
        L[0][0] = 1
        U[0][0] = A[0][0]
        return P, [[1]], [[A[0][0]]]        
    for i in range(n):
        #
        #  pivot = np.argmax(np.abs(A[i:, i])) + i
        #
        pivot = i
        pv = A[i][i]
        for k in range(i,n):
            if abs(A[k][i]) > pv:
                pivot = k
                pv = abs(A[k][i])
        #--^^
        if pivot != i:
            # A[[i, pivot]] = A[[pivot, i]]
            for k in range(n):
                xa = A[pivot][k]
                A[pivot][k] = A[i][k]
                A[i][k] = xa
            xx = P[pivot]
            P[pivot] = P[i]
            P[i] = xx
            if i > 0:
                # L[[i, pivot], :i] = L[[pivot, i], :i]
                for k in range(i):
                    xl = L[pivot][k]
                    L[pivot][k] = L[i][k]
                    L[i][k] = xl
        
        L[i][i] = 1
        for j in range(i, n):
            #
            # (np.dot(L[i, :i], U[:i, j])
            #
            sum1 = 0
            for k in range(i):
                sum1 += L[i][k] * U[k][j]
            #
            # U[i, j] = A[i, j] - np.dot(L[i, :i], U[:i, j])
            #
            U[i][j] = A[i][j] - sum1
        #if abs(U[i][i]) < EPS:
        #    return None, None, None
        for j in range(i+1, n):
            #
            # np.dot(L[j, :i], U[:i, i])
            #
            sum2 = 0
            for k in range(i):
                sum2 += L[j][k] * U[k][i]
            #
            # L[j, i] = (A[j, i] - np.dot(L[j, :i], U[:i, i])) / U[i, i]
            #  
            if abs(U[i][i]) < EPS:
                return None, None, None
            L[j][i] = (A[j][i] - sum2) / U[i][i]

    return P, L, U

def matrix_dmp(msg, A):
    print(msg, " MATRIX:")
    n = len(A)
    for i in range(n):
        for j in range(n):
            print(" % 0.4f" % (A[i][j]), end='')
        print("")

def chk(a):
    if type(a) == list:
        if len(a) == 0:
            return None
        else:
            if type(a[0]) != list:
                A = [a.copy()]
            else: 
                A = [e.copy() for e in  a]
        n = len(A)
        m = len(A[0])
    else:
        n = 0
        m = 0
    if m != n or n == 0: # 正方行列のみ
        return None
    return A

if __name__ == '__main__':

    import numpy as np

    def permutation(P, mat):
        '''
          順列 交換回数計算
               matrixをもとに戻す
        '''
        n = len(P)
        Z = [e for e in P]
        cnt = 0
        for i in range(n):
            if Z[i] != i:
                min = i
                for j in range(i+1,n):
                    if Z[j] < Z[min]:
                        min = j
                for j in range(n):
                    xx = mat[min][j]
                    mat[min][j] = mat[i][j]
                    mat[i][j] = xx 
                xx = Z[min]
                Z[min] = Z[i]
                Z[i] = xx
                cnt += 1
        return cnt


    def gen_matrix(n=0, RMAX=50, DCP=1):
        '''
            行列生成 N x N
              n = 0 : ランダムNxN , 9 : 9 x 9行列
              RMAX = 50 : (+-50)で要素データ、 99: (+-99)で要素データ
              DCP = 1 : 要素データ * 10,  +9 : 要素データ * (10**9) 、 -9 : 要素データ / (10**9)
        '''
        import random as r
        DC = 10**abs(DCP)
        if n == 0:
            N = r.randrange(10,41) # 10x10 ~ 40x40の行列を作る
        else:
            N = n                  # n x n の行列を作る
        nx = r.randrange(N*4)  # 時々、対角優位行列でなくする
        m = []
        for i in range(N):
            m.append([r.randrange(-RMAX,RMAX+1) for j in range(N)])
        for i in range(N):
            if i != nx:
                ml = 0
                for j in range(N):
                    if i != j:
                        ml += abs(m[i][j])
                if m[i][i] < 0:
                    m[i][i] -= ml
                else:
                    m[i][i] += ml
        for i in range(N):
            for j in range(N):
                if DCP < 0:
                    m[i][j] /= DC
                else:
                    m[i][j] *= DC

        return m

    def testMatrix(nc, EPS=1.0e-7):
        for n in range(1, nc+1):
            print("")
            print("TEST MATRIX No.", n)
            A = gen_matrix(RMAX=360, DCP=-3)
            nn = len(A)
            print("  %d x %d 行列" % (nn,nn))
            print("  numpy RANK:", np.linalg.matrix_rank(A))
            #P1, L1, U1 = lu_decomposition_with_partial_pivoting(A)
            P1, L1, U1 = lu(A)
            if L1 is None:         # 左辺行列がない
                print(" 計算できません")
            else:
                print("..検算:")
                lxu = np.dot(L1,U1)
                det = 1
                for i in range(len(A)):
                    det *= U1[i][i]
                s = permutation(P1, lxu)
                if s & 1:
                    det = -det
                ndet = np.linalg.det(A)
                diff = abs(det-ndet)/abs(ndet)
                if diff < EPS:
                    print(" det() OK")
                else:
                    print(" det() ??NG")
                    print(" DET:",det)
                    print(" numpy det:",ndet)
                if np.allclose(A, lxu):
                    print(" matrix OK")
                else:
                    print(" matrix ??NG")
            
    def test(msg,mat, EPS=1.0e-7):

        print("\n",msg," ● ***Results***")
        print("Used A ---")
        print(mat)
        print("**Answers**")
        A = chk(mat)
        if A is None:
            print("計算できません")
            return
        print("  numpy RANK:", np.linalg.matrix_rank(A))
        #P1, L1, U1 = lu_decomposition_with_partial_pivoting(A)
        P1, L1, U1 = lu(A)

        if L1 is None:
            print(" 計算できません")
        else:
            matrix_dmp("L1:",L1)
            matrix_dmp("U1:",U1)
            lxu = np.dot(L1,U1)
            print("行入れ替え情報:", P1)
            det = 1
            for i in range(len(A)):
                det *= U1[i][i]
            s = permutation(P1, lxu)
            if s & 1:
                det = -det
            print("DET:",det)
            if abs(det) < EPS:
                print(" DET() == ZERO")
            ndet = np.linalg.det(A)
            print("numpy det:",ndet)
            print("..検算..")
            if np.allclose(det, ndet):
                print(" det() OK")
            else:
                print(" det() ??NG")
            if np.allclose(A, lxu):
                print(" matrix OK")
            else:
                print(" matrix ??NG")
    
    test("計算−1",[[2, 3, 1, -3],[-1, 2, 2, 4],[4, 1, -3, 5],[5, -4, -4, 1]])
    test("計算−2",[[2,0],[0,5]])
    test("計算−3",[ [0.0, 1.0],[1.0, 0.0] ])
    test("計算−4",[[4]])
    test("計算−5",[0.0])
    test("計算−6",[[-1, 1, 3],[2, 3, -1],[3, 4, -2]])
    test("計算−7",[[1, 3, 9],[-1, 1, -1],[2, -4, -2]])
    test("計算−8",[[1,-1,-1],[-1,1,-1],[-1,-1,1]])
    test("計算-9",[[-5, -1, 10, -10], [-9, 3, -9, -7], [9, -4, -10, 0], [-3, 7, 7, -9]])
    test("計算−10",[[0,-2,0],[-1,5,2],[0,-1,1]])
    test("計算−11",[[0,0,3],[-1,5,2],[0,-1,2]])
    test("計算−12",[[1, 2, 2],[2, 1, 2],[2, 2, 1]])
    test("計算−13",[ [0.0, -1.0, 1.0, 0.0, -1.0] ,[4.0, 4.0, 2.0, 1.0, 1.0] ,[4.0, 1.0, 1.0, 3.0, 2.0] ,[0.0, 3.0, -1.0, 4.0, -2.0] ,[-1.0, -1.0, -1.0, -1.0, -1.0] ])
    print("\no o o o o o o")
    testMatrix(5)
----
2024-07-08 「余因子展開逆行列計算」
参考:
 初等線形代数ー考え方と応用プログラムー    石原辰雄、長谷川勝也 著 共立出版 1988

余因子展開で逆行列計算をやってみた。

$ python INV余因子展開.py
Input matrix is :
 0.00000000 -2.00000000  0.00000000 
-1.00000000  5.00000000  2.00000000 
 0.00000000 -1.00000000  1.00000000 

The Adjoint is :
-3.50000000 -1.00000000  2.00000000 
-0.50000000 -0.00000000 -0.00000000 
-0.50000000 -0.00000000  1.00000000 
検算 invert @ A:
 1.00000000  0.00000000  0.00000000 
 0.00000000  1.00000000  0.00000000 
 0.00000000  0.00000000  1.00000000 
numpy.inv:
-3.50000000 -1.00000000  2.00000000 
-0.50000000 -0.00000000 -0.00000000 
-0.50000000  0.00000000  1.00000000 

--- INV余因子展開.py ---
def fdet(A, n):
   '''
    My行列式計算
   '''
   det = 0
   if n == 1:
      det = A[0][0]
   elif n == 2:
      det = A[0][0] * A[1][1] - A[0][1] * A[1][0]
   else: 
      for x in range(n):
          submatrix = [ e.copy() for e in A]
          del submatrix[0]
          [ e.pop(x) for e in submatrix]
          det = det + (-1)**(x) * A[0][x] * fdet(submatrix, n-1)
          del submatrix
   return det

def cofactor(A, ia, ja):
  '''
    余因子展開  [0][0]  [0][1]  [0][2] ... [2][2] ....
      0123    0123    0123    0123       0123
     0 ABCD  0 ....  0 ....  0 ....     0 AB.D 
     1 EFGH  1 .FGH  1 E.GH  1 EF.H     1 EF.H
     2 IJKL  2 .JKL  2 I.KL  2 IJ.L     2 ....
     3 MNOP  3 .NOP  3 M.OP  3 MN.P     3 MN.P 

   余因子部 行列式計算
  '''
  n = len(A)
  ny = n - 1
  # 余因子展開
  YY = [e.copy() for e in A]
  del YY[ia]
  [ e.pop(ja) for e in YY]
  # determinant 余因子 行列式計算
  cdet = fdet(YY, ny)
  del YY
  return cdet

def inv0(A):
  '''
   逆行列計算
  Y:余因子行列(adjugate matrix)
   det : 行列式計算結果
   det = Y[0][0] * A[0][0] - (Y[1][0] * A[0][1]) + (Y[2][0] * A[0][2]) - ... + ... . . .
   Y[i][j] = Y[i][j] / det  (逆行列計算)
   return {Y or None}
  '''
  n = len(A)
  if n == 1:
    det = A[0][0]
    Y = [[1.0]]
  else:   
    Y = [[0.0 for _ in range(n)] for _ in range(n)]
    for i in range(n):
      for j in range(n):
        # Set cofactor determinat to adjugate matrix
        Y[j][i] = cofactor(A, i, j)
    # Calculate determinant
    det = 0.0
    for i in range(n):
      if i & 1:
        det -= (A[0][i] * Y[i][0])
      else:
        det += (A[0][i] * Y[i][0])
    # Calculate end
  if abs(det) < 0.000000001:
    return None 
  # Calculate inverse matrix
  #  Matrix SIGN         C0 C1 C2 C3 C4 . . .
  #                   R0| +  -  +  -  + - + -
  #                   R1| -  +  -  +  - + - +
  #                   R2| +  -  +  -  + - + -
  #                     | :  :  :  :  : : : :
  #  Rn(n-int(n/2)) == 0| +  -  +  -  + - + -
  #  Rn(n-int(n/2)) == 1| -  +  -  +  - + - +
  #
  for i in range(n):
    for j in range(n):
      if ((i & 1) + (j & 1)) & 1:
        Y[i][j] = ((-1) * Y[i][j]) / det
      else:
        Y[i][j] = Y[i][j] / det
  # Set inverse matrix
  return Y

def display(A):
  '''
   行列 表示
  '''
  for i in range(N):
    for j in range(N):
      print("% 3.8f " % (A[i][j]), end="")
    print()

if ( __name__ == '__main__' ):
  import numpy as np

  #A = [[5, -2, 2, 7], [1, 0, 0, 3], [-3, 1, 5, 0], [3, -1, -9, 4]]
  #A = [[1, 3, 9],
  #     [-1, 1, -1],
  #     [2, -4, -2]] # 非正則
  A = [
       [0, -2, 0], 
       [-1, 5, 2],
       [0, -1, 1]]
  #A = [[-1, 1, 3],
  #     [2, 3, -1],
  #     [3, 4, -2]] # 非正則
  #A = [[-6, -2, -9, -2], [-10, 3, -8, 11], [7, -9, -9, 5], [-11, 8, 5, 5]]
  N = len(A)

  print("Input matrix is :")
  display(A)

  print("\nThe Adjoint is :")
  adj = inv0(A)
  if adj == None:
    print("逆行列ができません。")
    exit()
  display(adj)
  print("検算 invert @ A:")
  km = np.array(adj) @ A
  display(km)
  del km
  del adj
  print("numpy.inv:")
  nui = np.linalg.inv(A)
  display(nui)
  del nui

2024-06-15 「HILL暗号復号キー」
HILL暗号の復号キーの作り方がわからなくて探してしまった。
以下例題。

---- hill_decode_key.py ---
'''
   Hill暗号
   暗号復号キーのテスト

  参照:
   https://github.com/krshrimali/Hill-Cipher
   krshrimali/Hill-Cipher

'''

import numpy as np

def multi_inverse(b, n):
    r1 = n
    r2 = round(b,0)
    t1 = 0
    t2 = 1
    inv_t = None
    while(r1 > 0 and r2 != 0 ):
        q = int(r1/r2)
        r = r1 - q * r2
        r1 = r2
        r2 = r
        t = t1 - q * t2
        t1 = t2 
        t2 = t

        if(r1 == 1):
            inv_t = t1
            break

    return inv_t

''' 暗号文ダンプ '''
def dump_m(str,m):
  print(str, end='')
  print(" \"", end='')
  for x in m:
    for y in x:
      print(chr(int(y)+0x20),end='')
  print("\"")
  for x in m:
    for y in x:
      print(" %d [%c]" % (int(y), int(y)+0x20), end='')
    print('')

''' 暗号復号キー作成 (整数) '''
def gen_encode_key(key, mod):
  n = len(key)
  m = len(key[0])
  det = np.linalg.det(key)
  ekey = np.linalg.inv(key) * det * multi_inverse(det, mod) % mod
  tm = ekey.tolist()
  for i in range(n):
    for j in range(m):
      tm[i][j] = round(tm[i][j],0)
  return np.array(tm)

# ******* Main ********
mn = 3     # 3行3列行列暗号キー
mod = 0x5B # 暗号電文コードであつかう法 0x20 - 0x7A
ss = 0x20  # 開始文字コード 空白
txt = [[19],[35],[51]] # 暗号文 "3CS" 3次列ベクトル
ks = (0x30 - 0x20)  # 暗号キー 行列要素開始文字'0'
ke = (0x5A - 0x20)  # 暗号キー 行列要素終了文字'Z'

n = 0
while True:
  key_matrix = np.random.randint(ks,ke,(mn,mn)).tolist()
  minv =  multi_inverse(np.linalg.det(key_matrix), mod)
  if minv == None:
    continue
  print(".... No. %d ...." % (n+1))
  print("   KEY:",key_matrix)
  for i in range(mn):
    for j in range(mn):
      print(chr(key_matrix[i][j]+ss), end='')
    print('')

  key_matrix_inv = gen_encode_key(key_matrix, mod)
  print("key_inv:", key_matrix_inv.tolist())
  p = np.array(key_matrix) @ txt % mod
  dump_m("暗号変換:", p)
  # 暗号復号
  en = key_matrix_inv @ p % mod
  dump_m("暗号復号:", en)
  n += 1
  if n >= 3:
    break
......
実行。
$ python hill_decode_key.py

.... No. 1 ....
   KEY: [[19, 17, 23], [44, 45, 23], [48, 55, 54]]
317
LM7
PWV
key_inv: [[54.0, 51.0, 21.0], [85.0, 52.0, 4.0], [39.0, 50.0, 43.0]]
暗号変換: "DCH"
 36 [D]
 35 [C]
 40 [H]
暗号復号: "3CS"
 19 [3]
 35 [C]
 51 [S]
.... No. 2 ....
   KEY: [[44, 32, 41], [46, 26, 37], [42, 38, 22]]
L@I
N:E
JF6
key_inv: [[32.0, 77.0, 88.0], [51.0, 13.0, 32.0], [8.0, 87.0, 87.0]]
暗号変換: "K?a"
 43 [K]
 31 [?]
 65 [a]
暗号復号: "3CS"
 19 [3]
 35 [C]
 51 [S]
.... No. 3 ....
   KEY: [[50, 29, 47], [33, 28, 30], [48, 54, 55]]
R=O
A<>
PVW
key_inv: [[45.0, 44.0, 12.0], [46.0, 52.0, 68.0], [38.0, 76.0, 75.0]]
暗号変換: "uKX"
 85 [u]
 43 [K]
 56 [X]
暗号復号: "3CS"
 19 [3]
 35 [C]
 51 [S]

2024-06-14 「Hill暗号」
検索で見つけたPDFに、行列計算で HILL暗号ができるとあったのでちょっとやってみた。

ものを知らないと時間がかかるなあ。
暗号キーは何でもいいとうわけではないようだ。復号キーを作るときに正しくできない場合がある。
キーの設定後、正しく復号できたかをチェックすること。

--- hill_2.py ----
''' 
   HILL暗号プログラム

   参照:https://www.geeksforgeeks.org/hill-cipher/
     Hill Cipher
    
    http://axoluder.seesaa.net/article/310022099.html
     ヒル暗号(暗号化・復号編)

    ”Cryptography in an algebraic alphabet” L.S.Hill, Amer. Math. Monthly, v. 36,1929, p. 306-31

    "Applications of Linear Algebra Data Encryption" Scott Gregory MATH 308

'''
import numpy as np

''' KEY計算 '''
def gen_key(key):
  from sympy import Matrix

  i = len(key)
  if 1 > i > 9:
    return None,None
  km = [[0 for i in range(3)] for j in range(3)]
  for i in range(i):
    if 0x20 <= ord(key[i]) < 0x7B:
      km[i//3][i%3] = ord(key[i]) - 0x20
  tmpk = Matrix(km)
  return km, tmpk.inv_mod(0x5B).tolist()

''' 暗号文ダンプ '''
def dump_m(str,m):
  print(str, end='')
  print(" \"", end='')
  for x in m:
    for y in x:
      print(chr(int(y)+0x20),end='')
  print("\"")
  for x in m:
    for y in x:
      print(" %02X [%c]" % (int(y), int(y)+0x20), end='')
    print('')

print("# ********************")
print("#  Hill暗号プログラム")
print("# ********************\n")
print("# 暗号キー設定")
key, inv_key = gen_key("PWBEWCXBO")
# 暗号変換キー表示
print("  暗号キー:", key)
# 暗号復号キー表示
print("暗号復号キー:", inv_key)
KEY = np.array(key)
ENCODE = np.array(inv_key)
print("# 入力電文は、コード0x20~0x7B(空白、記号、A-Z,a-z)")
print("# 暗号キーが3次行列なので、電文は3行n列行列にして不足分は空白を埋める")
b = "Hi, It's awesome."
c = len(b)
n = c // 3
if n * 3 < c:
  n += 1
#
# 暗号キーが3次行列なので、暗号文は3行
#
a = [[ 0 for i in range(n)] for j in range(3)]
for i in range(c):
  if 0x20 <= ord(b[i]) < 0x7B:
    a[i//n][i%n] = ord(b[i]) - 0x20
dump_m("入力電文:", a)
# 暗号変換
p = KEY @ a % 0x5B
dump_m("暗号変換:", p)
# 暗号復号
en = ENCODE @ p % 0x5B
dump_m("暗号復号:", en)
----
実行。
$ python hill_2.py
# ********************
#  Hill暗号プログラム
# ********************

# 暗号キー設定
  暗号キー: [[48, 55, 34], [37, 55, 35], [56, 34, 47]]
暗号復号キー: [[73, 2, 58], [13, 80, 53], [74, 23, 1]]
# 入力電文は、コード0x20~0x7B(空白、記号、A-Z,a-z)
# 暗号キーが3次行列なので、電文は3行n列行列にして不足分は空白を埋める
入力電文: "Hi, It's awesome. "
 28 [H] 49 [i] 0C [,] 00 [ ] 29 [I] 54 [t]
 07 ['] 53 [s] 00 [ ] 41 [a] 57 [w] 45 [e]
 53 [s] 4F [o] 4D [m] 45 [e] 0E [.] 00 [ ]
暗号変換: "?1)&H!F5MkZn)c.txK"
 1F [?] 11 [1] 09 [)] 06 [&] 28 [H] 01 [!]
 26 [F] 15 [5] 2D [M] 4B [k] 3A [Z] 4E [n]
 09 [)] 43 [c] 0E [.] 54 [t] 58 [x] 2B [K]
暗号復号: "Hi, It's awesome. "
 28 [H] 49 [i] 0C [,] 00 [ ] 29 [I] 54 [t]
 07 ['] 53 [s] 00 [ ] 41 [a] 57 [w] 45 [e]
 53 [s] 4F [o] 4D [m] 45 [e] 0E [.] 00 [ ]
2024-07-31 「行列式計算」
逆行列計算で正則行列でなくても結果がでるので、行列式計算をやってみた。
ガウス・ジョルダン消去法での計算追加。

$ python det.py
**** TEST No.1 *****
入力:  MATRIX:
[ ]
.
My det() 計算できません
.
gauss-jordan det() 計算できません
.

**** TEST No.2 *****
入力:  MATRIX:
[  3.00000 ]
.
my Det(): 3
.
gauss-jordan Det(): 3.0
.
numpy det(): 3.0000000000000004
numpy Rank(): 1

**** TEST No.3 *****
入力:  MATRIX:
[  0.00000 -2.00000  0.00000 ]
[ -1.00000  5.00000  2.00000 ]
[  0.00000 -1.00000  1.00000 ]
.
my Det(): -2
.
gauss-jordan Det(): -2.0
.
numpy det(): -2.0
numpy Rank(): 3

**** TEST No.4 *****
入力:  MATRIX:
[  1.00000 -1.00000 -1.00000 ]
[ -1.00000  1.00000 -1.00000 ]
[ -1.00000 -1.00000  1.00000 ]
.
my Det(): -4
.
gauss-jordan Det(): -4.0
.
numpy det(): -4.0
numpy Rank(): 3

**** TEST No.5 *****
入力:  MATRIX:
[  7.00000  2.00000 -4.00000  2.00000  3.00000 ]
[  1.00000  5.00000  2.00000  0.00000  3.00000 ]
[ -5.00000 -6.00000  3.00000  1.00000  2.00000 ]
[  0.00000  2.00000  7.00000  4.00000  3.00000 ]
[  4.00000  2.00000 -5.00000 -3.00000  5.00000 ]
.
my Det(): -2346
.
gauss-jordan Det(): -2346.0
.
numpy det(): -2345.999999999999
numpy Rank(): 5

**** TEST No.6 *****
入力:  MATRIX:
[  1.00000  0.00000  5.00000 ]
[  3.00000  0.00000 -1.00000 ]
[  4.00000  0.00000  2.00000 ]
.
my Det(): 0
.
gauss-jordan det() 計算できません
.
numpy det(): 0.0
numpy Rank(): 2

**** TEST No.7 *****
入力:  MATRIX:
[  1.00000  3.00000  9.00000 ]
[ -1.00000  1.00000 -1.00000 ]
[  2.00000 -4.00000 -2.00000 ]
.
my Det(): 0
.
gauss-jordan det() 計算できません
.
numpy det(): 1.1102230246251546e-15
numpy Rank(): 2

**** TEST No.8 *****
入力:  MATRIX:
[ -1.30000  1.60000  3.20000 ]
[ -4.60000  5.70000 -2.60000 ]
[ -1.20000  0.20000  6.30000 ]
.
my Det(): 22.94499999999999
.
gauss-jordan Det(): 22.944999999999993
.
numpy det(): 22.944999999999993
numpy Rank(): 3
......................

--- det.py -------
def determinant(mm):
    '''
     My行列式計算 正方行列制限、計算実行
    '''
    A = chk(mm)
    if A is None:
        return None
    n = len(A)
    return fdet(A, n)

def fdet(A, n):
    '''
     My行列式計算
    '''
    det = 0
    if n == 1:
        det = A[0][0]
    elif n == 2:
        det = A[0][0] * A[1][1] - A[0][1] * A[1][0]
    else: 
        for x in range(n):
            submatrix = [ e.copy() for e in A]
            del submatrix[0]
            [ e.pop(x) for e in submatrix]
            det = det + (-1)**(x) * A[0][x] * fdet(submatrix, n-1)
    return det

def gj_det(PA, E=1.0E-7):
    '''
     gauss-jordan 消去法で行列計算

     参照:初等線形代数 --考え方と応用プログラム--   石原辰雄 著 共立出版 1986,1988
           DET.GJ2
    '''
    A = chk(PA)
    if A is None:    
        return None
    n = len(A)
    det = 1.0
    for i in range(n):
        am = 0
        ii = 0
        for k in range(i,n):
            ab = abs(A[k][i])
            if ab > am:
                am = ab
                ii = k
        if am < E:
            return None
        if i != ii:
            det = -det
            for j in range(i,n):
                xx = A[i][j]
                A[i][j] = A[ii][j]
                A[ii][j] = xx
        aii = A[i][i]
        det *= aii
        for j in range(n):
            A[i][j] /= aii
        for k in range(n):
            if k != i:
                ww = A[k][i]
                for j in range(i,n):
                    A[k][j] -= ww * A[i][j]
    return det

def gen_matrix():
    '''
    行列生成 N x N
    '''
    import random as r
    N = r.randrange(3,7)
    RMAX = 70
    m = []
    for i in range(N):
        m.append([r.randrange(-RMAX,RMAX)/10 for j in range(N)])
    return m

def matrix_dmp(msg, MAT):
    '''
     行列の印刷
    '''
    print(msg, " MATRIX:")
    if MAT is None:
        print("  結果がありません")
        return
    if len(MAT) == 0:
        A = [[]]
    else:
        if type(MAT[0]) == list:
            A = [e.copy() for e in MAT]
        else:
            A = [MAT]
    n = len(A)
    nm = len(A[0])
    for i in range(n):
        print("[",end='')
        if nm <= n:
            for j in range(nm):
                print(" % .5f" % (A[i][j]), end='')
        else:
            for j in range(n):
                print(" % .5f" % (A[i][j]), end='')
            print(" |",end='')
            for j in range(n,nm):
                print(" % .5f" % (A[i][j]), end='')
        print(" ]")

def chk(m):
    if type(m) == list:
        if len(m) == 0:
            return None
        else:
            if type(m[0]) != list:
                A = [m.copy()]
            else: 
                A = [e.copy() for e in  m]
        n = len(A)
        m = len(A[0])
    else:
        n = 0
        m = 0
    if m != n: # 正方行列のみ
        return None
    return A


if __name__ == '__main__':
    import numpy as np

    t = 1
    def test(m):
        global t
        print("**** TEST No.%d *****" % (t))
        t += 1
        matrix_dmp("入力:",m)
        print(".")
        det = determinant(m)
        if det is None:
            print("My det() 計算できません")
        else:
            print("my Det():", det)
        print(".")
        det = gj_det(m)
        if det is None:
            print("gauss-jordan det() 計算できません")
        else:
            print("gauss-jordan Det():", det)
        print(".")
        nm = chk(m)
        if nm is not None:
            print("numpy det():", np.linalg.det(nm))
            print("numpy Rank():", np.linalg.matrix_rank(nm))
        print("")


    test([])
    test([3])
    test([[0,-2,0],[-1,5,2],[0,-1,1]])
    test([[1,-1,-1],[-1,1,-1],[-1,-1,1]])
    test([[7,2,-4,2,3],[1,5,2,0,3],[-5,-6,3,1,2],[0,2,7,4,3],[4,2,-5,-3,5]])
    test([[1,0,5],[3,0,-1],[4,0,2]])
    test([[1,3,9],[-1,1,-1],[2,-4,-2]])
    test(gen_matrix())
---
参照:https://colab.research.google.com/github/colbrydi/MatrixAlgebra/blob/main/docs/_sources/09--Determinants_pre-class-assignment.ipynb#scrollTo=zzVEI_6JiHWG
   09 Pre-Class Assignment: Determinants
[troff-color.png]
2024-05-12 「Heirloom-doctools 色」
.CL green This
.CL red  color
.CL blue
 on print \X'SetColor:blue on green'\fBis Blue.\fP

.PS
box "\fBBOX\fP"
.PE

\X'SetColor:white on black'\fBFill Color is \X'SetColor:red on black'Gray\fP. 
\X'SetColor:blue on yellow'Box line is NOT Green if box with \X'SetColor:white on black'\fBfill.
\fP\X'SetColor:'This color is black.

Allows colors on "color1 on color2" are
.br
   \X'SetColor:1.0 0.2 0.5 rgb'red , green , blue , cyan , magenta , yellow , white , black.
-------------------------
$ pic color.pic |troff -ms -mcolor | dpost > Post.ps
2024-05-11 「Heirloom-doctools EQN」
(1) 数式名称

.EQ 表示位置 数式名称
  表示位置:左寄せ、中央寄せ
  数式名称:表示名称となる

表示:
  x ** 2 + 2 x + 2 = 0                             数式名称

troff -me ..  : 「-me」がないと数式名称が表示されない。

漢字フォント切り替えをきちんとやらないと数式名称を指定してもゴミ数字1,2等が表示される。
  \fJ日本語\fP abcd <<== 注意★

 |x ** 2 + 2 x + 2 = 0 ★                            数式名称|
            ↑数字表示になる

(2) .nr 番号レジスタ

.nr 名前 初期値 加算値
  名前:レジスタ名 1,2,3文字の名前
  初期値: .nrは整数カウンタ。その初期値を設定する。
  加算値: 呼び出し毎に加減算する値。

使用:
  xxx\n+X    : xxx9 表示。1文字レジスタ名のとき。
  xxx\n+(XX  : xxx9 表示。2文字レジスタ名のとき。
  xxx\n+[XXX]: xxx9 表示。3文字レジスタ名のとき。
       3文字名称を使う場合は、レジスタ定義前に、
    .do xflag 3
       を記述する。

   $ troff -rNN=1 xxx.trof | dpost > xxx.ps
    番号レジスタ定義と初期値を与える。

(3) Xバー表示
[troff-bar.png]
... EQN ...
.fp 0 J GenJyuuGothic-Monospace-Normal
.fp 0 JB GenJyuuGothic-Monospace-Bold
.ft CW

.EQ
delim $$
.EN
$x dot$
$x dotdot$
$x hat$
$x tilde$
$x vec$
$x dyad$
$x under$
$x bar$

\f(JBxバーがずれる。\fP\fJどうしても揃えるとき\fP
$pile { ~~ x} bar$
...

(4) .DS ~ .DE
  DS定義をして EQ リクエストエラーになる場合は、DS定義前に".DS[改行].DE"を入れる。

 \" ダミーEQ-EN
 .EQ
  .EN

  .DS
   ; 以下 EQN 記述
[troff-utf8.png]

2024-05-15 「heirloom-doctools」
参照:https://github.com/n-t-roff/heirloom-doctools/issues/85
  Build problem #85
(1) Computing Science Technical Report No. 116
    PIC — A Graphics Language for Typesetting User Manual  / Brian W. Kernighan
    AT&T Bell Laboratories
(2) Tbl — A Program to Format Tables / L. L. Cherry, M. E. Lesk / AT&T Bell Laboratories
(3) Heirloom Documentation Tools Nroff/Troff User’s Manual 
     Joseph F. Ossanna, Brian W. Kernighan, Gunnar Ritter, ...others
(4) Document Formatting and Typesetting on the UNIX System"
     Second Edition Volume I (1987), II (1988) / Narain Gehani, Steven Lally / SILICON PRESS
(5) Font Handling in Troff With PostScript Devices
    Gunnar Ritter 10 / 24 / 06
(6) https://github.com/arnoldrobbins/dformat
    arnoldrobbins/dformat  (データ構造印刷 AWK スクリプト)
(7) https://troff.org/prog.html
    troff and its companion programs
(8) DFORMAT — A Program for Typesetting Data Formats / Jon L. Bentley / AT&T Bell Laboratories

行列計算をやったので数式を清書してみたいと思ってroff-eqn | tbl | pic | grap をまたやってみた。
Heirloom Doctools を使う。昔からの書き方が使えるので。
UTF-8日本語マニュアルが清書できるようになっていた。

$ git clone https://github.com/n-t-roff/heirloom-doctools.git

$ sudo apt install -y cmake
$ sudo apt install -y bison flex
$ sudo apt install -y byacc
$ YACC=/usr/bin/byacc
$ export YACC
$ cd heirloom-doctools

$ ./configure
$ make
$ sudo make install

....
dpost , grap等は /usr/local/ucb にある
$ ls /usr/local/ucb
addbib   col    eqn      lookbib  otf_info  ptx      soelim   tbl
checkeq  dhtml  grap     neqn     pic       refer    sortbib  troff
checknr  dpost  indxbib  nroff    picpack   roffbib  ta       vgrind

(o)clear
$ make  mrproper

(o)alias
$ nano ~/.bash_aliases
...
alias nroff='/usr/local/ucb/nroff'
alias troff='/usr/local/ucb/troff'
alias tbl='/usr/local/ucb/tbl'
alias eqn='/usr/local/ucb/eqn'
alias neqn='/usr/local/ucb/neqn'
alias dpost='/usr/local/ucb/dpost'
alias col='/usr/local/ucb/col'
alias grap='/usr/local/ucb/grap'
alias pic='/usr/local/ucb/pic'
...
$ . ~/..bash_aliases
aliasが登録される。
$ alias
  コマンドで確認すること。
 次回のログオンから自動登録される。

日本語manページダウンロード
https://linuxjm.sourceforge.io/download.html
マニュアルアーカイブのダウンロード

https://linuxjm.sourceforge.io/man-pages-ja-20231115.tar.gz
解凍。
man-pages-ja-20231115/manual/GNU_coreutils/man1/ls.1
を使う。

$ tbl -Tlocale ls.1 | neqn | nroff -Tlocale -mg -mandoc | col -x | ul
  これで日本語マニュアルページが見える。

$ tbl -Tlocale ls.1 | neqn | nroff -Tlocale -mg -mandoc | col -bx > ls.txt
 これで日本語マニュアルページのテキストになる。

$ nroff -ms -mandoc ls.1 | col -xb | paps --font="IPAMincho" > ls.ps
 これで日本語マニュアルページのPostscriptファイルになる。
 col -xb はバックスペースコードを削除する。
 paps は sudo apt install paps でインストールする。

 --font=desc
     Use  font  based  on  description desc. Default is "Courier 10".
     The format of the string representation is:

     "[family-list] [style-options] [size]"

   where family-list is a comma separated list of families  option-
     ally  terminated by a comma, style-options is a whitespace sepa-
     rated list of words where each  word  describes  one  of  style,
     variant,  weight,  or  stretch, and size is a decimal number for
     size in points, e.g. "Courier,Monospace Bold Italic 10".
 指定がないとゴシック文字。フォントのファミリー名指定は、
  fc-list より、フォント名称にある英文字IPAMincho等を指定する。

GRAP,PIC,EQN,TBLは、

$ /usr/local/ucb/grap FILE.grap| /usr/local/ucb/pic |/usr/local/ucb/tbl |/usr/local/ucb/eqn | /usr/local/ucb/troff -ms |/usr/local/ucb/dpost  > FILE.ps

$ evince FILE.ps  ->  印刷 PDF
で見える。

troff入力ファイル内にフォント割当をすると日本語が使える。
 $ fc-list|grep -e ipa -e takao
  ---
  /usr/share/fonts/opentype/ipafont-mincho/ipam.ttf: IPA明朝,IPAMincho:style=Regular
  /usr/share/fonts/truetype/takao-mincho/TakaoPMincho.ttf: Takao P明朝,TakaoPMincho:style=Regular
  /usr/share/fonts/opentype/ipafont-gothic/ipagp.ttf: IPA Pゴシック,IPAPGothic:style=Regular
  /usr/share/fonts/opentype/ipafont-mincho/ipamp.ttf: IPA P明朝,IPAPMincho:style=Regular
  /usr/share/fonts/opentype/ipafont-gothic/ipag.ttf: IPAゴシック,IPAGothic:style=Regular
  /usr/share/fonts/truetype/takao-gothic/TakaoPGothic.ttf: Takao Pゴシック,TakaoPGothic:style=Regular
  /usr/share/fonts/truetype/takao-gothic/TakaoGothic.ttf: Takaoゴシック,TakaoGothic:style=Regular
  /usr/share/fonts/truetype/takao-mincho/TakaoMincho.ttf: Takao明朝,TakaoMincho:style=Regular
  ---
  $ fc-list :lang=ja
   日本語フォント一覧

  troff ファイル
 ...
  .fp 0 G TakaoMincho <<== ファイル名 ipam 等
  .ft G
  ...で指定する。
 $ TROFFONTS=/usr/share/fonts/truetype/takao-mincho
 $ export TROFFONT
  環境変数を設定する。


http://jikasei.me/font/genjyuu/
 源柔ゴシック : genjyuugothic-20150607.7z (49.7 MB)

https://ftp.iij.ad.jp/pub/osdn.jp/users/8/8636/genjyuugothic-20150607.7z

解凍して、/usr/share/fonts/truetype/noto_jpを作成してコピーする。

$ sudo ls /usr/share/fonts/truetype/noto_jp
GenJyuuGothic-Bold.ttf			GenJyuuGothic-Monospace-Regular.ttf
GenJyuuGothic-ExtraLight.ttf		GenJyuuGothic-Normal.ttf
GenJyuuGothic-Heavy.ttf			GenJyuuGothic-P-Bold.ttf
GenJyuuGothic-Light.ttf			GenJyuuGothic-P-ExtraLight.ttf
GenJyuuGothic-Medium.ttf		GenJyuuGothic-P-Heavy.ttf
GenJyuuGothic-Monospace-Bold.ttf	GenJyuuGothic-P-Light.ttf
GenJyuuGothic-Monospace-ExtraLight.ttf	GenJyuuGothic-P-Medium.ttf
GenJyuuGothic-Monospace-Heavy.ttf	GenJyuuGothic-P-Normal.ttf
GenJyuuGothic-Monospace-Light.ttf	GenJyuuGothic-P-Regular.ttf
GenJyuuGothic-Monospace-Medium.ttf	GenJyuuGothic-Regular.ttf
GenJyuuGothic-Monospace-Normal.ttf

使う前にTROFFONTS環境変数にパス/usr/share/fonts/truetype/noto_jpを追加すること。
UTF-8漢字コードと半角英数字記号コードはフォント切り替えをしたほうがよい。
apt install *.ttcフォントから取り出した *.ttfは、表示されなかった。
[troff-dformat.png]
データ構造印刷 AWK スクリプト arnoldrobbins/dformat は https://github.com/arnoldrobbins/dformat
から、git cloneするかプログラムをもらってくるかする。
解凍すると、dformat.awk, dformat の2つのAWKスクリプトが入っている。どちらかを使用する。

$ awk -f dformat < 構造定義テキスト > 構造定義.pic

----構造定義テキスト---
.begin dformat
style bitwid 0.09
Short
   0 S
   1-15 Integer
Int
   0 S
   1-31 Integer
Float
   0 S
   1-7 Exponent
   8-31 Fraction
.end
 ---
$ pic 構造定義.pic | eqn | troff  -ms | dpost > 構造定義.ps
  eqn は,領域名称の右下小文字表示のために使用する。
$ evince 構造定義.ps
[troff-pic3.png]
==========================
PIC boxの塗りつぶしの修正。
==========================
Boxの塗りつぶしが三角形にしかならないのでソースプログラムを修正した。

heirloom-doctools/pic/pltroff.c の関数 void box(double x0, double y0, double x1, double y1)
...
void box(double x0, double y0, double x1, double y1)
{
	move(x0, y0);
	//cont(x0, y1);
	//cont(x1, y1);
	//cont(x1, y0);
	//cont(x0, y0);
	cont(x1, y0);
	cont(x1, y1);
	cont(x0, y1);
	cont(x0, y0);
}
...
2024-04-17 「固有値計算比較テスト」
参照:UNIXワークステーションによる科学技術計算ハンドブック 戸川隼人著 サイエンス社 1992

   FORTRAN数値計算とプログラミング 国井利泰監修 中村明子、伊藤文子著 1971 共立出版
      1.5 固有値 A.ヤコビ法 EX-1-5-A p-91 ~ 100

   行列計算ソフトウェア 小国力編著 村田、三好、ドンガラ、長谷川著 丸善 1991,2000 プログラムFD付き
     固有値計算と特異値計算 日本計算工学会編 長谷川,今村,山田,櫻井,荻田,相島,木村,中村著 丸善 2019
       プログラムがダウンロード可。ヤコビ方式プログラムはV1.0、行列計算ソフトウェア(2000)のFDにあるものは
    V2.0(サブルーチンの最後に検算が追加されている)となっている。
    手順はThe Jacobi Method for Real Symmetric Matrices(H.Rutishauser)
      となっている。下記のJohn Burkardt氏のものと同様である。
    PYTHONに変換してやってみると検算で精度がわるい。John Burkardt氏と比べると判定値3箇所ほど違う
    ところがある。John Burkardt氏のように変更するとよくなる。

     https://people.sc.fsu.edu/~jburkardt/py_src/jacobi_eigenvalue/jacobi_eigenvalue.html
     John Burkardt
     テストする場合は、ここからjacobi_eigenvalue.pyをダウンロードすること。
         people.math.sc.edu/Burkardt/py_src/jacobi_eigenvalue/jacobi_eigenvalue.htmlのもある
     が更新日が古い、ライセンスがGPLとなっている。
     新しいほうは、ライセンスがMIT。

   http://ics.p.lodz.pl/~dpuchala/JacobiNewI.pdf
     Handbook Series Linear Algebra/The Jacobi Method for Real Symmetric Matrices
        H.Rutishauser

   https://stackoverflow.com/questions/10806790/generating-symmetric-matrices-in-numpy
     Generating Symmetric Matrices in Numpy

UNIXワークステーションによる科学技術計算ハンドブックのJAC7.CをPYTHONに変換したもの。
FORTRAN数値計算とプログラミングのFORTRANをPYTHONにしたもの。
J.Burkardt氏のものをそのまま使用。numpy.linalg.eig()を比べてみた。
ヤコビ法は、対称行列のみが計算対称なので対称行列のみを計算する。

$ python test-all.py
◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎
◎◎◎◎◎◎◎◎◎◎◎計算開始◎◎◎◎◎◎◎◎◎◎
◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎
No.1 計算行列 4 x 4
[[ 21.2   51.5   17.8   21.4 ]
 [ 51.5   39.    56.05 -39.1 ]
 [ 17.8   56.05   9.   -44.75]
 [ 21.4  -39.1  -44.75  -4.1 ]]

■■■■■■■■■ 計算結果 No.1 ■■■■(科学技術計算ハンドブック)■■■■■
固有値
 [-40.00264901575932, 125.7493950044248, -58.50030558547468, 37.85355959680922]
固有ベクタ
 [[ 0.21250619  0.36561209 -0.50821882  0.75025498]
 [-0.58893811  0.69993445  0.39337504  0.09219412]
 [ 0.75911892  0.51787123  0.28012443 -0.27762954]
 [ 0.17813335 -0.3289817   0.71309186  0.5929077 ]]
  ■■■ 検証1 ■■■
[2.78043825e-14 4.81913530e-14 2.79740955e-14 1.57448258e-14]
  ■■■ 検証2 ■■■
[[ 0.00000000e+00 -7.10542736e-15  1.77635684e-14 -3.55271368e-15]
 [-2.13162821e-14  4.26325641e-14  3.55271368e-15  5.77315973e-15]
 [-1.77635684e-14  0.00000000e+00  0.00000000e+00  0.00000000e+00]
 [ 1.77635684e-15  2.13162821e-14 -2.13162821e-14 -1.42108547e-14]]

■■■■■■■■■ 計算結果 No.1 ■■■■(FORTRAN数値計算とプログラミング)■■■■■
固有値
 [-55.792972180451464, -9.031737456399028, 64.02302580941523, 65.90168382743529]
固有ベクタ
 [[ 0.62693309  0.38438309  0.59707089 -0.32048539]
 [-0.74411862  0.24834997  0.34473792 -0.51552453]
 [ 0.11869282 -0.85858514  0.17804532 -0.4658792 ]
 [-0.19787469 -0.23109194  0.70211251  0.64380132]]
  ■■■ 検証1 ■■■
[39.42200601 39.964956   58.72369839 66.5872806 ]
  ■■■ 検証2 ■■■
[[  7.82554737   4.18240917  10.38003546  -6.73857808]
 [-23.86052837  -7.36359255   4.64960558 -53.92168093]
 [-14.00308674  15.62161728 -11.26570479 -36.90058768]
 [ 26.9711719   35.7973147  -56.49949274 -10.92046047]]

■■■■■■■■■ 計算結果 No.1 ■■■■(sc.fsu.edu/ j.burkardt)■■■■■
固有値
 [-58.50030558547471, -40.002649015759324, 37.85355959680921, 125.74939500442483]
固有ベクタ
 [[-0.50821882  0.21250619  0.75025498  0.36561209]
 [ 0.39337504 -0.58893811  0.09219412  0.69993445]
 [ 0.28012443  0.75911892 -0.27762954  0.51787123]
 [ 0.71309186  0.17813335  0.5929077  -0.3289817 ]]
  ■■■ 検証1 ■■■
[8.70233572e-15 1.47555281e-14 1.23149709e-14 2.92964275e-14]
  ■■■ 検証2 ■■■
[[-3.55271368e-15 -1.77635684e-15  0.00000000e+00  0.00000000e+00]
 [ 0.00000000e+00  0.00000000e+00  1.11022302e-14  0.00000000e+00]
 [ 3.55271368e-15  1.42108547e-14  5.32907052e-15 -2.84217094e-14]
 [ 7.10542736e-15 -3.55271368e-15  0.00000000e+00 -7.10542736e-15]]

■■■■■■■■■ 計算結果 No.1 ■■■■(PYTHON NUMPY linalg.eig)■■■■■
固有値
 [125.74939500442478, 37.85355959680924, -58.50030558547472, -40.00264901575932]
固有ベクタ
 [[-0.36561209 -0.75025498 -0.50821882  0.21250619]
 [-0.69993445 -0.09219412  0.39337504 -0.58893811]
 [-0.51787123  0.27762954  0.28012443  0.75911892]
 [ 0.3289817  -0.5929077   0.71309186  0.17813335]]
  ■■■ 検証1 ■■■
[7.78360569e-14 3.52261012e-14 4.57735138e-14 1.83962314e-14]
  ■■■ 検証2 ■■■
[[ 2.84217094e-14  2.48689958e-14 -3.55271368e-15 -1.77635684e-15]
 [-7.10542736e-14  2.04281037e-14 -3.55271368e-15  1.42108547e-14]
 [ 1.42108547e-14  1.77635684e-15 -3.55271368e-14  1.06581410e-14]
 [ 0.00000000e+00  1.42108547e-14  2.84217094e-14 -4.44089210e-15]]
◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎
◎◎◎◎◎◎◎◎◎◎◎計算開始◎◎◎◎◎◎◎◎◎◎
◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎
No.2 計算行列 4 x 4
[[-35.8  -61.45   6.5  -29.4 ]
 [-61.45  97.2   58.1   20.7 ]
 [  6.5   58.1   26.6  -66.9 ]
 [-29.4   20.7  -66.9   -7.9 ]]

■■■■■■■■■ 計算結果 No.2 ■■■■(科学技術計算ハンドブック)■■■■■
固有値
 [-67.07620293659039, 144.65559681297157, 78.70918808502054, -76.18858196140172]
固有ベクタ
 [[ 0.89518041 -0.27761022  0.32206096 -0.13364635]
 [ 0.29515964  0.86519733 -0.21676487 -0.34253082]
 [-0.00672204  0.41739515  0.64435728  0.6407338 ]
 [ 0.33389765 -0.01214253 -0.65885766  0.67399666]]
  ■■■ 検証1 ■■■
[5.41051503e-14 1.82022411e-14 2.51214793e-14 2.77475809e-14]
  ■■■ 検証2 ■■■
[[ 4.97379915e-14 -7.10542736e-15 -1.06581410e-14 -1.06581410e-14]
 [ 1.06581410e-14 -1.42108547e-14  1.77635684e-14 -2.13162821e-14]
 [-1.50435220e-14  7.10542736e-15 -1.42108547e-14 -1.42108547e-14]
 [ 1.06581410e-14 -5.32907052e-15  0.00000000e+00  0.00000000e+00]]

■■■■■■■■■ 計算結果 No.2 ■■■■(FORTRAN数値計算とプログラミング)■■■■■
固有値
 [-68.61745588275613, 67.46200861910354, -1.1203217022646799, 82.37576896591735]
固有ベクタ
 [[ 0.90198654 -0.42919041  0.02345202  0.04081524]
 [ 0.34596093  0.68635341  0.26675139 -0.58144108]
 [-0.23780854 -0.49630771  0.73918869 -0.38823425]
 [ 0.10088817  0.31367698  0.61797555  0.71381689]]
  ■■■ 検証1 ■■■
[11.37656598 57.89211363 99.13680835 81.48374029]
  ■■■ 検証2 ■■■
[[  3.82973654 -10.30545643 -30.5689359    7.39644255]
 [ -9.78900249  24.44215811  80.52491271 -18.90791372]
 [ -3.42970011  36.38253546  -5.20132185 -59.6167138 ]
 [  2.67805134  36.38937221 -48.80913453 -51.70329586]]

■■■■■■■■■ 計算結果 No.2 ■■■■(sc.fsu.edu/ j.burkardt)■■■■■
固有値
 [-76.18858196140172, -67.07620293659033, 78.7091880850205, 144.65559681297154]
固有ベクタ
 [[-0.13364635  0.89518041  0.32206096 -0.27761022]
 [-0.34253082  0.29515964 -0.21676487  0.86519733]
 [ 0.6407338  -0.00672204  0.64435728  0.41739515]
 [ 0.67399666  0.33389765 -0.65885766 -0.01214253]]
  ■■■ 検証1 ■■■
[2.16831986e-14 1.21801131e-14 3.25611587e-14 4.28010775e-14]
  ■■■ 検証2 ■■■
[[ 1.24344979e-14 -7.10542736e-15  1.42108547e-14 -7.10542736e-15]
 [-1.06581410e-14  0.00000000e+00  0.00000000e+00  2.84217094e-14]
 [-1.42108547e-14  6.88338275e-15  7.10542736e-15 -2.84217094e-14]
 [ 0.00000000e+00  7.10542736e-15 -2.84217094e-14 -1.28785871e-14]]

■■■■■■■■■ 計算結果 No.2 ■■■■(PYTHON NUMPY linalg.eig)■■■■■
固有値
 [144.65559681297142, 78.70918808502046, -67.07620293659025, -76.18858196140174]
固有ベクタ
 [[-0.27761022  0.32206096  0.89518041 -0.13364635]
 [ 0.86519733 -0.21676487  0.29515964 -0.34253082]
 [ 0.41739515  0.64435728 -0.00672204  0.6407338 ]
 [-0.01214253 -0.65885766  0.33389765  0.67399666]]
  ■■■ 検証1 ■■■
[1.42978968e-13 7.58652039e-14 1.10133467e-13 3.46731022e-14]
  ■■■ 検証2 ■■■
[[ 1.42108547e-14  3.55271368e-14 -9.23705556e-14  5.32907052e-15]
 [ 1.27897692e-13 -2.84217094e-14 -5.32907052e-14  1.77635684e-14]
 [ 5.68434189e-14  5.68434189e-14 -2.53685961e-14  2.84217094e-14]
 [ 2.55351296e-14 -2.13162821e-14 -1.06581410e-14 -7.10542736e-15]]

[test-all.tgz 2.8kb]

2024-04-10  「行列 dot()計算」
配列の内積計算。

---- mydot.py ------
def dim(a):
    if not type(a) == list:
        return []
    return [len(a)] + dim(a[0])

def isnotnum(n):
    return (not isinstance(n, int) and not isinstance(n, float) and not isinstance(n, complex))

def mydot(a,b):
  '''  Dot()
         in: a, b : matrix (list)
        out: matrix (list)
                                    1
                                +-------+
                  n * m  ==>  1 | n * m |
                                +-------+

                 b_col            b_col
                +-----+         +-------+
         n * bl |  B  |  ==> bl | n * B |
                +-----+         +-------+

             a_col                a_col
           +------+             +-------+
        al | A    | * n  ==> al | A * n |
           +------+             +-------+

       a_col            b_col           b_col
      +------+         +-----+         +-----+
   al | A    |   *  bl |  B  |  ==> al | ans |
      +------+         +-----+         +-----+
       IF a_col != bl THEN ERROR
      
      (A[0][0-n]  *  B[0-n][0])合計  ==> ans[0][0]
      (A[0][0-n]  *  B[0-n][1])合計  ==> ans[0][1]
      (A[0][0-n]  *  B[0-n][n])合計  ==> ans[0][n]

      (A[1][0-n]  *  B[0-n][0])合計  ==> ans[1][0]
      (A[1][0-n]  *  B[0-n][1])合計  ==> ans[1][1]
      (A[1][0-n]  *  B[0-n][n])合計  ==> ans[1][n]

      (A[n][0-n]  *  B[0-n][0])合計  ==> ans[n][0]
      (A[n][0-n]  *  B[0-n][n])合計  ==> ans[n][n]
  '''
  alc = dim(a)
  blc = dim(b)
  rr = []
  if len(alc) < 0 or len(alc) > 2:
    return rr
  if len(alc) == 1:
    alc[0:0] = [1]
    a = [a]
  if len(blc) < 0 or len(blc) > 2:
    return rr
  if len(blc) == 1:
    blc[0:0] = [1]
    b = [b]
  if len(alc) == 0:
    if isnotnum(a):
      return rr
    if len(blc) == 0:
      if isnotnum(b):
        return []
      return [[a*b]]
    rr = [el.copy() for el in b]
    for i in range(blc[0]):
      for j in range(blc[1]):
        if isnotnum(rr[i][j]):
          return []
        rr[i][j] = a * rr[i][j]
    return rr
  if len(blc) == 0:
    if isnotnum(b):
      return []
    rr = [el.copy() for el in a]
    for i in range(alc[0]):
      for j in range(alc[1]):
        if isnotnum(rr[i][j]):
          return []
        rr[i][j] = b * rr[i][j]
    return rr

  if alc[1] != blc[0]:  # if a columns != b lines then error
    return rr
  for i in range(alc[0]): # 0 ~ (alines - 1)
    wc = [0 for j in range(blc[1])] # b columns as ans line 
    ae = a[i]
    
    for j in range(blc[1]):
        be = [e[j] for e in b]  # b.T
        for k in range(len(be)):
            if isnotnum(a[i][k]):
              return []
            if isnotnum(be[k]):
              return []
            wc[j] += (a[i][k] * be[k])
    rr.append(wc)
  return rr

if ( __name__ == '__main__' ):
  a = [[1,2],[3,4]]
  b = [[10,20],[30,40]]
  print("a=",a)
  print("b=",b)
  print(mydot(a,b))
  
  a = [1,2,3]
  b = [[100,200,300],[400,500,600],[700,800,900]]
  print("a=",a)
  print("b=",b)
  print(mydot(a,b))
  b = 3
  a = [[100,200,300],[400,500,600],[700,800,900]]
  print("a=",a)
  print("b=",b)
  print(mydot(a,b))
  a = 0.5
  b = [[100,200,300],[400,500,600],[700,800,900]]
  print("a=",a)
  print("b=",b)
  print(mydot(a,b))
  a = 3
  b = 20
  print("a=",a)
  print("b=",b)
  print(mydot(a,b))
  a = [3]
  b = [20]
  print("a=",a)
  print("b=",b)
  print(mydot(a,b))
  a = [[3]]
  b = [[20]]
  print("a=",a)
  print("b=",b)
  print(mydot(a,b))
---
$ python mydot.py
...
a= [[1, 2], [3, 4]]
b= [[10, 20], [30, 40]]
[[70, 100], [150, 220]]
a= [1, 2, 3]
b= [[100, 200, 300], [400, 500, 600], [700, 800, 900]]
[[3000, 3600, 4200]]
a= [[100, 200, 300], [400, 500, 600], [700, 800, 900]]
b= 3
[[300, 600, 900], [1200, 1500, 1800], [2100, 2400, 2700]]
a= 0.5
b= [[100, 200, 300], [400, 500, 600], [700, 800, 900]]
[[50.0, 100.0, 150.0], [200.0, 250.0, 300.0], [350.0, 400.0, 450.0]]
a= 3
b= 20
[[60]]
a= [3]
b= [20]
[[60]]
a= [[3]]
b= [[20]]
[[60]]

2024-04-10  「行列 四則演算」
行列の四則演算。
掛算は単純な掛算。dot(),@ とは違う。

>>> import numpy as np
>>> a = np.array([[1,2],[3,4]])
>>> b = np.array([[10,20],[30,40]])
>>> a+b
array([[11, 22],
       [33, 44]])
>>> a-b
array([[ -9, -18],
       [-27, -36]])
>>> a*b
array([[ 10,  40],
       [ 90, 160]])
>>> a/b
array([[0.1, 0.1],
       [0.1, 0.1]])
>>> np.dot(a,b)
array([[ 70, 100],
       [150, 220]])
>>> a@b
array([[ 70, 100],
       [150, 220]])

---- mycalc_matrix.py -----
def dim(a):
    if not type(a) == list:
        return []
    return [len(a)] + dim(a[0])

def isnotnum(n):
    return (not isinstance(n, int) and not isinstance(n, float) and not isinstance(n, complex))

def mycalc(func, x,y):
  if func == "+":
    return x + y
  elif func == "-":
    return x - y
  elif func == "*":
    return x * y
  elif func == "/":
    if y == 0:
      return None
    else:
      return x / y
  else:
    return None

def mycalc_matrix(func, a,b):
  '''  mycalc_matrix()
         in: a, b : matrix (list), numeric 
        out: matrix (list)

       a_col    {+}     b_col         {a_col} or {b_col}
      +------+  {-}    +-----+     {al}+-----+
   al | A    |  {*} bl |  B  |  ==> or | ans |
      +------+  {/}    +-----+     {bl}+-----+
       IF al == a_col == 1 THEN OK
       IF bl == b_col == 1 THEN OK
       IF al == 1 and a_col == b_col THEN OK
       IF bl == 1 and a_col == b_col THEN OK
       IF a_col == 1 and al == bl THEN OK
       IF b_col == 1 and al == bl THEN OK
       IF a_col == b_col and al == bl THEN OK
      
  '''
  alc = dim(a)
  blc = dim(b)
  rr = []
  if len(alc) < 0 or len(alc) > 2:
    return rr
  if len(alc) == 0:
    alc = [1,1]
    a = [[a]]
  if len(alc) == 1:
    alc[0:0] = [1]
    a = [a]
  if len(blc) < 0 or len(blc) > 2:
    return rr
  if len(blc) == 0:
    blc = [1,1]
    b = [[b]]
  if len(blc) == 1:
    blc[0:0] = [1]
    b = [b]
  if mycalc(func,1,1) == None: # chack func
    return rr
  for i in range(alc[0]):
    for j in range(alc[1]):
      if isnotnum(a[i][j]):
        return []
  for i in range(blc[0]):
    for j in range(blc[1]):
      if isnotnum(b[i][j]):
        return []

  if alc[0] == alc[1] == 1:
    rr = [el.copy() for el in b]
    for i in range(blc[0]):
      for j in range(blc[1]):
        rr[i][j] = mycalc(func,a[0][0],rr[i][j])

  elif blc[0] == blc[1] == 1:
    rr = [el.copy() for el in a]
    for i in range(alc[0]):
      for j in range(alc[1]):
        rr[i][j] = mycalc(func,rr[i][j],b[0][0])

  elif alc[0] == 1 and alc[1] == blc[1]:
    rr = [[mycalc(func,a[0][j],el[j]) for j in range(blc[1])] for el in b]

  elif blc[0] == 1 and alc[1] == blc[1]:
    rr = [[mycalc(func,el[j],b[0][j]) for j in range(alc[1])] for el in a]

  elif alc[1] == 1 and alc[0] == blc[0]:
    for i in range(alc[0]):
      rr.append([mycalc(func,a[i][0],b[i][j]) for j in range(blc[1])])

  elif blc[1] == 1 and alc[0] == blc[0]:
    for i in range(alc[0]):
      rr.append([mycalc(func,a[i][j],b[i][0]) for j in range(alc[1])])

  elif alc[1] == blc[1] and alc[0] == blc[0]:
    for i in range(alc[0]):
      rr.append([mycalc(func,a[i][j],b[i][j]) for j in range(alc[1])])
  # else Error
  return rr

if ( __name__ == '__main__' ):
 
  a = [[1,2,3],[4,5,6],[7,8,9]]
  b = [[100,200,300],[400,500,600],[700,800,900]]
  print("a=",a)
  print("b=",b)
  print("add", mycalc_matrix("+",a,b))
  print("sub", mycalc_matrix("-",a,b))
  print("mul", mycalc_matrix("*",a,b))
  print("div", mycalc_matrix("/",b,a))
  a = 1000
  print("a=",a)
  print("b=",b)
  print("add", mycalc_matrix("+",a,b))
  print("sub", mycalc_matrix("-",a,b))
  print("mul", mycalc_matrix("*",a,b))
  print("div", mycalc_matrix("/",a,b))
  b = [[1,2,3],[4,5,6],[7,8,9]]
  a = [[100,200,300]]
  print("a=",a)
  print("b=",b)
  print("add", mycalc_matrix("+",a,b))
  print("sub", mycalc_matrix("-",a,b))
  print("mul", mycalc_matrix("*",a,b))
  print("div", mycalc_matrix("/",a,b))
  b = [[1,2,3],[4,5,6],[7,8,9]]
  a = [[100],[400],[700]]
  print("a=",a)
  print("b=",b)
  print("add", mycalc_matrix("+",a,b))
  print("sub", mycalc_matrix("-",a,b))
  print("mul", mycalc_matrix("*",a,b))
  print("div", mycalc_matrix("/",a,b))
  b = 2
  a = [[100],[400],[700]]
  print("a=",a)
  print("b=",b)
  print("add", mycalc_matrix("+",a,b))
  print("sub", mycalc_matrix("-",a,b))
  print("mul", mycalc_matrix("*",a,b))
  print("div", mycalc_matrix("/",a,b))
-----
$ python mycalc_matrix.py
..
a= [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
b= [[100, 200, 300], [400, 500, 600], [700, 800, 900]]
add [[101, 202, 303], [404, 505, 606], [707, 808, 909]]
sub [[-99, -198, -297], [-396, -495, -594], [-693, -792, -891]]
mul [[100, 400, 900], [1600, 2500, 3600], [4900, 6400, 8100]]
div [[100.0, 100.0, 100.0], [100.0, 100.0, 100.0], [100.0, 100.0, 100.0]]
a= 1000
b= [[100, 200, 300], [400, 500, 600], [700, 800, 900]]
add [[1100, 1200, 1300], [1400, 1500, 1600], [1700, 1800, 1900]]
sub [[900, 800, 700], [600, 500, 400], [300, 200, 100]]
mul [[100000, 200000, 300000], [400000, 500000, 600000], [700000, 800000, 900000]]
div [[10.0, 5.0, 3.3333333333333335], [2.5, 2.0, 1.6666666666666667], [1.4285714285714286, 1.25, 1.1111111111111112]]
a= [[100, 200, 300]]
b= [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
add [[101, 202, 303], [104, 205, 306], [107, 208, 309]]
sub [[99, 198, 297], [96, 195, 294], [93, 192, 291]]
mul [[100, 400, 900], [400, 1000, 1800], [700, 1600, 2700]]
div [[100.0, 100.0, 100.0], [25.0, 40.0, 50.0], [14.285714285714286, 25.0, 33.333333333333336]]
a= [[100], [400], [700]]
b= [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
add [[101, 102, 103], [404, 405, 406], [707, 708, 709]]
sub [[99, 98, 97], [396, 395, 394], [693, 692, 691]]
mul [[100, 200, 300], [1600, 2000, 2400], [4900, 5600, 6300]]
div [[100.0, 50.0, 33.333333333333336], [100.0, 80.0, 66.66666666666667], [100.0, 87.5, 77.77777777777777]]
a= [[100], [400], [700]]
b= 2
add [[102], [402], [702]]
sub [[98], [398], [698]]
mul [[200], [800], [1400]]
div [[50.0], [200.0], [350.0]]

2024-04-07 「非対称行列固有値計算」
計算対称行列に合わない固有値計算関数の使い方でどうなるかをやってみた。

$ python lib_jacob.py
■■■■■■■■■ 入力 ■■■■■■■■■
MATRIX: [[1, 7, 3], [2, 9, 12], [5, 22, 7]]
対称行列ではありません。
■■■■■■■ ヤコビ法計算 ■■■■■■■
 EPS= 2.220446049250313e-16
 KOUT= 9
 AMAX=   0.000000000000000
 固有値: [[-4.784566014866619, 0.0, -1.1036075382276867e-29], [0.0, -0.41221518263870705, 1.726327615835052e-18], [-1.1036075382276867e-29, 1.726327615835052e-18, 22.196781197505327]]
 固有ベクタ: [[0.7992781967609033, 0.5119293149747735, 0.31477411051752296], [-0.5684930090684294, 0.47424576916171074, 0.6722400234087083], [0.19485908452766953, -0.7162536749655646, 0.6700825398974086]]
■■■■■■■■■ 計算結果 ■■■■■■■■■
 LAMDA(1)= -4.7845660148666189215305167
 LAMDA(2)= -0.4122151826387070450152805
 LAMDA(3)=  22.1967811975053272988134268
 X(0)=   0.799278196760903    0.511929314974773    0.314774110517523 
 X(1)=  -0.568493009068429    0.474245769161711    0.672240023408708 
 X(2)=   0.194859084527670   -0.716253674965565    0.670082539897409 
計算行列= [[ 1  7  3]
 [ 2  9 12]
 [ 5 22  7]]
固有値= [[-4.78456601  0.          0.        ]
 [ 0.         -0.41221518  0.        ]
 [ 0.          0.         22.1967812 ]]
固有ベクタ= [[ 0.7992782   0.51192931  0.31477411]
 [-0.56849301  0.47424577  0.67224002]
 [ 0.19485908 -0.71625367  0.67008254]]
  ■■■ 検証方法1 ■■■
[7.43850938 8.50221312 6.18347139]
  ■■■ 検証方法2 ■■■
検算 dot(計算行列 , 固有ベクトルの1列)ー(固有値1*固有ベクトルの1列)
[ 1.22860368 -3.899564   -6.21412547]
検算 dot(計算行列 , 固有ベクトルの2列)ー(固有値2*固有ベクトルの2列)
[ 1.89391371 -3.10748224  7.68402713]
検算 dot(計算行列 , 固有ベクトルの3列)ー(固有値3*固有ベクトルの3列)
[ 0.04372984 -0.2008658   6.18005332]
  ■■■ 検証方法3 ■■■
[[ 1.22860368  1.89391371  0.04372984]
 [-3.899564   -3.10748224 -0.2008658 ]
 [-6.21412547  7.68402713  6.18005332]]
. . .
■■■■■■ numpy.linalg.eig()計算 ■■■■■■
■■■■■■■■■ 計算結果 ■■■■■■■■■
 LAMDA(1)=  25.5548386342907107859900862
 LAMDA(2)= -0.5789337929080543565518724
 LAMDA(3)= -7.9759048413826647561108985
 X(0)=  -0.260976503318146   -0.973445274559594    0.189104107807029 
 X(1)=  -0.587027077498621    0.228061283850043   -0.581572782101413 
 X(2)=  -0.766348794609388   -0.019807782467165    0.791209665973142 
計算行列= [[ 1  7  3]
 [ 2  9 12]
 [ 5 22  7]]
固有値= [[25.55483863  0.          0.        ]
 [ 0.         -0.57893379  0.        ]
 [ 0.          0.         -7.97590484]]
固有ベクタ= [[-0.2609765  -0.97344527  0.18910411]
 [-0.58702708  0.22806128 -0.58157278]
 [-0.76634879 -0.01980778  0.79120967]]
  ■■■ 検証方法1 ■■■
[1.28094913e-14 2.21849431e-15 3.55964581e-15]
  ■■■ 検証方法2 ■■■
検算 dot(計算行列 , 固有ベクトルの1列)ー(固有値1*固有ベクトルの1列)
[ 0.00000000e+00 -7.10542736e-15 -1.06581410e-14]
検算 dot(計算行列 , 固有ベクトルの2列)ー(固有値2*固有ベクトルの2列)
[ 1.55431223e-15  1.58206781e-15 -5.37764278e-17]
検算 dot(計算行列 , 固有ベクトルの3列)ー(固有値3*固有ベクトルの3列)
[-3.33066907e-15  8.88178420e-16 -8.88178420e-16]
  ■■■ 検証方法3 ■■■
[[ 0.00000000e+00  1.55431223e-15 -3.33066907e-15]
 [-7.10542736e-15  1.58206781e-15  8.88178420e-16]
 [-1.06581410e-14 -5.37764278e-17 -8.88178420e-16]]

---- lib_jacob.py ----
"""
 固有値 ヤコビ法計算

"""
import sys
import math
import numpy as np

def chk_symmetric(mat, n):
  for i in range(n):
    for j in range(n):
      if mat[i][j] != mat[j][i]:
        return 0
  return 1

def calc_jacob(mat,n,eps,cmax):
  '''
  ヤコビ法で計算

  入力引数:計算マトリクス(実対象行列)、次数、収束値、計算回数

  戻り値:固有値・マトリクス、固有ベクトル・マトリクス、計算回数、収束値

  参照:FORTRAN数値計算とプログラミング
       国井利泰監修 中村明子、伊藤文子著 1971 共立出版
      1.5 固有値 A.ヤコビ法 EX-1-5-A p-91 ~ 100
    より、Fortranの手順をPythonに修正したもの。
  '''
  u = [[ 0.0 for i in range(n)] for j in range(n)]
  for i in range(n):
    u[i][i] = 1.0
  n1 = n-1
  kout = 0
  while True:
    amax = 0.0
    for i in range(n1):
      i1 = i+1
      for j in range(i1,n):
        w = math.fabs(mat[i][j])
        if amax < w:
          amax = w
          k=i
          l=j

    if eps >= amax:
      break
    if kout >= cmax:
      break

    kout = kout + 1
    a1 = mat[k][k]
    a2 = mat[l][l]
    a3 = mat[k][l]
    w = (a1-a2) * 0.5
    if w < 0.0:
      af = a3
    else:
      af = -1.0 * a3

    if w == 0.0:
      z = math.sqrt(4.0*math.pow(a3,2))
      t = 2.0*af / z
    else:
      w = af/w
      t = w/(math.sqrt(w*w+1.0)+1.0)

    zz = t*t+1.0
    c = math.sqrt(1.0/zz)
    s = t * c
    for i in range(n):
      aw = u[i][k]
      az = u[i][l]
      u[i][k] = aw*c + az*s
      u[i][l] = -aw*s + az*c
      if i ==k:
        continue
      if i == l:
        continue
      aw = mat[i][k]
      az = mat[i][l]
      mat[i][k] = aw*c + az*s
      mat[i][l] = -aw*s + az*c
      mat[k][i] = mat[i][k]
      mat[l][i] = mat[i][l]

    asc2 = 2.0 * a3 * s * c
    mat[k][k] = a1 * math.pow(c,2) + a2 * math.pow(s,2) + asc2
    mat[l][l] = a1 * math.pow(s,2) + a2 * math.pow(c,2) - asc2
    mat[k][l] = 0.0
    mat[l][k] = 0.0
  return [mat, u, kout, amax]

def input_matrix():
  '''
  計算終了判定値:実数  
  マトリックスの入力
    次数n:1〜10
    マトリクスデータ:N*N実数対称行列

  戻り値:計算終了判定値・実数、次数n、計算対称行列N*N
  '''
  while True:
    inn = None
    try:
      inn = input("収束判定値は")
      eps = float(inn)
      break
    except:
      if inn == None:
        return [0.0,0,None]
      continue
  while True:
    inn = None
    try:
      inn = input("行列入力:実対象行列n x n の次数:整数n:")
      n = int(inn)
      if 0 < n <= 10:
        print ("n:",n," eps:",eps)
        break
    except:
      if inn == None:
        return [0.0,0,None]
      continue

  mat = [[ 0.0 for i in range(n)] for j in range(n)]

  print("行列入力:実数 x n個[ENTER] n回")
  for i in range(n):
    for j in range(n):
      while True:
        inn = None 
        try:
          print("%d x %d 番目の実数入力:" % (i+1,j+1), end='')
          inn = input("")
          mat[i][j] = float(inn)
          break
        except:
          if inn == None:
            return [0.0,0,None]
          continue
  return [eps, n, mat]

def matrix():
  eps = 2.2204460492503131E-016
  n = 3
  mat = [
[1, 7, 3],
[2, 9, 12],
[5, 22, 7]]
  return [eps,n,mat]

def matrix2():
  eps = 2.2204460492503131E-016
  n = 3
  mat = [
[1, -1, -1],
[-1, 1, -1],
[-1, -1, 1]]
  return [eps,n,mat]

def matrix3():
  eps = 2.2204460492503131E-016
  n = 4
  mat = [
[89, 75, 22, 102],
[75, 116, 27, 120],
[22,27, 33, 62],
[102,120,62,200]]
  return [eps,n,mat]

def eig_check(A, value, vector):
    r = np.zeros(value.shape[0])
    i = 0
    for l, v in zip(value, vector.T):
        r[i] = np.linalg.norm(A.dot(v) - l*v)
        i += 1
    return r

def result(A, evalue, evect):
  print("■■■■■■■■■ 計算結果 ■■■■■■■■■")
  n = len(A)
  for i in range(n):
    print(" LAMDA(%d)= % 20.25f" % (i+1, evalue[i][i]))
  for i in range(n):
    print(" X(%d)=" % (i), end='')
    for j in range(n):
      print("% 20.15f " % (evect[i][j]), end='')
    print("")
  print("計算行列=",A)
  print("固有値=",evalue)
  print("固有ベクタ=",evect)
  print("  ■■■ 検証方法1 ■■■")
  print(eig_check(A, np.array([evalue[i][i] for i in range(n)]), evect))
  print("  ■■■ 検証方法2 ■■■")
  for i in range(n):
    print("検算 dot(計算行列 , 固有ベクトルの%d列)ー(固有値%d*固有ベクトルの%d列)" % (i+1,i+1,i+1) )
    print(np.dot(A,evect[:,i])-evalue[i][i]*evect[:,i])
  print("  ■■■ 検証方法3 ■■■")
  print(np.dot(A,evect)-np.dot(evect,evalue))

if ( __name__ == '__main__' ):
  import warnings
  warnings.filterwarnings('ignore')

  m_max = 50
  eps,n,mat = matrix()
  if n > 0:
    print("■■■■■■■■■ 入力 ■■■■■■■■■")
    print("MATRIX:",mat)
    if chk_symmetric(mat, n) == 0:
      print("対称行列ではありません。")
      # sys.exit()
    np_inmatrix = np.array([e.copy() for e in mat]) # copy matrix
    print("■■■■■■■ ヤコビ法計算 ■■■■■■■")
    egvalue, egvect, kout, amax = calc_jacob(mat,n,eps,m_max)
    print(" EPS=",eps)
    print(" KOUT=",kout)
    print(" AMAX=% 20.15f" % (amax))
    print(" 固有値:",egvalue)
    print(" 固有ベクタ:",egvect)
    np_vector = np.array(egvect)
    for i in range(n):
      v = egvalue[i][i]
      egvalue[i] = [0.0 for j in range(n)]
      egvalue[i][i] = v
    np_evalue = np.array(egvalue)
    result(np_inmatrix, np_evalue, np_vector)
    print(". . .")
    print("■■■■■■ numpy.linalg.eig()計算 ■■■■■■")
    egvalue, egvect = np.linalg.eig(np_inmatrix)
    np_value = np.array([[0.0 for j in range(n)] for j in range(n)])
    for i in range(n):
      np_value[i][i] = egvalue[i]
    result(np_inmatrix, np_value, egvect)

  print("")
---
2024-04-05 「行列 固有値計算検算」
★Mathematica

参照:https://mathematica.stackexchange.com/questions/268772/check-eigenvalues-and-eigenvectors-are-correct
   Check Eigenvalues and Eigenvectors are correct [closed]

    https://ss1.xrea.com/penguinitis.g1.xrea.com/computer/programming/Python/eigenvalue.html
    行列の固有値の計算                  (検証方法あり )

    https://jp.mathworks.com/help/matlab/ref/eig.html
    eig 固有値と固有ベクトル

In[42]:= 
mat={{1.0,-1.0,-1.0},{-1.0,1.0,-1.0},{-1.0,-1.0,1.0}}
Out[42]= {{1.,-1.,-1.},{-1.,1.,-1.},{-1.,-1.,1.}}
In[43]:= 
{e,v}=Eigensystem[mat]
Out[43]= {{2.,2.,-0.999999999999999},
         {{-0.408248290463863,-0.408248290463863,0.816496580927726},
          {0.707106781186548,-0.707106781186548,0.},
          {-0.577350269189626,-0.577350269189626,-0.577350269189626}}}
In[44]:= 
mat.v[[1]]==e[[1]] v[[1]]
Out[44]= True
In[45]:= 
mat.v[[2]]==e[[2]] v[[2]]
Out[45]= False
In[46]:= 
mat.v[[3]]==e[[3]] v[[3]]
Out[46]= True
In[47]:= 
mat.v[[1]]-(e[[1]] v[[1]])
Out[47]= {-3.33066907387547*10^-16,-3.33066907387547*10^-16,-4.44089209850063*10^-16}
In[49]:= 
mat.v[[2]]-(e[[2]] v[[2]])
Out[49]= {0.,-2.22044604925031*10^-16,-1.11022302462516*10^-16}
In[50]:= 
mat.v[[3]]-(e[[3]] v[[3]])
Out[50]= {6.66133814775094*10^-16,1.33226762955019*10^-15,3.33066907387547*10^-16}

★OCTAVE
>> a = [1 -1 -1; -1 1 -1; -1 -1 1];
>> [v,e] = eig(a)
v =

   0.577350  -0.396780  -0.713605
   0.577350   0.816390   0.013181
   0.577350  -0.419610   0.700424

e =

Diagonal Matrix

  -1   0   0
   0   2   0
   0   0   2

>> a*v(:,1) <<== 計算行列値 * 固有値ベクトルの1列目
ans =
  -0.5774
  -0.5774
  -0.5774

>> e(1,1)*v(:,1)  <<== 固有値1番目 * 固有値ベクトルの1列目
ans =
  -0.5774
  -0.5774
  -0.5774

>> a*v(:,1) - e(1,1)*v(:,1) 
ans = <<== 検算(計算行列値 * 固有ベクトルの1列目)ー(固有値1番目 * 固有ベクトルの1列目)
  -1.1102e-16
  -1.1102e-16
   5.5511e-16

>> a*v(:,2) - e(2,2)*v(:,2)
ans = <<== 検算(計算行列値 * 固有ベクトルの2列目)ー(固有値2番目 * 固有ベクトルの2列目)
   1.1102e-16
   1.1102e-15
   1.1102e-16

>> a*v(:,3) - e(3,3)*v(:,3)
ans = <<== 検算(計算行列値 * 固有ベクトルの3列目)ー(固有値3番目 * 固有ベクトルの3列目)
            0
   9.7145e-17
            0

★PYTHON

---- mydot.py --------
import numpy as np

def mydot(A,val):
  vd = np.array([0.0 for i in range(len(val))])
  for i in range(len(A)):
    for x,y in zip(A[i],val):
      vd[i] += x*y
  return vd

mat=np.array([[1,-1,-1],[-1,1,-1],[-1,-1,1]])
print("計算行列\n",mat)
e,v=np.linalg.eig(mat)
print("e=",e)
print("v=",v)
print("検算 dot(計算行列,固有ベクトルの1列)ー(固有値1*固有ベクトルの1列)")
print(mydot(mat,v[:,0])-e[0]*v[:,0])
print("検算 dot(計算行列,固有ベクトルの2列)ー(固有値2*固有ベクトルの2列)")
print(mydot(mat,v[:,1])-e[1]*v[:,1])
print("検算 dot(計算行列,固有ベクトルの3列)ー(固有値3*固有ベクトルの3列)")
print(mydot(mat,v[:,2])-e[2]*v[:,2])
print("")
print((mat.dot(v[:,0]))-e[0]*v[:,0])
print((mat.dot(v[:,1]))-e[1]*v[:,1])
print((mat.dot(v[:,2]))-e[2]*v[:,2])
---

$ python mydot.py
...
計算行列
 [[ 1 -1 -1]
 [-1  1 -1]
 [-1 -1  1]]
e= [-1.  2.  2.]
v= [[-0.57735027 -0.57842803  0.57891179]
 [-0.57735027 -0.20985087 -0.78809991]
 [-0.57735027  0.7882789   0.20918812]]
検算 dot(計算行列,固有ベクトルの1列)ー(固有値1*固有ベクトルの1列)
[ 5.55111512e-16 -1.11022302e-16 -1.11022302e-16]
検算 dot(計算行列,固有ベクトルの2列)ー(固有値2*固有ベクトルの2列)
[ 0.00000000e+00 -5.55111512e-17  0.00000000e+00]
検算 dot(計算行列,固有ベクトルの3列)ー(固有値3*固有ベクトルの3列)
[ 2.22044605e-16 -4.44089210e-16  5.55111512e-17]

[ 5.55111512e-16 -1.11022302e-16 -1.11022302e-16]
[ 0.00000000e+00 -5.55111512e-17  0.00000000e+00]
[ 2.22044605e-16 -4.44089210e-16  5.55111512e-17]
...
>>> import numpy as np
>>> a = np.array([[1,-1,-1],[-1,1,-1],[-1,-1,1]])
>>> d,v = np.linalg.eig(a)
>>> d
array([-1.,  2.,  2.])
>>> v
array([[-0.57735027, -0.57842803,  0.57891179],
       [-0.57735027, -0.20985087, -0.78809991],
       [-0.57735027,  0.7882789 ,  0.20918812]])
>>> dd = np.array([[d[0],0,0],[0,d[1],0],[0,0,d[2]]])
>>> dd
array([[-1.,  0.,  0.],
       [ 0.,  2.,  0.],
       [ 0.,  0.,  2.]])
>>> np.dot(a,v)
array([[ 0.57735027, -1.15685606,  1.15782358],
       [ 0.57735027, -0.41970174, -1.57619982],
       [ 0.57735027,  1.5765578 ,  0.41837624]])
>>> np.dot(v,dd)
array([[ 0.57735027, -1.15685606,  1.15782358],
       [ 0.57735027, -0.41970174, -1.57619982],
       [ 0.57735027,  1.5765578 ,  0.41837624]])
>>> np.dot(a,v)-np.dot(v,dd)
array([[ 5.55111512e-16,  0.00000000e+00,  2.22044605e-16],
       [-1.11022302e-16, -5.55111512e-17, -4.44089210e-16],
       [-1.11022302e-16,  0.00000000e+00,  5.55111512e-17]])

2024-03-31 「行列 固有値計算」
参照:東京大学のデータサイエンティスト育成講座
   Pythonで手を動かして学ぶデータ分析 塚本邦尊、山田典一、大澤文孝 著 マイナビ出版2022
      Chapter 2-3 Scipyの基礎 p-45,46

固有値 -1, 2, 2  固有ベクトル 0.577, -0.816, 0.428
                            0.577,  0.408, -0.816
                            0.577,  0.408, 0.389
SCIPYの固有値、固有ベクトル 計算をしたとき違う値が表示されたのが気になり調べてみた。
とりあえずは他のプログラム

---python-----
>>> import numpy as np
>>> mat = np.array([[1,-1,-1],[-1,1,-1],[-1,-1,1]])
>>> mat
array([[ 1, -1, -1],
       [-1,  1, -1],
       [-1, -1,  1]])
>>> evalue,evector = np.linalg.eig(mat)
>>> evalue
array([-1.,  2.,  2.])
>>> evector
array([[-0.57735027, -0.57842803,  0.57891179],
       [-0.57735027, -0.20985087, -0.78809991],
       [-0.57735027,  0.7882789 ,  0.20918812]])
>>> import scipy
>>> evalue,evector = scipy.linalg.eig(mat)
>>> evalue
array([-1.+0.j,  2.+0.j,  2.+0.j])
>>> evector
array([[-0.57735027, -0.57842803,  0.57891179],
       [-0.57735027, -0.20985087, -0.78809991],
       [-0.57735027,  0.7882789 ,  0.20918812]])

lapackのdgeevの結果と同様になる。
LAPACK/BLAS入門より
https://github.com/tkouya/lapack_blas_tutorial

dpkg -l liblapack-dev
dpkg -l libblas-dev
  arm64  version 3.11.0-2

$ ./lapack_dgeev
A = 
  0:          1         -1         -1 
  1:         -1          1         -1 
  2:         -1         -1          1 
A(org) = 
  0:          1         -1         -1 
  1:         -1          1         -1 
  2:         -1         -1          1 
実数 実数 実数 
Eigenvalues = 
  0: (        -1,          0)
  1: (         2,          0)
  2: (         2,          0)

(-0.57735,     0) (-0.578428,     0) (0.578912,     0) 
(-0.57735,     0) (-0.209851,     0) (-0.7881,     0) 
(-0.57735,     0) (0.788279,     0) (0.209188,     0) 
||A * right_ev - lambda * right_ev||_F / ||A||_F =   2.55056138285437054e-16
||A^T * left_ev - lambda * left_ev||_F / ||A||_F =   4.84641987789776181e-16
.......
lapack_dgeev.cは修正して使わしてもらいました。
... lapack_dgeev.c ....
;;
	//printf("Dim = "); scanf("%d", &dim);
        dim = 3;
;;
  ↓	/*
	for(i = 0; i < dim; i++)
	{
		for(j = 0; j < dim; j++)
		{
			// A = Lotkin matrix
			//if(i == 0) ma[j] = 1.0;
			//else ma[i * dim + j] = 1.0 / (double)(i + j + 1);
コメント			// A = Random matrix
			ma[i * dim + j] = (double)rand() / (double)RAND_MAX;
		
			// ma_org = ma
			ma_org[i * dim + j] = ma[i * dim + j] + 0.0 * I;
		}
	}
  ↑	*/
	
	ma_org[0 * dim + 0] = (ma[0 * dim + 0] = 1.0) + 0.0 * I;
	ma_org[0 * dim + 1] = (ma[0 * dim + 1] = -1.0) + 0.0 * I;
	ma_org[0 * dim + 2] = (ma[0 * dim + 2] = -1.0) + 0.0 * I;
	ma_org[1 * dim + 0] = (ma[1 * dim + 0] = -1.0) + 0.0 * I;
	ma_org[1 * dim + 1] = (ma[1 * dim + 1] = 1.0) + 0.0 * I;
	ma_org[1 * dim + 2] = (ma[1 * dim + 2] = -1.0) + 0.0 * I;
	ma_org[2 * dim + 0] = (ma[2 * dim + 0] = -1.0) + 0.0 * I;
	ma_org[2 * dim + 1] = (ma[2 * dim + 1] = -1.0) + 0.0 * I;
	ma_org[2 * dim + 2] = (ma[2 * dim + 2] = 1.0) + 0.0 * I;
;;
 maの表示。	
;;
		// 固有値が実数の時
		if(im_eig[i] == 0.0)
		{
			printf("実数 ");
			for(j = 0; j < dim; j++)
;;
		// 固有値が複素数になる場合
		else if(im_eig[i] > 0.0)
		{
			printf("複素数 ");
			for(j = 0; j < dim; j++)
;;
		else
		{
			printf("その他 ");
			for(j = 0; j < dim; j++)
;;
....
他のプログラムも同様。


$ ./lapack_ssyev
INPUT: A = 
  0:          1         -1         -1 
  1:         -1          1         -1 
  2:         -1         -1          1 
OUTPUT: A = 
  0: -0.57735 -0.750394 -0.321832 
  1: -0.57735 0.0964827 0.810776 
  2: -0.57735 0.653911 -0.488944 
Eigenvalues = 
  0:         -1
  1:          2
  2:          2

absmax_eig =   2.0000000e+00
absmin_eig =  -1.0000000e+00
cond2      =   2.0000000e+00
||ev^T * A * ev - lambda * I||_2 =   1.5325554e-07


$ ./lapack_dsyev
A = 
  0:          1         -1         -1 
  1:         -1          1         -1 
  2:         -1         -1          1 
Envenvectors: 
  0: 0.57735 -0.39678 -0.713605 
  1: 0.57735 0.81639 0.0131811 
  2: 0.57735 -0.41961 0.700424 
Eigenvalues = 
  0:         -1
  1:          2
  2:          2

absmax_eig =   2.00000000000000000e+00
absmin_eig =  -1.00000000000000022e+00
cond2      =   1.99999999999999956e+00
||ev^T * A * ev - lambda||_F / ||A||_F  =   3.5090480e-16

・・・・・・
---- mathematica -----------------------
In[1]:= mat={{1.0,-1.0,-1.0},{-1.0,1.0,-1.0},{-1.0,-1.0,1.0}}
Out[1]= {{1.,-1.,-1.},{-1.,1.,-1.},{-1.,-1.,1.}}
In[2]:= MatrixForm[%]
Out[2]//MatrixForm= (1.	-1.	-1.
-1.	1.	-1.
-1.	-1.	1.
)
In[3]:= Eigenvalues[mat]
Out[3]= {2.,2.,-1.}
In[4]:= Eigenvectors[mat]
Out[4]= {{-0.408248290463863,-0.408248290463863,0.816496580927726},
{0.707106781186548,-0.707106781186548,0.},
{-0.577350269189626,-0.577350269189626,-0.577350269189626}}
In[5]:= Eigensystem[mat]
Out[5]= {{2.,2.,-0.999999999999999},
{{-0.408248290463863,-0.408248290463863,0.816496580927726},
{0.707106781186548,-0.707106781186548,0.},
{-0.577350269189626,-0.577350269189626,-0.577350269189626}}}

---SCILAB-------------
--> a = [ 1 -1 -1; -1 1 -1; -1 -1 1]
 a  = 

   1.  -1.  -1.
  -1.   1.  -1.
  -1.  -1.   1.

--> [t2, aa2] = spec(a)
 t2  = 

   0.5773503  -0.3967799  -0.7136052
   0.5773503   0.8163902   0.0131811
   0.5773503  -0.4196102   0.7004241
 aa2  = 

  -1.   0.   0.
   0.   2.   0.
   0.   0.   2.

--> A=[1,-1,-1;-1,1,-1;-1,-1,1]
 A  = 

   1.  -1.  -1.
  -1.   1.  -1.
  -1.  -1.   1.

--> [V,E]=bdiag(A)
 V  = 

  -1.   0.   0.
   0.   2.   0.
   0.   0.   2.
 E  = 

   0.5773503   0.4896217   0.6010959
   0.5773503   0.3210539  -0.7850266
   0.5773503  -0.8106756   0.1839307

----OCTAVE--------------------------
>> a = [1 -1 -1; -1 1 -1; -1 -1 1];
>> [v,d] = eig(a)
v =

   0.577350  -0.396780  -0.713605
   0.577350   0.816390   0.013181
   0.577350  -0.419610   0.700424

d =

Diagonal Matrix

  -1   0   0
   0   2   0
   0   0   2

-----JULIA-----------
julia> using LinearAlgebra

julia> A = [1 -1 -1;-1 1 -1; -1 -1 1]
3×3 Matrix{Int64}:
  1  -1  -1
 -1   1  -1
 -1  -1   1

julia> eigvecs(A)
3×3 Matrix{Float64}:
 -0.57735   0.707107  -0.408248
 -0.57735  -0.707107  -0.408248
 -0.57735   0.0        0.816497

julia> eigvals(A)
3-element Vector{Float64}:
 -1.0000000000000002
  2.0
  2.0

他にも、手元にあったプログラムの手順でやってみた。

! 参照:FORTRAN数値計算とプログラミング
!       国井利泰監修 中村明子、伊藤文子著 1971 共立出版
!     1.5 固有値 A.ヤコビ法 EX-1-5-A p-91 ~ 100
FORTRANのプログラムでそれをfortran90に修正している。
gfortran でコンパイルした。
...
 行列入力:実対象行列n x n の次数:整数n
3
 実対象行列 N x N、 収束判定値EPS, 計算繰り返し回数Max Loop
 N= 3, EPS:0.22204460492503E-15 ,Max Loop= 50
 行列入力:実数 x n個[ENTER] n回
1 -1 -1
-1 1 -1           
-1 -1 1
 ◇◇◇◇◇ 入力結果 ◇◇◇◇◇
 A( 1)=      1.0000     -1.0000     -1.0000 
 A( 2)=     -1.0000      1.0000     -1.0000 
 A( 3)=     -1.0000     -1.0000      1.0000 
 ・・・・・
 U( 1)=      1.0000      0.0000      0.0000 
 U( 2)=      0.0000      1.0000      0.0000 
 U( 3)=      0.0000      0.0000      1.0000 
 ◆◆◆◆◆ 計算結果 ◆◆◆◆◆◆
 LAMDA( 1)= -0.9999999961338617
 LAMDA( 2)=  1.9999999754758784
 LAMDA( 3)=  1.9999999994888948
 X( 1)=    0.5773502689056838   -0.8158338288228492   -0.0328909540699514 
 X( 2)=    0.5773502623183976    0.4364013294067319   -0.6900873411458593 
 X( 3)=    0.5773502588272095    0.3794325175124923    0.7229783123361159 
 KOUT=   5
 AMAX=   0.000000000000000
...
となった。
結果を計算しないと正しいかどうかわからないというのが最近わかった。
2024-03-23 「RaspiでVisual Studio Codeデバッグ」
Visual Studio Code でデバッグ。

参照:https://code.visualstudio.com/docs/cpp/config-linux
     Using C++ on Linux in VS Code

(1) mkdir ソースプログラムディレクトリ

(2) プログラム作成
   $ cd ソースプログラムディレクトリ
   $ nano sin.c
   ---
   #include <stdio.h>
   #include <math.h>

   int main(int argc, char *argv[])
   {
    double n = 999.0;
    if ( argc <= 1 ) {
        printf("ラジアンを指定して?\n");
        return 1;
    }
    sscanf(argv[1],"%lf",&n);
    if ( fabs(n) > 2.0 ) {
        printf("2ラジアンまで?\n");
        return 1;
    }
    printf("結果: sin(%lf) = %lf\n",n, sin(n));
    return 0;
   }
   ---

(3) Visual Studio Codeインストール
  $ sudo apt install code

(4) Visual Studio Code 起動
   メニュー・ファイル・フォルダを開く 選択
  "ソースプログラムディレクトリ"を開く
   プログラム sin.c を開く。

(5) task.json自動作成
  メニュー・ターミナル・規定のビルドタスクの構成 選択
  選択リストのなかの"GCCアクティブなファイルのビルド"を選択する。
  task.jsonが自動生成されて表示される。
  cソースを選択して、
  メニュー・実行・デバッグの実行 を選んで実行する。
  エラーが出て終わる。
  ディレクトリ ".vscode" 作成され、tasks.jsonができる。

(6) tasks.json修正
   ---
  {
	"version": "2.0.0",
	"tasks": [
	  {
	    "type": "cppbuild",
	    "label": "C/C++: gcc アクティブなファイルのビルド",
	    "command": "/usr/bin/gcc",
	    "args": [
		"-fdiagnostics-color=always",
		"-g",
		"${file}",
		"-o",
	        "${fileDirname}/${fileBasenameNoExtension}", # <<== ”,”追加
		"-lm"        # <<== リンクオブジェクト指定
	    ],
	    "options": {
		"cwd": "${fileDirname}"
	    },
	    "problemMatcher": [
		"$gcc"
	    ],
	    "group": {
		"kind": "build",
		"isDefault": true
	    },
	    "detail": "コンパイラ: /usr/bin/gcc"
	  }
	]
  }
   ---
   修正したら、保存する。

(7) プログラムのデバッグ
  codeのメニュー・実行・デバッグの実行 => 最初のメニューを選んで実行する。
  デバッグができるようになる。
  このままでは、codeのメニュー・実行・デバッグなしの実行 でもデバッグとなってしまう。

(8) launch.json作成
  codeのメニュー・実行・構成の追加 選択。
  launch.jsonの編集ウィンドウになる。
  「構成の追加」(青色ボタン)でGDB起動を選ぶ。
  ---
   {
    // IntelliSense を使用して利用可能な属性を学べます。
    // 既存の属性の説明をホバーして表示します。
    // 詳細情報は次を確認してください: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "name": "(gdb) 起動",
            "type": "cppdbg",
            "request": "launch",

            //"program": "プログラム名を入力してください (例: ${workspaceFolder}/a.out)",

            "program": "${fileDirname}/${fileBasenameNoExtension}",
            // プログラム名を入力してくださいを↑のように修正する。
            "args": [],
            "stopAtEntry": false,
            "cwd": "${fileDirname}",
            "environment": [],
            "externalConsole": false,
            "MIMode": "gdb",
            "setupCommands": [
                {
                    "description": "gdb の再フォーマットを有効にする",
                    "text": "-enable-pretty-printing",
                    "ignoreFailures": true
                },
                {
                    "description": "逆アセンブリ フレーバーを Intel に設定",
                    "text": "-gdb-set disassembly-flavor intel",
                    "ignoreFailures": true
                }
            ]
        }

    ]
   }
   ---
   修正したら、保存。
  保存しなくてプログラムデバッグ・実行しても以前の状態で実行される。ここで保存される。
  もう一度デバッグ・実行すると反映されている結果となる。
  jsonファイルの修正はどちらも同じなので修正したら保存する。

(9) プログラムのデバッグなしで実行
  codeのメニュー・実行・デバッグなしで実行、選択。
  デバッグなしで実行される。

(10) プログラムに引数がある場合は、launch.jsonを修正する。
  ---
    ;; 途中の
            "name": "(gdb) 起動",
            "type": "cppdbg",
            "request": "launch",
            "program": "${fileDirname}/${fileBasenameNoExtension}",
            "args": ["0.5"],     <<== コマンド > プログラム名 引数(これを指定)
            "stopAtEntry": false,
            "cwd": "${fileDirname}",
            "environment": [],
   ;;
   ---
  修正したら、保存。

(11) ソースプログラムの修正
  ソースプログラムを修正する。

(12) コンパイル
  codeのメニュー・ターミナル・ビルドタスクの実行 選択
  エラーの確認。修正。
2024-03-21 「juliaインストール、実行」
参照:https://www.jstage.jst.go.jp/article/itej/71/1/71_74/_pdf
   動的プログラミング言語Juliaの紹介

(1)ダウンロード
https://julialang.org/downloads/

Current stable release: v1.10.2 (March 1, 2024)
Generic Linux on ARM [help]	AArch64 (GPG)

julia-1.10.2-linux-aarch64.tar.gz

(2)インストール
ダウンロードし、解凍。

(3)実行

$ cd julia-1.10.2/bin
$ ./julia

☆JULIAからPython呼び出し。
・・・
julia> using Pkg

julia> Pkg.add("PyCall")
      メッセージがでる。1回設定せればよい。

julia> using PyCall

julia> @pyimport numpy as np

julia> @pyimport scipy.linalg as linalg

julia> mat = np.array([[1,-1,-1],[-1,1,-1],[-1,-1,1]])
3×3 Matrix{Int64}:
  1  -1  -1
 -1   1  -1
 -1  -1   1

julia> evalue,evector = linalg.eig(mat)
(ComplexF64[-0.9999999999999999 + 0.0im, 2.0 + 0.0im, 1.9999999999999996 + 0.0im],
 [-0.5773502691896256 -0.5784280301128795 0.5789117904251897;
  -0.5773502691896258 -0.20985087099025507 -0.7880999106986186;
  -0.5773502691896258 0.7882789011031346 0.209188120273429])

  ここまでPYTHONパッケージ。
 以下、JULIAパッケージ。

julia> using LinearAlgebra

julia> A = [1 -1 -1;-1 1 -1; -1 -1 1]
3×3 Matrix{Int64}:
  1  -1  -1
 -1   1  -1
 -1  -1   1

julia> eigvecs(A)
3×3 Matrix{Float64}:
 -0.57735   0.707107  -0.408248
 -0.57735  -0.707107  -0.408248
 -0.57735   0.0        0.816497

julia> eigvals(A)
3-element Vector{Float64}:
 -1.0000000000000002
  2.0
  2.0

----
☆ユーザ作成PYTHONプログラム呼び出し
・・・
julia> using PyCall
julia> scriptdir = @__DIR__
  カレントディレクトリ、または、
julia> scriptdir = "/home/xxxxxx/xxx/sample"

julia> pushfirst!(PyVector(pyimport("sys")."path"), scriptdir)

julia> mytest = pyimport("sample")

julia> led24 = mytest.init_led(4)

julia> mytest.buzz(led24,600,2)

julia> mytest.led_close(led24)

-----sample.py-----------------
from gpiozero import LED
import time

def init_led(p):
    ''' p : pi number '''
    return LED(p)

def led(led,s):
    ''' LED ON/OFF
        led : pyobject led, s : 0 - off / 1 - ON '''
    if s == 0:
       led.off()
    else:
       led.on()

def led_close(led):
    ''' led object close 
          led " pyobject led '''
    led.close()

def buzz(led,hz,t):
    ''' LED PWM 50% Output
         led : pyobject led, hz : frequency 0-1200 , t : time (sec [float]) '''
    if hz <= 0:
        led.on()
    else:
        if hz > 1200:
            hz = 1200;
        onoff = 0.5 / hz
        led.blink(onoff, onoff) # バックグラウンドでblinkは継続しない
    time.sleep(t)
    led.off()

if __name__ == '__main__':
   ld4 = init_led(4)
   buzz(ld4,400,1)
   led_close(ld4)
...

☆bash 呼び出し。
・・・
julia> ”;”文字入力で。
shell>     に変わる。bashコマンド実行できる。
      戻るには、CTRL+C。
julia>   になる。

2024-03-20 「マシンイプシロン」
$ cc epsilon.c -o eps-c
$ ./eps-c
LONG epsilon: 1.92592994438723585305597794258e-34 
  1.0  epsilon: 2.22044604925031e-16 
  0.0  epsilon: 4.94065645841247e-324 
  0.005  epsilon: 4.33680868994202e-19 
  1000.0  epsilon: 1.13686837721616e-13 

$ cat epsilon.c
#include <stdio.h>

int main()
{
    long double  e,  se;
    double       le, sle;

    e = 1.0;
    le = 1.0;
    for (; 1.0 + (e /= 2.0L) != 1.0;) {
        se = e;
    }
    printf("LONG epsilon: %.30Lg \n",se);

    for (; 1.0 + (le /= 2.0) != 1.0; ) {
        sle = le;
    }
    printf("  1.0  epsilon: %.15g \n",sle);

    le = 1.0;
    for (; 0.0 + (le /= 2.0) != 0.0; ) {
        sle = le;
    }
    printf("  0.0  epsilon: %.15g \n",sle);
    le = 1.0;
    for (; 0.005 + (le /= 2.0) != 0.005; ) {
        sle = le;
    }
    printf("  0.005  epsilon: %.15g \n",sle);
    le = 1.0;
    for (; 1000.0 + (le /= 2.0) != 1000.0; ) {
        sle = le;
    }
    le = 1.0;
    printf("  1000.0  epsilon: %.15g \n",sle);

    return 0;
}
...

-----PYTHON---------------
>>> import numpy as np
>>> print(np.finfo(float).eps)
2.220446049250313e-16
>>> print(np.finfo(np.float32).eps)
1.1920929e-07
...

-------
参照:http://ri2t.kyushu-u.ac.jp/~watanabe/RESERCH/MANUSCRIPT/KOHO/CONVERGE/converge.pdf
   いつ反復計算をやめるべきか? - ∼収束判定基準の設定方法

$ gfortran epsilon.f90 -o epsilon
$ ./epsilon
     real(kind=4):   1.19209290E-07
     real(kind=8):   2.2204460492503131E-016
    real(kind=16):   1.92592994438723585305597794258492732E-0034
             real:   1.19209290E-07
 double precision:   2.2204460492503131E-016
----epsilon.f90-----------
program machine_epsilon
  implicit none
  real(kind=4)    :: x
  real(kind=8)    :: y
  real(kind=16)   :: z
  real    :: x1
  double precision :: y1
  
  print *,"    real(kind=4):", epsilon(x)
  print *,"    real(kind=8):", epsilon(y)
  print *,"   real(kind=16):", epsilon(z)
  print *,"            real:", epsilon(x1)
  print *,"double precision:", epsilon(y1)
end program machine_epsilon

◆◆◆julia◆◆◆
参照:https://julialang.org/downloads/
   Current stable release: v1.10.2 (March 1, 2024)
   Generic Linux on ARM [help]	AArch64 (GPG)
   julia-1.10.2-linux-aarch64.tar.gz

Linux 6.6.20+rpt-rpi-2712 #1 SMP PREEMPT Debian 1:6.6.20-1+rpt1 (2024-03-07) aarch64 GNU/Linux
...
ダウンロードし、解凍。
$ cd julia-1.10.2/bin
$ ./julia
....
julia> Sys.WORD_SIZE
64

julia> eps()
2.220446049250313e-16

julia> eps(Float32)
1.1920929f-7

julia> eps(Float64)
2.220446049250313e-16

julia> eps(0.0)
5.0e-324

julia> eps(1.0)
2.220446049250313e-16

julia> eps(1000.)
1.1368683772161603e-13

julia> eps(0.005)
8.673617379884035e-19

julia> eps(0.1)
1.3877787807814457e-17

2024-03-10 「IEEE754 丸め」
参考:
http://verifiedby.me/kv/kv-intro.pdf
精度保証付き数値計算と kv ライブラリ
柏木 雅英 著

https://catalog.lib.kyushu-u.ac.jp/opac_download_md/1470409/p063.pdf
IEEE754と数値計算 : 浮動小数点演算の特徴とは?
皆本晃弥 著

https://www.am.ics.keio.ac.jp/proj/asap/wiki/?plugin=attach&refer=Numerical%20Recipe%20in%20C&openfile=ukiwa08.pdf
浮動小数点輪講
よしみ まさと 著

インターフェース2024/4月号 数学100の0.1を100回足す結果をみてEXCELとLibreOffice Calcを比べて
結果が微妙に違っている。丸め方がちょっと違うかもしれない?
そんなのもあって、以前も丸めをやってはいたが、ちょっと考えが甘かったのでもう一度。
近接偶数丸めのテストはどうするんだろうかと考えてみた。
もう少しわかりやすく改修しました。

......仮数部 LSB 1、小数点以下なし...(+n) + (+x)...............
...............................................
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
 +)                                                                   1 0000 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0010 0000 0000 .0
        Binary Result(Add significant digits) =>xxxxx 11 1111 1111 0010 0000 0000 .0
.
     2305843009213690112
 +)                  256
 ------------------------------- この計算値は値の大小を確認するため。
     2305843009213690368
====================================================================================
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
 +)                                                                     1111 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0010 0000 0000 .0
        Binary Result(Add significant digits) =>xxxxx 11 1111 1111 0001 1111 0000 .0
.
     2305843009213690112
 +)                  240
 -------------------------------------------------
     2305843009213690368
====================================================================================
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
 +)                                                                     1110 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0010 0000 0000 .0
        Binary Result(Add significant digits) =>xxxxx 11 1111 1111 0001 1110 0000 .0
.
     2305843009213690112
 +)                  224
 -------------------------------------------------
     2305843009213690368
====================================================================================
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
 +)                                                                     1101 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0010 0000 0000 .0
        Binary Result(Add significant digits) =>xxxxx 11 1111 1111 0001 1101 0000 .0
.
     2305843009213690112
 +)                  208
 -------------------------------------------------
     2305843009213690368
====================================================================================
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
 +)                                                                     1100 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0010 0000 0000 .0
        Binary Result(Add significant digits) =>xxxxx 11 1111 1111 0001 1100 0000 .0
.
     2305843009213690112
 +)                  192
 -------------------------------------------------
     2305843009213690368
====================================================================================
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
 +)                                                                     1011 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0010 0000 0000 .0
        Binary Result(Add significant digits) =>xxxxx 11 1111 1111 0001 1011 0000 .0
.
     2305843009213690112
 +)                  176
 -------------------------------------------------
     2305843009213690368
====================================================================================
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
 +)                                                                     1010 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0010 0000 0000 .0
        Binary Result(Add significant digits) =>xxxxx 11 1111 1111 0001 1010 0000 .0
.
     2305843009213690112
 +)                  160
 -------------------------------------------------
     2305843009213690368
====================================================================================
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
 +)                                                                     1001 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0010 0000 0000 .0
        Binary Result(Add significant digits) =>xxxxx 11 1111 1111 0001 1001 0000 .0
.
     2305843009213690112
 +)                  144
 -------------------------------------------------
     2305843009213690368
====================================================================================
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
 +)                                                                     1000 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0010 0000 0000 .0
        Binary Result(Add significant digits) =>xxxxx 11 1111 1111 0001 1000 0000 .0
.
     2305843009213690112
 +)                  128
 -------------------------------------------------
     2305843009213690368
====================================================================================
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
 +)                                                                      111 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
        Binary Result(Add significant digits) =>xxxxx 11 1111 1111 0001 0111 0000 .0
.
     2305843009213690112
 +)                  112
 -------------------------------------------------
     2305843009213690112
====================================================================================
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
 +)                                                                      110 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
        Binary Result(Add significant digits) =>xxxxx 11 1111 1111 0001 0110 0000 .0
.
     2305843009213690112
 +)                   96
 -------------------------------------------------
     2305843009213690112
====================================================================================
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
 +)                                                                      101 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
        Binary Result(Add significant digits) =>xxxxx 11 1111 1111 0001 0101 0000 .0
.
     2305843009213690112
 +)                   80
 -------------------------------------------------
     2305843009213690112
====================================================================================
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
 +)                                                                      100 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
        Binary Result(Add significant digits) =>xxxxx 11 1111 1111 0001 0100 0000 .0
.
     2305843009213690112
 +)                   64
 -------------------------------------------------
     2305843009213690112
====================================================================================
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
 +)                                                                       11 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
        Binary Result(Add significant digits) =>xxxxx 11 1111 1111 0001 0011 0000 .0
.
     2305843009213690112
 +)                   48
 -------------------------------------------------
     2305843009213690112
====================================================================================
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
 +)                                                                       10 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
        Binary Result(Add significant digits) =>xxxxx 11 1111 1111 0001 0010 0000 .0
.
     2305843009213690112
 +)                   32
 -------------------------------------------------
     2305843009213690112
====================================================================================
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
 +)                                                                        1 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
        Binary Result(Add significant digits) =>xxxxx 11 1111 1111 0001 0001 0000 .0
.
     2305843009213690112
 +)                   16
 -------------------------------------------------
     2305843009213690112
====================================================================================
......仮数部 LSB 0、小数点以下なし...(+n) + (+x)...............
...............................................
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1110 0000 0000 .0
 +)                                                                   1 0000 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0000 0000 .0
        Binary Result(Add significant digits) =>xxxxx 11 1111 1111 1111 0000 0000 .0
.
     2305843009213693440
 +)                  256
 -------------------------------------------------
     2305843009213693696
====================================================================================
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1110 0000 0000 .0
 +)                                                                     1111 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0000 0000 .0
        Binary Result(Add significant digits) =>xxxxx 11 1111 1111 1110 1111 0000 .0
.
     2305843009213693440
 +)                  240
 -------------------------------------------------
     2305843009213693696
====================================================================================
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1110 0000 0000 .0
 +)                                                                     1110 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0000 0000 .0
        Binary Result(Add significant digits) =>xxxxx 11 1111 1111 1110 1110 0000 .0
.
     2305843009213693440
 +)                  224
 -------------------------------------------------
     2305843009213693696
====================================================================================
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1110 0000 0000 .0
 +)                                                                     1101 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0000 0000 .0
        Binary Result(Add significant digits) =>xxxxx 11 1111 1111 1110 1101 0000 .0
.
     2305843009213693440
 +)                  208
 -------------------------------------------------
     2305843009213693696
====================================================================================
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1110 0000 0000 .0
 +)                                                                     1100 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0000 0000 .0
        Binary Result(Add significant digits) =>xxxxx 11 1111 1111 1110 1100 0000 .0
.
     2305843009213693440
 +)                  192
 -------------------------------------------------
     2305843009213693696
====================================================================================
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1110 0000 0000 .0
 +)                                                                     1011 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0000 0000 .0
        Binary Result(Add significant digits) =>xxxxx 11 1111 1111 1110 1011 0000 .0
.
     2305843009213693440
 +)                  176
 -------------------------------------------------
     2305843009213693696
====================================================================================
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1110 0000 0000 .0
 +)                                                                     1010 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0000 0000 .0
        Binary Result(Add significant digits) =>xxxxx 11 1111 1111 1110 1010 0000 .0
.
     2305843009213693440
 +)                  160
 -------------------------------------------------
     2305843009213693696
====================================================================================
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1110 0000 0000 .0
 +)                                                                     1001 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0000 0000 .0
        Binary Result(Add significant digits) =>xxxxx 11 1111 1111 1110 1001 0000 .0
.
     2305843009213693440
 +)                  144
 -------------------------------------------------
     2305843009213693696
====================================================================================
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1110 0000 0000 .0
 +)                                                                     1000 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1110 0000 0000 .0
        Binary Result(Add significant digits) =>xxxxx 11 1111 1111 1110 1000 0000 .0
.
     2305843009213693440
 +)                  128
 -------------------------------------------------
     2305843009213693440
====================================================================================
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1110 0000 0000 .0
 +)                                                                      111 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1110 0000 0000 .0
        Binary Result(Add significant digits) =>xxxxx 11 1111 1111 1110 0111 0000 .0
.
     2305843009213693440
 +)                  112
 -------------------------------------------------
     2305843009213693440
====================================================================================
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1110 0000 0000 .0
 +)                                                                      110 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1110 0000 0000 .0
        Binary Result(Add significant digits) =>xxxxx 11 1111 1111 1110 0110 0000 .0
.
     2305843009213693440
 +)                   96
 -------------------------------------------------
     2305843009213693440
====================================================================================
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1110 0000 0000 .0
 +)                                                                      101 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1110 0000 0000 .0
        Binary Result(Add significant digits) =>xxxxx 11 1111 1111 1110 0101 0000 .0
.
     2305843009213693440
 +)                   80
 -------------------------------------------------
     2305843009213693440
====================================================================================
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1110 0000 0000 .0
 +)                                                                      100 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1110 0000 0000 .0
        Binary Result(Add significant digits) =>xxxxx 11 1111 1111 1110 0100 0000 .0
.
     2305843009213693440
 +)                   64
 -------------------------------------------------
     2305843009213693440
====================================================================================
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1110 0000 0000 .0
 +)                                                                       11 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1110 0000 0000 .0
        Binary Result(Add significant digits) =>xxxxx 11 1111 1111 1110 0011 0000 .0
.
     2305843009213693440
 +)                   48
 -------------------------------------------------
     2305843009213693440
====================================================================================
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1110 0000 0000 .0
 +)                                                                       10 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1110 0000 0000 .0
        Binary Result(Add significant digits) =>xxxxx 11 1111 1111 1110 0010 0000 .0
.
     2305843009213693440
 +)                   32
 -------------------------------------------------
     2305843009213693440
====================================================================================
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1110 0000 0000 .0
 +)                                                                        1 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1110 0000 0000 .0
        Binary Result(Add significant digits) =>xxxxx 11 1111 1111 1110 0001 0000 .0
.
     2305843009213693440
 +)                   16
 -------------------------------------------------
     2305843009213693440
====================================================================================
......仮数部 LSB 0、小数点以下なし...(-n) + (+x)...............
...............................................
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
 +)                                                                   1 0000 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0000 0000 0000 .0
        Binary Result(Subtract significant digits) => 11 1111 1111 0000 0000 0000 .0
.
    -2305843009213690112
 +)                  256
 -------------------------------------------------
    -2305843009213689856
====================================================================================
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
 +)                                                                     1111 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0000 0000 0000 .0
        Binary Result(Subtract significant digits) => 11 1111 1111 0000 0001 0000 .0
.
    -2305843009213690112
 +)                  240
 -------------------------------------------------
    -2305843009213689856
====================================================================================
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
 +)                                                                     1110 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0000 0000 0000 .0
        Binary Result(Subtract significant digits) => 11 1111 1111 0000 0010 0000 .0
.
    -2305843009213690112
 +)                  224
 -------------------------------------------------
    -2305843009213689856
====================================================================================
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
 +)                                                                     1101 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0000 0000 0000 .0
        Binary Result(Subtract significant digits) => 11 1111 1111 0000 0011 0000 .0
.
    -2305843009213690112
 +)                  208
 -------------------------------------------------
    -2305843009213689856
====================================================================================
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
 +)                                                                     1100 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0000 0000 0000 .0
        Binary Result(Subtract significant digits) => 11 1111 1111 0000 0100 0000 .0
.
    -2305843009213690112
 +)                  192
 -------------------------------------------------
    -2305843009213689856
====================================================================================
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
 +)                                                                     1011 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0000 0000 0000 .0
        Binary Result(Subtract significant digits) => 11 1111 1111 0000 0101 0000 .0
.
    -2305843009213690112
 +)                  176
 -------------------------------------------------
    -2305843009213689856
====================================================================================
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
 +)                                                                     1010 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0000 0000 0000 .0
        Binary Result(Subtract significant digits) => 11 1111 1111 0000 0110 0000 .0
.
    -2305843009213690112
 +)                  160
 -------------------------------------------------
    -2305843009213689856
====================================================================================
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
 +)                                                                     1001 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0000 0000 0000 .0
        Binary Result(Subtract significant digits) => 11 1111 1111 0000 0111 0000 .0
.
    -2305843009213690112
 +)                  144
 -------------------------------------------------
    -2305843009213689856
====================================================================================
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
 +)                                                                     1000 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0000 0000 0000 .0
        Binary Result(Subtract significant digits) => 11 1111 1111 0000 1000 0000 .0
.
    -2305843009213690112
 +)                  128
 -------------------------------------------------
    -2305843009213689856
====================================================================================
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
 +)                                                                      111 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
        Binary Result(Subtract significant digits) => 11 1111 1111 0000 1001 0000 .0
.
    -2305843009213690112
 +)                  112
 -------------------------------------------------
    -2305843009213690112
====================================================================================
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
 +)                                                                      110 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
        Binary Result(Subtract significant digits) => 11 1111 1111 0000 1010 0000 .0
.
    -2305843009213690112
 +)                   96
 -------------------------------------------------
    -2305843009213690112
====================================================================================
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
 +)                                                                      101 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
        Binary Result(Subtract significant digits) => 11 1111 1111 0000 1011 0000 .0
.
    -2305843009213690112
 +)                   80
 -------------------------------------------------
    -2305843009213690112
====================================================================================
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
 +)                                                                      100 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
        Binary Result(Subtract significant digits) => 11 1111 1111 0000 1100 0000 .0
.
    -2305843009213690112
 +)                   64
 -------------------------------------------------
    -2305843009213690112
====================================================================================
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
 +)                                                                       11 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
        Binary Result(Subtract significant digits) => 11 1111 1111 0000 1101 0000 .0
.
    -2305843009213690112
 +)                   48
 -------------------------------------------------
    -2305843009213690112
====================================================================================
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
 +)                                                                       10 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
        Binary Result(Subtract significant digits) => 11 1111 1111 0000 1110 0000 .0
.
    -2305843009213690112
 +)                   32
 -------------------------------------------------
    -2305843009213690112
====================================================================================
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
 +)                                                                        1 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
        Binary Result(Subtract significant digits) => 11 1111 1111 0000 1111 0000 .0
.
    -2305843009213690112
 +)                   16
 -------------------------------------------------
    -2305843009213690112
====================================================================================
......仮数部 LSB 1、小数点以下なし...(-n) + (+x)...............
...............................................
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1110 0000 0000 .0
 +)                                                                   1 0000 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1101 0000 0000 .0
        Binary Result(Subtract significant digits) => 11 1111 1111 1101 0000 0000 .0
.
    -2305843009213693440
 +)                  256
 -------------------------------------------------
    -2305843009213693184
====================================================================================
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1110 0000 0000 .0
 +)                                                                     1111 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1101 0000 0000 .0
        Binary Result(Subtract significant digits) => 11 1111 1111 1101 0001 0000 .0
.
    -2305843009213693440
 +)                  240
 -------------------------------------------------
    -2305843009213693184
====================================================================================
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1110 0000 0000 .0
 +)                                                                     1110 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1101 0000 0000 .0
        Binary Result(Subtract significant digits) => 11 1111 1111 1101 0010 0000 .0
.
    -2305843009213693440
 +)                  224
 -------------------------------------------------
    -2305843009213693184
====================================================================================
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1110 0000 0000 .0
 +)                                                                     1101 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1101 0000 0000 .0
        Binary Result(Subtract significant digits) => 11 1111 1111 1101 0011 0000 .0
.
    -2305843009213693440
 +)                  208
 -------------------------------------------------
    -2305843009213693184
====================================================================================
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1110 0000 0000 .0
 +)                                                                     1100 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1101 0000 0000 .0
        Binary Result(Subtract significant digits) => 11 1111 1111 1101 0100 0000 .0
.
    -2305843009213693440
 +)                  192
 -------------------------------------------------
    -2305843009213693184
====================================================================================
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1110 0000 0000 .0
 +)                                                                     1011 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1101 0000 0000 .0
        Binary Result(Subtract significant digits) => 11 1111 1111 1101 0101 0000 .0
.
    -2305843009213693440
 +)                  176
 -------------------------------------------------
    -2305843009213693184
====================================================================================
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1110 0000 0000 .0
 +)                                                                     1010 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1101 0000 0000 .0
        Binary Result(Subtract significant digits) => 11 1111 1111 1101 0110 0000 .0
.
    -2305843009213693440
 +)                  160
 -------------------------------------------------
    -2305843009213693184
====================================================================================
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1110 0000 0000 .0
 +)                                                                     1001 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1101 0000 0000 .0
        Binary Result(Subtract significant digits) => 11 1111 1111 1101 0111 0000 .0
.
    -2305843009213693440
 +)                  144
 -------------------------------------------------
    -2305843009213693184
====================================================================================
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1110 0000 0000 .0
 +)                                                                     1000 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1110 0000 0000 .0
        Binary Result(Subtract significant digits) => 11 1111 1111 1101 1000 0000 .0
.
    -2305843009213693440
 +)                  128
 -------------------------------------------------
    -2305843009213693440
====================================================================================
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1110 0000 0000 .0
 +)                                                                      111 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1110 0000 0000 .0
        Binary Result(Subtract significant digits) => 11 1111 1111 1101 1001 0000 .0
.
    -2305843009213693440
 +)                  112
 -------------------------------------------------
    -2305843009213693440
====================================================================================
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1110 0000 0000 .0
 +)                                                                      110 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1110 0000 0000 .0
        Binary Result(Subtract significant digits) => 11 1111 1111 1101 1010 0000 .0
.
    -2305843009213693440
 +)                   96
 -------------------------------------------------
    -2305843009213693440
====================================================================================
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1110 0000 0000 .0
 +)                                                                      101 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1110 0000 0000 .0
        Binary Result(Subtract significant digits) => 11 1111 1111 1101 1011 0000 .0
.
    -2305843009213693440
 +)                   80
 -------------------------------------------------
    -2305843009213693440
====================================================================================
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1110 0000 0000 .0
 +)                                                                      100 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1110 0000 0000 .0
        Binary Result(Subtract significant digits) => 11 1111 1111 1101 1100 0000 .0
.
    -2305843009213693440
 +)                   64
 -------------------------------------------------
    -2305843009213693440
====================================================================================
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1110 0000 0000 .0
 +)                                                                       11 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1110 0000 0000 .0
        Binary Result(Subtract significant digits) => 11 1111 1111 1101 1101 0000 .0
.
    -2305843009213693440
 +)                   48
 -------------------------------------------------
    -2305843009213693440
====================================================================================
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1110 0000 0000 .0
 +)                                                                       10 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1110 0000 0000 .0
        Binary Result(Subtract significant digits) => 11 1111 1111 1101 1110 0000 .0
.
    -2305843009213693440
 +)                   32
 -------------------------------------------------
    -2305843009213693440
====================================================================================
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1110 0000 0000 .0
 +)                                                                        1 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1110 0000 0000 .0
        Binary Result(Subtract significant digits) => 11 1111 1111 1101 1111 0000 .0
.
    -2305843009213693440
 +)                   16
 -------------------------------------------------
    -2305843009213693440
====================================================================================
......仮数部 LSB 0、小数点以下...(+n) + (+x)...............
...............................................
     0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0000 0000
 +)  0 .0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 1000 0000
 ------------------------------------------------------------------------LGRS-oooo
     0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1000 0000
        Binary Result(Add significant digits) =>xxxxx 111 1111 1111 1111 1000 0000
.
     0.99999999999999977795539507496869
 +)  0.00000000000000011102230246251565
 -------------------------------------------------
     0.99999999999999988897769753748435
====================================================================================
     0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0000 0000
 +)  0 .0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0111 1000
 ------------------------------------------------------------------------LGRS-oooo
     0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1000 0000
        Binary Result(Add significant digits) =>xxxxx 111 1111 1111 1111 0111 1000
.
     0.99999999999999977795539507496869
 +)  0.00000000000000010408340855860843
 -------------------------------------------------
     0.99999999999999988897769753748435
====================================================================================
     0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0000 0000
 +)  0 .0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0111 0000
 ------------------------------------------------------------------------LGRS-oooo
     0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1000 0000
        Binary Result(Add significant digits) =>xxxxx 111 1111 1111 1111 0111 0000
.
     0.99999999999999977795539507496869
 +)  0.00000000000000009714451465470120
 -------------------------------------------------
     0.99999999999999988897769753748435
====================================================================================
     0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0000 0000
 +)  0 .0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0110 1000
 ------------------------------------------------------------------------LGRS-oooo
     0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1000 0000
        Binary Result(Add significant digits) =>xxxxx 111 1111 1111 1111 0110 1000
.
     0.99999999999999977795539507496869
 +)  0.00000000000000009020562075079397
 -------------------------------------------------
     0.99999999999999988897769753748435
====================================================================================
     0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0000 0000
 +)  0 .0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0110 0000
 ------------------------------------------------------------------------LGRS-oooo
     0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1000 0000
        Binary Result(Add significant digits) =>xxxxx 111 1111 1111 1111 0110 0000
.
     0.99999999999999977795539507496869
 +)  0.00000000000000008326672684688674
 -------------------------------------------------
     0.99999999999999988897769753748435
====================================================================================
     0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0000 0000
 +)  0 .0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0101 1000
 ------------------------------------------------------------------------LGRS-oooo
     0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1000 0000
        Binary Result(Add significant digits) =>xxxxx 111 1111 1111 1111 0101 1000
.
     0.99999999999999977795539507496869
 +)  0.00000000000000007632783294297951
 -------------------------------------------------
     0.99999999999999988897769753748435
====================================================================================
     0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0000 0000
 +)  0 .0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0101 0000
 ------------------------------------------------------------------------LGRS-oooo
     0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1000 0000
        Binary Result(Add significant digits) =>xxxxx 111 1111 1111 1111 0101 0000
.
     0.99999999999999977795539507496869
 +)  0.00000000000000006938893903907228
 -------------------------------------------------
     0.99999999999999988897769753748435
====================================================================================
     0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0000 0000
 +)  0 .0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0100 1000
 ------------------------------------------------------------------------LGRS-oooo
     0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1000 0000
        Binary Result(Add significant digits) =>xxxxx 111 1111 1111 1111 0100 1000
.
     0.99999999999999977795539507496869
 +)  0.00000000000000006245004513516506
 -------------------------------------------------
     0.99999999999999988897769753748435
====================================================================================
     0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0000 0000
 +)  0 .0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0100 0000
 ------------------------------------------------------------------------LGRS-oooo
     0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0000 0000
        Binary Result(Add significant digits) =>xxxxx 111 1111 1111 1111 0100 0000
.
     0.99999999999999977795539507496869
 +)  0.00000000000000005551115123125783
 -------------------------------------------------
     0.99999999999999977795539507496869
====================================================================================
     0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0000 0000
 +)  0 .0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0011 1000
 ------------------------------------------------------------------------LGRS-oooo
     0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0000 0000
        Binary Result(Add significant digits) =>xxxxx 111 1111 1111 1111 0011 1000
.
     0.99999999999999977795539507496869
 +)  0.00000000000000004857225732735060
 -------------------------------------------------
     0.99999999999999977795539507496869
====================================================================================
     0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0000 0000
 +)  0 .0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0011 0000
 ------------------------------------------------------------------------LGRS-oooo
     0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0000 0000
        Binary Result(Add significant digits) =>xxxxx 111 1111 1111 1111 0011 0000
.
     0.99999999999999977795539507496869
 +)  0.00000000000000004163336342344337
 -------------------------------------------------
     0.99999999999999977795539507496869
====================================================================================
     0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0000 0000
 +)  0 .0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0010 1000
 ------------------------------------------------------------------------LGRS-oooo
     0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0000 0000
        Binary Result(Add significant digits) =>xxxxx 111 1111 1111 1111 0010 1000
.
     0.99999999999999977795539507496869
 +)  0.00000000000000003469446951953614
 -------------------------------------------------
     0.99999999999999977795539507496869
====================================================================================
     0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0000 0000
 +)  0 .0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0010 0000
 ------------------------------------------------------------------------LGRS-oooo
     0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0000 0000
        Binary Result(Add significant digits) =>xxxxx 111 1111 1111 1111 0010 0000
.
     0.99999999999999977795539507496869
 +)  0.00000000000000002775557561562891
 -------------------------------------------------
     0.99999999999999977795539507496869
====================================================================================
     0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0000 0000
 +)  0 .0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0001 1000
 ------------------------------------------------------------------------LGRS-oooo
     0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0000 0000
        Binary Result(Add significant digits) =>xxxxx 111 1111 1111 1111 0001 1000
.
     0.99999999999999977795539507496869
 +)  0.00000000000000002081668171172169
 -------------------------------------------------
     0.99999999999999977795539507496869
====================================================================================
     0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0000 0000
 +)  0 .0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0001 0000
 ------------------------------------------------------------------------LGRS-oooo
     0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0000 0000
        Binary Result(Add significant digits) =>xxxxx 111 1111 1111 1111 0001 0000
.
     0.99999999999999977795539507496869
 +)  0.00000000000000001387778780781446
 -------------------------------------------------
     0.99999999999999977795539507496869
====================================================================================
     0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0000 0000
 +)  0 .0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 1000
 ------------------------------------------------------------------------LGRS-oooo
     0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0000 0000
        Binary Result(Add significant digits) =>xxxxx 111 1111 1111 1111 0000 1000
.
     0.99999999999999977795539507496869
 +)  0.00000000000000000693889390390723
 -------------------------------------------------
     0.99999999999999977795539507496869
====================================================================================
......仮数部 LSB 1、小数点以下...(+n) + (+x)...............
...............................................
     0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1000 1000 0000
 +)  0 .0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 1000 0000
 ------------------------------------------------------------------------LGRS-oooo
     0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1001 0000 0000
        Binary Result(Add significant digits) =>xxxxx 111 1111 1111 1001 0000 0000
.
     0.99999999999999833466546306226519
 +)  0.00000000000000011102230246251565
 -------------------------------------------------
     0.99999999999999844568776552478084
====================================================================================
     0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1000 1000 0000
 +)  0 .0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0111 1000
 ------------------------------------------------------------------------LGRS-oooo
     0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1001 0000 0000
        Binary Result(Add significant digits) =>xxxxx 111 1111 1111 1000 1111 1000
.
     0.99999999999999833466546306226519
 +)  0.00000000000000010408340855860843
 -------------------------------------------------
     0.99999999999999844568776552478084
====================================================================================
     0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1000 1000 0000
 +)  0 .0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0111 0000
 ------------------------------------------------------------------------LGRS-oooo
     0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1001 0000 0000
        Binary Result(Add significant digits) =>xxxxx 111 1111 1111 1000 1111 0000
.
     0.99999999999999833466546306226519
 +)  0.00000000000000009714451465470120
 -------------------------------------------------
     0.99999999999999844568776552478084
====================================================================================
     0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1000 1000 0000
 +)  0 .0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0110 1000
 ------------------------------------------------------------------------LGRS-oooo
     0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1001 0000 0000
        Binary Result(Add significant digits) =>xxxxx 111 1111 1111 1000 1110 1000
.
     0.99999999999999833466546306226519
 +)  0.00000000000000009020562075079397
 -------------------------------------------------
     0.99999999999999844568776552478084
====================================================================================
     0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1000 1000 0000
 +)  0 .0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0110 0000
 ------------------------------------------------------------------------LGRS-oooo
     0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1001 0000 0000
        Binary Result(Add significant digits) =>xxxxx 111 1111 1111 1000 1110 0000
.
     0.99999999999999833466546306226519
 +)  0.00000000000000008326672684688674
 -------------------------------------------------
     0.99999999999999844568776552478084
====================================================================================
     0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1000 1000 0000
 +)  0 .0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0101 1000
 ------------------------------------------------------------------------LGRS-oooo
     0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1001 0000 0000
        Binary Result(Add significant digits) =>xxxxx 111 1111 1111 1000 1101 1000
.
     0.99999999999999833466546306226519
 +)  0.00000000000000007632783294297951
 -------------------------------------------------
     0.99999999999999844568776552478084
====================================================================================
     0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1000 1000 0000
 +)  0 .0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0101 0000
 ------------------------------------------------------------------------LGRS-oooo
     0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1001 0000 0000
        Binary Result(Add significant digits) =>xxxxx 111 1111 1111 1000 1101 0000
.
     0.99999999999999833466546306226519
 +)  0.00000000000000006938893903907228
 -------------------------------------------------
     0.99999999999999844568776552478084
====================================================================================
     0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1000 1000 0000
 +)  0 .0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0100 1000
 ------------------------------------------------------------------------LGRS-oooo
     0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1001 0000 0000
        Binary Result(Add significant digits) =>xxxxx 111 1111 1111 1000 1100 1000
.
     0.99999999999999833466546306226519
 +)  0.00000000000000006245004513516506
 -------------------------------------------------
     0.99999999999999844568776552478084
====================================================================================
     0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1000 1000 0000
 +)  0 .0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0100 0000
 ------------------------------------------------------------------------LGRS-oooo
     0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1001 0000 0000
        Binary Result(Add significant digits) =>xxxxx 111 1111 1111 1000 1100 0000
.
     0.99999999999999833466546306226519
 +)  0.00000000000000005551115123125783
 -------------------------------------------------
     0.99999999999999844568776552478084
====================================================================================
     0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1000 1000 0000
 +)  0 .0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0011 1000
 ------------------------------------------------------------------------LGRS-oooo
     0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1000 1000 0000
        Binary Result(Add significant digits) =>xxxxx 111 1111 1111 1000 1011 1000
.
     0.99999999999999833466546306226519
 +)  0.00000000000000004857225732735060
 -------------------------------------------------
     0.99999999999999833466546306226519
====================================================================================
     0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1000 1000 0000
 +)  0 .0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0011 0000
 ------------------------------------------------------------------------LGRS-oooo
     0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1000 1000 0000
        Binary Result(Add significant digits) =>xxxxx 111 1111 1111 1000 1011 0000
.
     0.99999999999999833466546306226519
 +)  0.00000000000000004163336342344337
 -------------------------------------------------
     0.99999999999999833466546306226519
====================================================================================
     0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1000 1000 0000
 +)  0 .0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0010 1000
 ------------------------------------------------------------------------LGRS-oooo
     0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1000 1000 0000
        Binary Result(Add significant digits) =>xxxxx 111 1111 1111 1000 1010 1000
.
     0.99999999999999833466546306226519
 +)  0.00000000000000003469446951953614
 -------------------------------------------------
     0.99999999999999833466546306226519
====================================================================================
     0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1000 1000 0000
 +)  0 .0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0010 0000
 ------------------------------------------------------------------------LGRS-oooo
     0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1000 1000 0000
        Binary Result(Add significant digits) =>xxxxx 111 1111 1111 1000 1010 0000
.
     0.99999999999999833466546306226519
 +)  0.00000000000000002775557561562891
 -------------------------------------------------
     0.99999999999999833466546306226519
====================================================================================
     0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1000 1000 0000
 +)  0 .0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0001 1000
 ------------------------------------------------------------------------LGRS-oooo
     0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1000 1000 0000
        Binary Result(Add significant digits) =>xxxxx 111 1111 1111 1000 1001 1000
.
     0.99999999999999833466546306226519
 +)  0.00000000000000002081668171172169
 -------------------------------------------------
     0.99999999999999833466546306226519
====================================================================================
     0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1000 1000 0000
 +)  0 .0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0001 0000
 ------------------------------------------------------------------------LGRS-oooo
     0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1000 1000 0000
        Binary Result(Add significant digits) =>xxxxx 111 1111 1111 1000 1001 0000
.
     0.99999999999999833466546306226519
 +)  0.00000000000000001387778780781446
 -------------------------------------------------
     0.99999999999999833466546306226519
====================================================================================
     0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1000 1000 0000
 +)  0 .0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 1000
 ------------------------------------------------------------------------LGRS-oooo
     0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1000 1000 0000
        Binary Result(Add significant digits) =>xxxxx 111 1111 1111 1000 1000 1000
.
     0.99999999999999833466546306226519
 +)  0.00000000000000000693889390390723
 -------------------------------------------------
     0.99999999999999833466546306226519
====================================================================================
......仮数部 LSB 1、小数点以下...(-n) + (+x)...............
...............................................
    -0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0000 0000
 +)  0 .0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 1000 0000
 ------------------------------------------------------------------------LGRS-oooo
    -0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1110 1000 0000
        Binary Result(Subtract significant digits) => 111 1111 1111 1110 1000 0000
.
    -0.99999999999999977795539507496869
 +)  0.00000000000000011102230246251565
 -------------------------------------------------
    -0.99999999999999966693309261245304
====================================================================================
    -0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0000 0000
 +)  0 .0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0111 1000
 ------------------------------------------------------------------------LGRS-oooo
    -0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1110 1000 0000
        Binary Result(Subtract significant digits) => 111 1111 1111 1110 1000 1000
.
    -0.99999999999999977795539507496869
 +)  0.00000000000000010408340855860843
 -------------------------------------------------
    -0.99999999999999966693309261245304
====================================================================================
    -0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0000 0000
 +)  0 .0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0111 0000
 ------------------------------------------------------------------------LGRS-oooo
    -0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1110 1000 0000
        Binary Result(Subtract significant digits) => 111 1111 1111 1110 1001 0000
.
    -0.99999999999999977795539507496869
 +)  0.00000000000000009714451465470120
 -------------------------------------------------
    -0.99999999999999966693309261245304
====================================================================================
    -0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0000 0000
 +)  0 .0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0110 1000
 ------------------------------------------------------------------------LGRS-oooo
    -0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1110 1000 0000
        Binary Result(Subtract significant digits) => 111 1111 1111 1110 1001 1000
.
    -0.99999999999999977795539507496869
 +)  0.00000000000000009020562075079397
 -------------------------------------------------
    -0.99999999999999966693309261245304
====================================================================================
    -0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0000 0000
 +)  0 .0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0110 0000
 ------------------------------------------------------------------------LGRS-oooo
    -0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1110 1000 0000
        Binary Result(Subtract significant digits) => 111 1111 1111 1110 1010 0000
.
    -0.99999999999999977795539507496869
 +)  0.00000000000000008326672684688674
 -------------------------------------------------
    -0.99999999999999966693309261245304
====================================================================================
    -0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0000 0000
 +)  0 .0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0101 1000
 ------------------------------------------------------------------------LGRS-oooo
    -0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1110 1000 0000
        Binary Result(Subtract significant digits) => 111 1111 1111 1110 1010 1000
.
    -0.99999999999999977795539507496869
 +)  0.00000000000000007632783294297951
 -------------------------------------------------
    -0.99999999999999966693309261245304
====================================================================================
    -0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0000 0000
 +)  0 .0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0101 0000
 ------------------------------------------------------------------------LGRS-oooo
    -0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1110 1000 0000
        Binary Result(Subtract significant digits) => 111 1111 1111 1110 1011 0000
.
    -0.99999999999999977795539507496869
 +)  0.00000000000000006938893903907228
 -------------------------------------------------
    -0.99999999999999966693309261245304
====================================================================================
    -0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0000 0000
 +)  0 .0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0100 1000
 ------------------------------------------------------------------------LGRS-oooo
    -0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1110 1000 0000
        Binary Result(Subtract significant digits) => 111 1111 1111 1110 1011 1000
.
    -0.99999999999999977795539507496869
 +)  0.00000000000000006245004513516506
 -------------------------------------------------
    -0.99999999999999966693309261245304
====================================================================================
    -0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0000 0000
 +)  0 .0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0100 0000
 ------------------------------------------------------------------------LGRS-oooo
    -0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0000 0000
        Binary Result(Subtract significant digits) => 111 1111 1111 1110 1100 0000
.
    -0.99999999999999977795539507496869
 +)  0.00000000000000005551115123125783
 -------------------------------------------------
    -0.99999999999999977795539507496869
====================================================================================
    -0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0000 0000
 +)  0 .0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0011 1000
 ------------------------------------------------------------------------LGRS-oooo
    -0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0000 0000
        Binary Result(Subtract significant digits) => 111 1111 1111 1110 1100 1000
.
    -0.99999999999999977795539507496869
 +)  0.00000000000000004857225732735060
 -------------------------------------------------
    -0.99999999999999977795539507496869
====================================================================================
    -0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0000 0000
 +)  0 .0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0011 0000
 ------------------------------------------------------------------------LGRS-oooo
    -0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0000 0000
        Binary Result(Subtract significant digits) => 111 1111 1111 1110 1101 0000
.
    -0.99999999999999977795539507496869
 +)  0.00000000000000004163336342344337
 -------------------------------------------------
    -0.99999999999999977795539507496869
====================================================================================
    -0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0000 0000
 +)  0 .0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0010 1000
 ------------------------------------------------------------------------LGRS-oooo
    -0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0000 0000
        Binary Result(Subtract significant digits) => 111 1111 1111 1110 1101 1000
.
    -0.99999999999999977795539507496869
 +)  0.00000000000000003469446951953614
 -------------------------------------------------
    -0.99999999999999977795539507496869
====================================================================================
    -0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0000 0000
 +)  0 .0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0010 0000
 ------------------------------------------------------------------------LGRS-oooo
    -0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0000 0000
        Binary Result(Subtract significant digits) => 111 1111 1111 1110 1110 0000
.
    -0.99999999999999977795539507496869
 +)  0.00000000000000002775557561562891
 -------------------------------------------------
    -0.99999999999999977795539507496869
====================================================================================
    -0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0000 0000
 +)  0 .0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0001 1000
 ------------------------------------------------------------------------LGRS-oooo
    -0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0000 0000
        Binary Result(Subtract significant digits) => 111 1111 1111 1110 1110 1000
.
    -0.99999999999999977795539507496869
 +)  0.00000000000000002081668171172169
 -------------------------------------------------
    -0.99999999999999977795539507496869
====================================================================================
    -0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0000 0000
 +)  0 .0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0001 0000
 ------------------------------------------------------------------------LGRS-oooo
    -0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0000 0000
        Binary Result(Subtract significant digits) => 111 1111 1111 1110 1111 0000
.
    -0.99999999999999977795539507496869
 +)  0.00000000000000001387778780781446
 -------------------------------------------------
    -0.99999999999999977795539507496869
====================================================================================
    -0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0000 0000
 +)  0 .0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 1000
 ------------------------------------------------------------------------LGRS-oooo
    -0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0000 0000
        Binary Result(Subtract significant digits) => 111 1111 1111 1110 1111 1000
.
    -0.99999999999999977795539507496869
 +)  0.00000000000000000693889390390723
 -------------------------------------------------
    -0.99999999999999977795539507496869
====================================================================================
......仮数部 LSB 0、小数点以下...(-n) + (+x)...............
...............................................
    -0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1000 1000 0000
 +)  0 .0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 1000 0000
 ------------------------------------------------------------------------LGRS-oooo
    -0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1000 0000 0000
        Binary Result(Subtract significant digits) => 111 1111 1111 1000 0000 0000
.
    -0.99999999999999833466546306226519
 +)  0.00000000000000011102230246251565
 -------------------------------------------------
    -0.99999999999999822364316059974954
====================================================================================
    -0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1000 1000 0000
 +)  0 .0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0111 1000
 ------------------------------------------------------------------------LGRS-oooo
    -0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1000 0000 0000
        Binary Result(Subtract significant digits) => 111 1111 1111 1000 0000 1000
.
    -0.99999999999999833466546306226519
 +)  0.00000000000000010408340855860843
 -------------------------------------------------
    -0.99999999999999822364316059974954
====================================================================================
    -0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1000 1000 0000
 +)  0 .0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0111 0000
 ------------------------------------------------------------------------LGRS-oooo
    -0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1000 0000 0000
        Binary Result(Subtract significant digits) => 111 1111 1111 1000 0001 0000
.
    -0.99999999999999833466546306226519
 +)  0.00000000000000009714451465470120
 -------------------------------------------------
    -0.99999999999999822364316059974954
====================================================================================
    -0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1000 1000 0000
 +)  0 .0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0110 1000
 ------------------------------------------------------------------------LGRS-oooo
    -0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1000 0000 0000
        Binary Result(Subtract significant digits) => 111 1111 1111 1000 0001 1000
.
    -0.99999999999999833466546306226519
 +)  0.00000000000000009020562075079397
 -------------------------------------------------
    -0.99999999999999822364316059974954
====================================================================================
    -0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1000 1000 0000
 +)  0 .0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0110 0000
 ------------------------------------------------------------------------LGRS-oooo
    -0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1000 0000 0000
        Binary Result(Subtract significant digits) => 111 1111 1111 1000 0010 0000
.
    -0.99999999999999833466546306226519
 +)  0.00000000000000008326672684688674
 -------------------------------------------------
    -0.99999999999999822364316059974954
====================================================================================
    -0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1000 1000 0000
 +)  0 .0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0101 1000
 ------------------------------------------------------------------------LGRS-oooo
    -0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1000 0000 0000
        Binary Result(Subtract significant digits) => 111 1111 1111 1000 0010 1000
.
    -0.99999999999999833466546306226519
 +)  0.00000000000000007632783294297951
 -------------------------------------------------
    -0.99999999999999822364316059974954
====================================================================================
    -0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1000 1000 0000
 +)  0 .0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0101 0000
 ------------------------------------------------------------------------LGRS-oooo
    -0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1000 0000 0000
        Binary Result(Subtract significant digits) => 111 1111 1111 1000 0011 0000
.
    -0.99999999999999833466546306226519
 +)  0.00000000000000006938893903907228
 -------------------------------------------------
    -0.99999999999999822364316059974954
====================================================================================
    -0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1000 1000 0000
 +)  0 .0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0100 1000
 ------------------------------------------------------------------------LGRS-oooo
    -0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1000 0000 0000
        Binary Result(Subtract significant digits) => 111 1111 1111 1000 0011 1000
.
    -0.99999999999999833466546306226519
 +)  0.00000000000000006245004513516506
 -------------------------------------------------
    -0.99999999999999822364316059974954
====================================================================================
    -0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1000 1000 0000
 +)  0 .0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0100 0000
 ------------------------------------------------------------------------LGRS-oooo
    -0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1000 0000 0000
        Binary Result(Subtract significant digits) => 111 1111 1111 1000 0100 0000
.
    -0.99999999999999833466546306226519
 +)  0.00000000000000005551115123125783
 -------------------------------------------------
    -0.99999999999999822364316059974954
====================================================================================
    -0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1000 1000 0000
 +)  0 .0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0011 1000
 ------------------------------------------------------------------------LGRS-oooo
    -0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1000 1000 0000
        Binary Result(Subtract significant digits) => 111 1111 1111 1000 0100 1000
.
    -0.99999999999999833466546306226519
 +)  0.00000000000000004857225732735060
 -------------------------------------------------
    -0.99999999999999833466546306226519
====================================================================================
    -0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1000 1000 0000
 +)  0 .0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0011 0000
 ------------------------------------------------------------------------LGRS-oooo
    -0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1000 1000 0000
        Binary Result(Subtract significant digits) => 111 1111 1111 1000 0101 0000
.
    -0.99999999999999833466546306226519
 +)  0.00000000000000004163336342344337
 -------------------------------------------------
    -0.99999999999999833466546306226519
====================================================================================
    -0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1000 1000 0000
 +)  0 .0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0010 1000
 ------------------------------------------------------------------------LGRS-oooo
    -0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1000 1000 0000
        Binary Result(Subtract significant digits) => 111 1111 1111 1000 0101 1000
.
    -0.99999999999999833466546306226519
 +)  0.00000000000000003469446951953614
 -------------------------------------------------
    -0.99999999999999833466546306226519
====================================================================================
    -0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1000 1000 0000
 +)  0 .0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0010 0000
 ------------------------------------------------------------------------LGRS-oooo
    -0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1000 1000 0000
        Binary Result(Subtract significant digits) => 111 1111 1111 1000 0110 0000
.
    -0.99999999999999833466546306226519
 +)  0.00000000000000002775557561562891
 -------------------------------------------------
    -0.99999999999999833466546306226519
====================================================================================
    -0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1000 1000 0000
 +)  0 .0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0001 1000
 ------------------------------------------------------------------------LGRS-oooo
    -0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1000 1000 0000
        Binary Result(Subtract significant digits) => 111 1111 1111 1000 0110 1000
.
    -0.99999999999999833466546306226519
 +)  0.00000000000000002081668171172169
 -------------------------------------------------
    -0.99999999999999833466546306226519
====================================================================================
    -0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1000 1000 0000
 +)  0 .0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0001 0000
 ------------------------------------------------------------------------LGRS-oooo
    -0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1000 1000 0000
        Binary Result(Subtract significant digits) => 111 1111 1111 1000 0111 0000
.
    -0.99999999999999833466546306226519
 +)  0.00000000000000001387778780781446
 -------------------------------------------------
    -0.99999999999999833466546306226519
====================================================================================
    -0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1000 1000 0000
 +)  0 .0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 1000
 ------------------------------------------------------------------------LGRS-oooo
    -0 .1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1000 1000 0000
        Binary Result(Subtract significant digits) => 111 1111 1111 1000 0111 1000
.
    -0.99999999999999833466546306226519
 +)  0.00000000000000000693889390390723
 -------------------------------------------------
    -0.99999999999999833466546306226519
====================================================================================

###### マイナス無限大方向への丸め : プラス値 ########################################################
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
 +)                                                                   1 0000 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0010 0000 0000 .0
        Binary Result(Add significant digits) =>xxxxx 11 1111 1111 0010 0000 0000 .0
.
     2305843009213690112
 +)                  256
 -------------------------------------------------
     2305843009213690368
====================================================================================
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
 +)                                                                     1000 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
        Binary Result(Add significant digits) =>xxxxx 11 1111 1111 0001 1000 0000 .0
.
     2305843009213690112
 +)                  128
 -------------------------------------------------
     2305843009213690112
====================================================================================
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
 +)                                                                      100 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
        Binary Result(Add significant digits) =>xxxxx 11 1111 1111 0001 0100 0000 .0
.
     2305843009213690112
 +)                   64
 -------------------------------------------------
     2305843009213690112
====================================================================================
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
 +)                                                                       10 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
        Binary Result(Add significant digits) =>xxxxx 11 1111 1111 0001 0010 0000 .0
.
     2305843009213690112
 +)                   32
 -------------------------------------------------
     2305843009213690112
====================================================================================
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
 +)                                                                        1 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
        Binary Result(Add significant digits) =>xxxxx 11 1111 1111 0001 0001 0000 .0
.
     2305843009213690112
 +)                   16
 -------------------------------------------------
     2305843009213690112
====================================================================================
###### マイナス無限大方向への丸め : マイナス値 ########################################################
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
 -)                                                                   1 0000 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0010 0000 0000 .0
        Binary Result(Add significant digits) =>xxxxx 11 1111 1111 0010 0000 0000 .0
.
    -2305843009213690112
 -)                  256
 -------------------------------------------------
    -2305843009213690368
====================================================================================
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
 -)                                                                     1000 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0010 0000 0000 .0
        Binary Result(Add significant digits) =>xxxxx 11 1111 1111 0001 1000 0000 .0
.
    -2305843009213690112
 -)                  128
 -------------------------------------------------
    -2305843009213690368
====================================================================================
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
 -)                                                                      100 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0010 0000 0000 .0
        Binary Result(Add significant digits) =>xxxxx 11 1111 1111 0001 0100 0000 .0
.
    -2305843009213690112
 -)                   64
 -------------------------------------------------
    -2305843009213690368
====================================================================================
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
 -)                                                                       10 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0010 0000 0000 .0
        Binary Result(Add significant digits) =>xxxxx 11 1111 1111 0001 0010 0000 .0
.
    -2305843009213690112
 -)                   32
 -------------------------------------------------
    -2305843009213690368
====================================================================================
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
 -)                                                                        1 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0010 0000 0000 .0
        Binary Result(Add significant digits) =>xxxxx 11 1111 1111 0001 0001 0000 .0
.
    -2305843009213690112
 -)                   16
 -------------------------------------------------
    -2305843009213690368
====================================================================================
###### ゼロ方向への丸め : プラス値 ########################################################
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
 +)                                                                   1 0000 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0010 0000 0000 .0
        Binary Result(Add significant digits) =>xxxxx 11 1111 1111 0010 0000 0000 .0
.
     2305843009213690112
 +)                  256
 -------------------------------------------------
     2305843009213690368
====================================================================================
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
 +)                                                                     1000 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
        Binary Result(Add significant digits) =>xxxxx 11 1111 1111 0001 1000 0000 .0
.
     2305843009213690112
 +)                  128
 -------------------------------------------------
     2305843009213690112
====================================================================================
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
 +)                                                                      100 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
        Binary Result(Add significant digits) =>xxxxx 11 1111 1111 0001 0100 0000 .0
.
     2305843009213690112
 +)                   64
 -------------------------------------------------
     2305843009213690112
====================================================================================
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
 +)                                                                       10 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
        Binary Result(Add significant digits) =>xxxxx 11 1111 1111 0001 0010 0000 .0
.
     2305843009213690112
 +)                   32
 -------------------------------------------------
     2305843009213690112
====================================================================================
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
 +)                                                                        1 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
        Binary Result(Add significant digits) =>xxxxx 11 1111 1111 0001 0001 0000 .0
.
     2305843009213690112
 +)                   16
 -------------------------------------------------
     2305843009213690112
====================================================================================
###### ゼロ方向への丸め : マイナス値 ########################################################
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
 -)                                                                   1 0000 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0010 0000 0000 .0
        Binary Result(Add significant digits) =>xxxxx 11 1111 1111 0010 0000 0000 .0
.
    -2305843009213690112
 -)                  256
 -------------------------------------------------
    -2305843009213690368
====================================================================================
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
 -)                                                                     1000 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
        Binary Result(Add significant digits) =>xxxxx 11 1111 1111 0001 1000 0000 .0
.
    -2305843009213690112
 -)                  128
 -------------------------------------------------
    -2305843009213690112
====================================================================================
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
 -)                                                                      100 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
        Binary Result(Add significant digits) =>xxxxx 11 1111 1111 0001 0100 0000 .0
.
    -2305843009213690112
 -)                   64
 -------------------------------------------------
    -2305843009213690112
====================================================================================
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
 -)                                                                       10 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
        Binary Result(Add significant digits) =>xxxxx 11 1111 1111 0001 0010 0000 .0
.
    -2305843009213690112
 -)                   32
 -------------------------------------------------
    -2305843009213690112
====================================================================================
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
 -)                                                                        1 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
        Binary Result(Add significant digits) =>xxxxx 11 1111 1111 0001 0001 0000 .0
.
    -2305843009213690112
 -)                   16
 -------------------------------------------------
    -2305843009213690112
====================================================================================
###### プラス無限大方向への丸め : プラス値 ########################################################
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
 +)                                                                   1 0000 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0010 0000 0000 .0
        Binary Result(Add significant digits) =>xxxxx 11 1111 1111 0010 0000 0000 .0
.
     2305843009213690112
 +)                  256
 -------------------------------------------------
     2305843009213690368
====================================================================================
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
 +)                                                                     1000 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0010 0000 0000 .0
        Binary Result(Add significant digits) =>xxxxx 11 1111 1111 0001 1000 0000 .0
.
     2305843009213690112
 +)                  128
 -------------------------------------------------
     2305843009213690368
====================================================================================
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
 +)                                                                      100 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0010 0000 0000 .0
        Binary Result(Add significant digits) =>xxxxx 11 1111 1111 0001 0100 0000 .0
.
     2305843009213690112
 +)                   64
 -------------------------------------------------
     2305843009213690368
====================================================================================
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
 +)                                                                       10 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0010 0000 0000 .0
        Binary Result(Add significant digits) =>xxxxx 11 1111 1111 0001 0010 0000 .0
.
     2305843009213690112
 +)                   32
 -------------------------------------------------
     2305843009213690368
====================================================================================
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
 +)                                                                        1 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
     1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0010 0000 0000 .0
        Binary Result(Add significant digits) =>xxxxx 11 1111 1111 0001 0001 0000 .0
.
     2305843009213690112
 +)                   16
 -------------------------------------------------
     2305843009213690368
====================================================================================
###### プラス無限大方向への丸め : マイナス値 ########################################################
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
 -)                                                                   1 0000 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0010 0000 0000 .0
        Binary Result(Add significant digits) =>xxxxx 11 1111 1111 0010 0000 0000 .0
.
    -2305843009213690112
 -)                  256
 -------------------------------------------------
    -2305843009213690368
====================================================================================
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
 -)                                                                     1000 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
        Binary Result(Add significant digits) =>xxxxx 11 1111 1111 0001 1000 0000 .0
.
    -2305843009213690112
 -)                  128
 -------------------------------------------------
    -2305843009213690112
====================================================================================
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
 -)                                                                      100 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
        Binary Result(Add significant digits) =>xxxxx 11 1111 1111 0001 0100 0000 .0
.
    -2305843009213690112
 -)                   64
 -------------------------------------------------
    -2305843009213690112
====================================================================================
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
 -)                                                                       10 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
        Binary Result(Add significant digits) =>xxxxx 11 1111 1111 0001 0010 0000 .0
.
    -2305843009213690112
 -)                   32
 -------------------------------------------------
    -2305843009213690112
====================================================================================
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
 -)                                                                        1 0000 .0
 ---------------------------------------------------------------------L GRSo-oooo---
    -1 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 .0
        Binary Result(Add significant digits) =>xxxxx 11 1111 1111 0001 0001 0000 .0
.
    -2305843009213690112
 -)                   16
 -------------------------------------------------
    -2305843009213690112
====================================================================================

2024-03-11  「Raspberry-pi 5」
Raspberry pi 5を使ってみた。
[ras5.jpg]
4Bの頃から紙箱に裸で入っている。
基板サイズは今までと同じ。ビス穴も同じ。USB,LANコネクタ配置は2B,3Bと同じ。

通常の電源はTDKラムダ スイッチング電源 5V dc 6A以上のものを使っている。
USB TypeA オス・USB TypeC オス ケーブルを使うと、

usb_max_current_enable default 0 max-current 900
と認識される。

そこで、
 電源5Vー+ーーーーーーUSB VBUS5V   USB-C オス・USB-C オス ケーブルでRaspi5の電源へ。
      |    10kΩ
          +---/\/\/\--USB-C A5 (CC1)
          |    10kΩ
          +---/\/\/\--USB-C B5 (CC2)

 電源GNDーーーーーーーーUSB-C GND

とすると、
usb_max_current_enable default 0 max-current 3000
と認識される。

/boot/firmware/config.txtに「usb_max_current_enable=1」を設定すると上記のメッセージは出なかった。
5Aにさせるには、rpi-eeprom-config -eで「PSU_MAX_CURRENT=5000」と設定した。

カメラ picamera V2を接続した。
==== BOARD ( Memory 8.0MB ) ===
Raspberry Pi 5 Model B Rev 1.0
======= OS ( 64 Bits ) ========
Debian GNU/Linux 12 (bookworm)
===============================
/boot/firmware/config.txt に "camera_auto_detect=1"が記述してあるのでカメラを接続して自動検出する。
$ libcamera-hello -t 0
でエラーがでた。

「ERROR V4L2 v4l2_videodevice.cpp:1906 /dev/video4[16:cap]:
  Failed to start streaming: Broken pipe
  ERROR: *** failed to start camera ***」

$ libcamera-hello --list-camera
Available cameras
-----------------
0 : imx219 [3280x2464 10-bit RGGB] (/base/axi/pcie@120000/rp1/i2c@88000/imx219@10)
    Modes: 'SRGGB10_CSI2P' : 640x480 [206.65 fps - (1000, 752)/1280x960 crop]
                             1640x1232 [41.85 fps - (0, 0)/3280x2464 crop]
                             1920x1080 [47.57 fps - (680, 692)/1920x1080 crop]
                             3280x2464 [21.19 fps - (0, 0)/3280x2464 crop]
           'SRGGB8' : 640x480 [206.65 fps - (1000, 752)/1280x960 crop]
                      1640x1232 [83.70 fps - (0, 0)/3280x2464 crop]
                      1920x1080 [47.57 fps - (680, 692)/1920x1080 crop]
                      3280x2464 [21.19 fps - (0, 0)/3280x2464 crop]

接続カメラのリストは表示される。
libcamera-* は、リネームされて rpicam-* となっている。

"Raspberry pi 5 v4l2 Broken pipe"で検索して、

検索結果:https://github.com/raspberrypi/libcamera/issues/104
     libcamera-apps fail to run V2 camera on RPi5 #104 
の中にあった以下のコマンドを実行。

$ sudo rpi-update d16727d
$ sudo reboot

するとエラーがでなくなり、カメラが動作するようになる。

参照:https://www.raspberrypi.com/documentation/computers/camera_software.html
   Raspberry Pi Documentation
   Camera software

2B,3BケースのUSB,LANコネクタ穴に収まる。電源USB-C,HMDI 2個のコネクタが刺さるように穴を広げて、
電源SWの頭が基板端より少し出ているのでそこに穴を開ければ収まる。CPU上の板状の部分も取るといいかも。
[pi5b-case-pci-ssd.jpg]
メモリ基板 「Geekworm X1000 Pcie M.2 Key-M NVMe SSD拡張ボード」と
メモリ 「Samsung SSD 256GB PM991 M.2 2242 42mm PCIe 3.0 x4 NVMe MZALQ256HAJD MZALQ2560 ソリッドス
テートドライブ」追加してみました。

2.4Ghz WIFIは、大きな解像度(1920x1080)のディスプレイを接続しても接続できる。
Raspi4Bは、接続できない、できにくいことが多かった。

処理速度は早い。
USBブートは設定を変えること。
raspi-config の Advanced Options の A4 Boot Order の B2 にする。
リブートしてもUSBブートはしない。
ACアダプタONでも自動USBブートしない。
POWER SWを押すとUSBブートする。(ちょっと面倒)
POWER SWを押すまではFANが回る。

FANは常に回るわけではない。

USBデバイスでブートする場合

●POWER SWの扱い
 電源断状態から、ACアダプタで電源ONにして、ディスプレイに文字メッセージ表示のみになる。
 このとき1回 短押しするとUSBブートを始め、OSが起動する。

 デスクトップ表示中に短押しすると、シャットダウンポップアップメニューが出る。もう1回短押しするとシャットダウンし、ディスプレイ表示なしとなる。
 このとき5V電源は、電流が流れておりCPUは動作している。
 ディスプレイ表示なしのこのときPOWER SW短押しするとOS起動する。

 デスクトップ表示中にPOWER SWを長押ししたままでシャットダウンしてディスプレイ表示なしになる。このとき5V電源は電流はほぼゼロとなっている。

 ディスプレイ表示なし、5V電源は電流はほぼゼロのとき、 POWER SW短押しすると、ディスプレイに文字メッセージ表示されたら、もう1回短押しするとOS起動する。


SDカードよりブートする場合

●POWER SWの扱い
 電源断状態から、ACアダプタで電源ONにして、ディスプレイに文字メッセージ表示し、自動でOSが起動する。

 デスクトップ表示中に短押しすると、シャットダウンポップアップメニューが出る。もう1回短押しするとシャットダウンし、ディスプレイ表示なしとなる。
 このとき5V電源は、電流が流れておりCPUは動作している。
 ディスプレイ表示なしのこのときPOWER SW短押しするとOS起動する。

 デスクトップ表示中にPOWER SWを長押ししたままでシャットダウンしてディスプレイ表示なしになる。このとき5V電源は電流はほぼゼロとなっている。

 ディスプレイ表示なし、5V電源は電流はほぼゼロとき、 POWER SW短押しすると、ディスプレイに文字メッセージ表示されたら、自動でがOS起動する。

ドキュメントに書いてありました。
/boot/firmware/config.txt に usb_max_current_enable=1 を追加設定すれば自動起動すると。

POWER SWを押す回数が多そうなのでプッシュSWを追加した。
(昔のPCマザーボードについていたリセットSW)
短押し2回では電流が0.3Aほど流れている。ディスプレイは表示なし。
シリアルコンソールは動作しない。(電流が流れているので変な期待をしたのがバカだった)

その後短押し1回でOSが起動する。

電流が0.3Aほど流れているとき、

https://www.raspberrypi.com/documentation/computers/raspberry-pi.html#POWER_OFF_ON_HALT
より、

デフォルトではPMIC出力ありになっている。
LEDは赤色。ここでPWER SWを長押しするとLEDは赤色から緑色になってまた赤色となる。
このとき5V電源は電流はほぼゼロ。
roi-eeprom-config -e で”POWER_OFF_ON_HALT=1”にするとshutdownで電流はセロになる。
長押ししたままでシャットダウンしてディスプレイ表示なしに、短押し1回でOSが起動する。
USB電源入れ直すと自動でUSBブートする。

デスクトップ表示中に短押しすると、シャットダウンポップアップメニューが出るのは、WaylandのときでX11でDesktop表示では
短押しでは。シャットダウンポップアップメニューが出ない。長押しのみ有効。

アナログTVコンポジット出力を試してみた。
RasPi5基板のコンポジット信号出力パターン穴に接続する。

/boot/firmware/config.txt に
#dtoverlay=vc4-kms-v3d
dtoverlay=vc4-kms-v3d-pi5,composite
と修正する。再起動でTVに表示される。
2024-02-25 「BITBANGソフトウェアI2C」
雑誌インターフェース2024・3月号のソフトウェアI2C(I2C bitbang)を見てちょっと面倒そうだなと思って真似てやってみた。
I2C接続はオープンドレインで、誰かがLOWにしたら全部LOW検出のしくみで混乱してしまった。
テスト用にAVR ATTiny85でI2Cスレーブデバイスを作成し、PICOでBME280と一緒にテストする。

参考:
NXP I2Cドキュメント UM1024.pdf (日本語、英語)
トランジスタ技術 2014・10月号 2線シリアル・インターフェースI2C詳解 (p152-176)

PICOオープンドレインテストの配線。

PICO
3.3V -----/\/10KΩ\/\---+---▶|(LED)---/\/1KΩ\/\---> GND 
GP28 ------------------+

micropython のPICOオープンドレインテストプログラム
手で入力実行。
---
from machine import Pin
out = Pin(28)
out.init(Pin.OPEN_DRAIN)
out.value(0)  # LED消灯
out.value(1)  # LED薄く点灯
out.init(Pin.OUT)
out.value(0)  # LED消灯
out.value(1)  # LED点灯


==== BOARD ( Memory 8.0MB ) ===
Raspberry Pi 4 Model B Rev 1.5
======= OS ( 64 Bits ) ========
Debian GNU/Linux 12 (bookworm)
===============================

Raspberry pi書き込み用GPIO接続

ピン17,1:3.3V ーー> ATTINY85 pin8(VDD)
ピン19:MOSI(GPO10) ーー> ATTINY85 pin5(MOSI)
ピン21:MISO(GPIO9) ーー> ATTINY85 pin6(MISO)
ピン23:CLK(GPIO11) ーー> ATTINY85 pin7(CLK)
ATTINY85 pin8(VDD) --[10 kΩ]-- ATTINY85 pin1(RESET) pull up
ピン37:GPIO26 ーー> ATTINY85 pin1(RESET)
ピン6,39:GND ーー> ATTINY85 pin4(GND)

ヒューズビットが外付けXtal,セラミック発振子の場合はつけること。

インストール
sudo apt-get install gcc-avr avr-libc binutils-avr avrdude

sudo nano /etc/avrdude.conf
----修正 コメントを取る-----
programmer
     id                   = "linuxgpio";
     desc                 = "Use the Linux sysfs interface to bitbang GPIO line>
     type                 = "linuxgpio";
     prog_modes           = PM_ISP;
     reset                = 26;
     sck                  = 11;
     sdo                  = 10;
     sdi                  = 9;
 ;

https://yetanotherhackersblog.wordpress.com/2011/04/12/interfacing-the-beagleboard-with-an-attiny85-microcontroller-over-i2c/
Yet Another Hacker's Blog - Interfacing the BeagleBoard with an ATtiny85 Microcontroller over I2C

  ” You can download the code from here (its an AVR Studio project for AVR GCC).” 
  の「here」をクリック。

にあったリンクのソース ↓
https://storage.googleapis.com/google-code-archive-source/v2/code.google.com/usi-i2c-slave/source-archive.zip
をもらってきて、修正。
-----i2ctest.c -------
#define F_CPU 8000000UL
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay_basic.h>
#include "usiTwiSlave.h"
#include <avr/cpufunc.h>

#define I2C_SLAVE_ADDR  0x26
#define PIEZO PB1
#define GPIO_PIN PB3


// Somewhere to store the values the master writes to i2c register.
static volatile uint8_t pinb = 0;
static volatile uint8_t adc_data = 0;

void adcInit() {

	// Enable ADC2/PB4 as ADC input
	ADMUX |= 1 << MUX1;

	// Set the ADC clock precaler to 16 (ie 500KHz if the main clock is 8MHz).
	ADCSRA |= 1 << ADPS2;

	// Left align the output (this lets us just use the 8 bits in the ADCH output register (we 
	// can ignore the extra 2 bits in the ADCL register).
	ADMUX |= 1 << ADLAR;

	// Enable ADC.
	ADCSRA |= 1 << ADEN;
}

uint8_t adcRead() {

	// Start a conversion	
	ADCSRA |= 1 << ADSC;

	// Wait for it to finish
	while (ADCSRA & (1 << ADSC));

	// Get the result.
	return ADCH;
}

void on_buzz()
{
	TCCR0A &= 0xCF;		// Stop OC0B
	TCCR0A |= 0x10;		// out OC0B
}

void off_buzz()
{
	TCCR0A &= 0xCF;		// Stop OC0B
	PORTB &= ~(1 << PIEZO);
}

// A callback triggered when the i2c master attempts to read from a register.
uint8_t i2cReadFromRegister(uint8_t reg)
{
	uint8_t r;

	switch (reg)
	{
		case 0:  // read PB3
			if ( DDRB & (1 << PB3) ) {
				DDRB &= ~(1 << PB3);
				r = PINB;
			} 
			if ( PINB & (1<<PB3)) {
				r = 1;
			} else {
				r = 0;
			}
			return r;
		case 1:  // read ADC
			return adc_data;
		default:
			return 0xAA;
	}
}

// A callback triggered when the i2c master attempts to write to a register.
void i2cWriteToRegister(uint8_t reg, uint8_t value)
{

	switch (reg)
	{
		case 0:  // write PB3 
			DDRB |= (1 << PB3);
			if ( value & 1 )
			    PORTB |= 1 << PB3;
			else
			    PORTB &= ~(1 << PB3);
			break;
		case 1:  // write ON/OFF buzzer
			if( value & 1 )
				on_buzz();
			else
				off_buzz();
			break;
	}

}

ISR(TIM1_OVF_vect)
{
	adc_data = adcRead();
}

void init_int(void)
{
	// Timer0
	TCCR0A = 0x00;
	TCCR0B = 0x00;    
	TCCR0A = 0x02;	// OC0B out / CTC
	TCCR0B = 0x03;  // 2 Mhz / (64 [TCCR0B.CS0] * 2 * (n[OCR0A] - 1) ) = f(Hz)
	OCR0A = 38;     // 400Hz

	// Timer1
	TCCR1 = 0xcc;	// CK / 2048  -- OCR1C on zero cntr
	OCR1C = 100;	// 2Mhz / 2048 / 100 = 100ms 
	TIMSK |= 0x04;
}

int main()
{
	CLKPR = 0x80;
	CLKPR = 0x02;  // 8Mhz/4 =2000000hz

	// Set the LED pin as output.
	DDRB |= (1 << PIEZO);
	PORTB = (1 << PIEZO) ^ 0x3F; // in pull up
	init_int();
	adcInit();
	usiTwiSlaveInit(I2C_SLAVE_ADDR, i2cReadFromRegister, i2cWriteToRegister);
	sei();

	while (1)
	{
		_NOP();
	}
}
----
コンパイル
avr-gcc i2ctest.c usiTwiSlave.c -o i2cdev -Wall -Os -std=gnu99 -mmcu=attiny85 -I.
avr-objcopy -O ihex 12cdev i2cdev.hex
プログラム書き込み
sudo avrdude -p t85 -P linuxgpio -c linuxgpio -v -U flash:w:i2cdev.hex
ヒューズビット書き込み
sudo avrdude  -p t85 -c linuxgpio -P linuxgpio -v -U lfuse:w:0x72:m -U hfuse:w:0xDF:m -U efuse:w:0xFF:m
ATTiny85を試す。
i2cdetect -y 1
0x26 があること

・・・I2Cスレーブ機能
書き込みは、2バイト。
1バイト目 2バイト目
 0    0x01 (PB3 Hi - LED点灯) or 0x00 (PB3 Low - LED消灯)
 1    0x01 (PB1 - ピエゾ鳴く) or 0x00 (PB1 - ピエゾ消音)
読み込みは、1バイト機能指定、1バイト読み込み。
1バイト目 読み込み値
 0    PB3 の値 Hi - 1 or Low - 0
 1    PB4 ADC値 0 ~ 255
・・・

Raspberry PICOには、BME280と作成したATTiny85とLED、抵抗、ピエゾ、SW、ボリューム抵抗を配線する。

PICO配線
[attiny85-i2cdev.jpg]
micropython のI2Cテストプログラム
---test.py---
from machine import Pin, I2C
from time import sleep

i2c = I2C(0, sda = Pin(0), scl = Pin(1), freq = 40000)
adr = i2c.scan()
adr_lst = list(hex(a) for a in adr)
print("Addr:", adr_lst)
i2c.writeto(0x26,b'\x01\x01')
sleep(0.5)
i2c.writeto(0x26,b'\x01\x00')
---
ブザーが鳴る。

micropython BitbangソフトI2C のテストプログラム。
--i2c-bme280-attiny85.py---
from machine import Pin

def SDA_BIT():
    return sda.value()

def I2C_INIT2():
    sda.init(Pin.OUT, Pin.OPEN_DRAIN)
    scl.init(Pin.OUT, Pin.OPEN_DRAIN)
    sda.value(1)
    scl.value(1)
    
def SDA_HIGH2():
    sda.value(1)

def SDA_LOW2():
    sda.value(0)
    
def SCL_HIGH2():
    scl.value(1)

def SCL_LOW2():
    scl.value(0)

# ========================
def start_condition():
    SCL_HIGH2()
    SDA_LOW2()

def stop_condition():
    SDA_LOW2()
    SCL_HIGH2()
    SDA_HIGH2()

def send_byte( byte ):
    for i in range(8):
        SCL_LOW2()
        if byte & (0x80>>i):
            SDA_HIGH2()
        else:
            SDA_LOW2()
        SCL_HIGH2()

    # getting ACK/NACK
    SCL_LOW2()
    SDA_HIGH2()

    SCL_HIGH2()
    nack = SDA_BIT()
    SCL_LOW2()
    return nack

def recv_byte(nack):
    b = 0
    SDA_HIGH2()

    for i in range(8):
        b <<= 1
        SCL_LOW2()
        SCL_HIGH2()
        b |= SDA_BIT()

    SCL_LOW2()
    if nack:
        SDA_HIGH2() # Last byte NACK
    else:
        SDA_LOW2()
    SCL_HIGH2()
    SCL_LOW2()

    return b

def p_out(adr, reg, data):
    start_condition()
    if send_byte( adr<<1|0 ): # Write
        stop_condition()
        print("Error OUTPUT:%02X / REG:%02X" % (adr, reg))
        return    
    send_byte( reg )
    send_byte( data ) 
    stop_condition()

def p_in(adr,reg):
    start_condition()
    if send_byte( adr<<1|0 ): # Write
        stop_condition()
        print("Error INPUT:%02X / REG:%02X" % (adr, reg))
        return    
    send_byte( reg )
    start_condition()
    send_byte( adr<<1|1 )     # Read
    data = recv_byte(True)    # 1byte NACK
    stop_condition()
    print("REG(%02X):%02X %d" % (reg,data,data))

import time

sda = Pin(0)
scl = Pin(1)

I2C_INIT2()
print("*** DUMP REGISTER ***")
print("BME280 ID : 0x60")
p_in(0x76, 0xD0)
print("BME280 制御")
print("BME280 Reg F2 : 0x01")
p_out(0x76, 0xF2,0x01)
print("BME280 Reg F4 : 0x27")
p_out(0x76, 0xF4,0x27)
print("BME280 Reg F5 : 0xA0")
p_out(0x76, 0xF5,0xA0)
p_in(0x76, 0xF2)
p_in(0x76, 0xF4)
p_in(0x76, 0xF5)
print("--ATTiny85 I2C--")
print("--OUT-- led ON, BUZZ on")
p_out(0x26, 0, 1) # led on
p_out(0x26, 1, 1) # buzz on
time.sleep(0.5)
print("--OUT-- led OFF, BUZZ off")
p_out(0x26, 0, 0) # led off
p_out(0x26, 1, 0) # buzz off
print("--IN--")
p_in(0x26, 0)     # PB3 in
p_in(0x26, 1)     # ADC in
time.sleep(0.5)
print("--OUT-- led ON, BUZZ on")
p_out(0x26, 0, 1) # led on
p_out(0x26, 1, 1) # buzz on
time.sleep(0.5)
print("--OUT-- led OFF, BUZZ off")
p_out(0x26, 0, 0) # led off
p_out(0x26, 1, 0) # buzz off
----
結果
...
MPY: soft reboot
*** DUMP REGISTER ***
BME280 ID : 0x60
REG(D0):60 96
BME280 制御
BME280 Reg F2 : 0x01
BME280 Reg F4 : 0x27
BME280 Reg F5 : 0xA0
REG(F2):01 1
REG(F4):27 39
REG(F5):A0 160
--ATTiny85 I2C--
--OUT-- led ON, BUZZ on
--OUT-- led OFF, BUZZ off
--IN--
REG(00):00 0       <<==SW ONで1、OFFで0
REG(01):B5 181     <<==ボリューム位置で変わる 0〜255
--OUT-- led ON, BUZZ on
--OUT-- led OFF, BUZZ off
...
2024-01-17  「seed studio XIAO ESP32S3 Micropythonインストール」
seed studio XIAO ESP32S3 にMicropythonをインストールしてみた。

2023-12-05 arm64 bookworm DeskTop Full イメージを使う。
==== BOARD ( Memory 8.0MB ) ===
Raspberry Pi 4 Model B Rev 1.5
======= OS ( 64 Bits ) ========
Debian GNU/Linux 12 (bookworm)
===============================

ESP32-S3 micropythonダウンロード。

https://micropython.org/download/ESP32_GENERIC_S3/
https://micropython.org/resources/firmware/ESP32_GENERIC_S3-SPIRAM_OCT-20240105-v1.22.1.bin

apt install でESPTOOLがインストールできないので、

https://github.com/espressif/esptool/releases
より、 esptool-v4.7.0-arm64.zip ダウンロード。
解凍。
$ cd esptool-arm64
$ chmod +x esptool
$ ./esptool --help
  ヘルプが表示されること。

USBケーブル差し込む。
boot SWを押しながら、reset swをプッシュ、boot swをはなす。
(SWが小さい、扱いが雑だったのでBeset SWの上の盛り上がった接触接点が剥がれた)

$ ./esptool --port /dev/ttyACM0 chip_id
====
esptool.py v4.7.0
Serial port /dev/ttyACM0
Connecting...
Detecting chip type... ESP32-S3
Chip is ESP32-S3 (QFN56) (revision v0.2)
Features: WiFi, BLE, Embedded PSRAM 8MB (AP_3v3)
Crystal is 40MHz
MAC: dc:da:0c:57:ab:c0
Uploading stub...
Running stub...
Stub running...
Warning: ESP32-S3 has no Chip ID. Reading MAC instead.
MAC: dc:da:0c:57:ab:c0
Hard resetting via RTS pin...
===
$ ./esptool --chip esp32s3 --port /dev/ttyACM0 erase_flash
esptool.py v4.7.0
Serial port /dev/ttyACM0
Connecting...
Chip is ESP32-S3 (QFN56) (revision v0.2)
Features: WiFi, BLE, Embedded PSRAM 8MB (AP_3v3)
Crystal is 40MHz
MAC: dc:da:0c:57:ab:c0
Uploading stub...
Running stub...
Stub running...
Erasing flash (this may take a while)...
Chip erase completed successfully in 2.7s
Hard resetting via RTS pin...
===
$ ./esptool --chip esp32s3 --port /dev/ttyACM0 write_flash -z 0 ESP32_GENERIC_S3-SPIRAM_OCT-20240105-v1.22.1.bin
===
esptool.py v4.7.0
Serial port /dev/ttyACM0
Connecting...
Chip is ESP32-S3 (QFN56) (revision v0.2)
Features: WiFi, BLE, Embedded PSRAM 8MB (AP_3v3)
Crystal is 40MHz
MAC: dc:da:0c:57:ab:c0
Uploading stub...
Running stub...
Stub running...
Configuring flash size...
Flash will be erased from 0x00000000 to 0x0018efff...
Compressed 1631504 bytes to 1068949...
Wrote 1631504 bytes (1068949 compressed) at 0x00000000 in 10.0 seconds (effective 1298.8 kbit/s)...
Hash of data verified.

Leaving...
Hard resetting via RTS pin...
===

$ minicom -b 115200 -D /dev/ttyACM0
===
>>> help('modules')
__main__          bluetooth         heapq             select
_asyncio          btree             inisetup          socket
_boot             builtins          io                ssl
_espnow           cmath             json              struct
_onewire          collections       machine           sys
_thread           cryptolib         math              time
_webrepl          deflate           micropython       uasyncio
aioespnow         dht               mip/__init__      uctypes
apa106            ds18x20           neopixel          umqtt/robust
array             errno             network           umqtt/simple
asyncio/__init__  esp               ntptime           upysh
asyncio/core      esp32             onewire           urequests
asyncio/event     espnow            os                webrepl
asyncio/funcs     flashbdev         platform          webrepl_setup             
asyncio/lock      framebuf          random            websocket                 
asyncio/stream    gc                re                                          
binascii          hashlib           requests/__init__                           
Plus any modules on the filesystem                                              
>>> 
=====
または、Thonnyシェルで。

配線:                           XIAO ESP32S3 
          +-----/\/1kΩ/\----|◁---ESP32 GPIO 6
          |  LED
      ▽

         +--/\/10kΩ/\------------ESP32 3V3
         |
          +-----------------------ESP32 GPIO 7
          |
      ○ |
            |=  SW
          ○ |
          |
         ▽

        Rasberry pi ==== USBケーブル ==== ESP32

Thonnyで実行
--- sw-led.py ----
from machine import Pin
import time

user_led = Pin(21, Pin.OUT)
user_led.value(0)
led = Pin(6, Pin.OUT)
led.value(0)
sw = Pin(7, Pin.IN)
while True:
    user_led.value(user_led.value() ^ 1)
    if sw.value():
        led.value(0)
    else:
        led.value(1)
    time.sleep(0.5)
-----
実行
 ユーザLEDが点滅、SW ONでLEDが点灯。

[seed-studio-ESP32S3.jpg]
2023-12-20 「PICO-W ble キーボード」
参考:
 https://forums.raspberrypi.com/viewtopic.php?t=347395
  Running the BT demo programs - encouraged!

 https://github.com/bluekitchen/btstack
 Welcome to BTstack

 https://forums.raspberrypi.com/viewtopic.php?t=356457
 Trying to turn Pico W into a Bluetooth keyboard

  https://technotes.kynetics.com/2018/BLE_Pairing_and_bonding/
  BLE Pairing and Bonding

  https://bluekitchen-gmbh.com/btstack/
  BTstack Manual master-486107eca

  https://bluekitchen-gmbh.com/btstack/#examples/examples/
  LE Peripheral - Test Pairing Methods
  Main Application Setup
  (LE Secure Connections, Just Works)

Raspberry PICO-W でBluetoothキーボードを作ってみました。
NRF51822 Blutooth基板 BBC Micro:bit、BBC Micro:bit V2はnRF52833 と同じように接続するものです。
PICO-Wのサンプルは、ペアリング条件により接続できないスマホがあるが,ペアリング条件を変えると接続するようになる。
ペアリング条件はレガシーなので注意する必要があります。

キーボードマトリックス入力は、Microchip MCP23S17 2個でSPI経由で入力。

ble-keyboard
├── CMakeLists.txt
├── build
├── hog_keyboard_demo.c
├── hog_keyboard_demo.gatt
├── keyboard.c
└── keyboard.h


CMakefiles.txt
...
set(PROJECT       hog_keyboard_demo)
set(PICO_BOARD    pico_w)
set(PICO_SDK_PATH $ENV{PICO_SDK_PATH})

cmake_minimum_required(VERSION 3.12)
include(${PICO_SDK_PATH}/external/pico_sdk_import.cmake)
project(${PROJECT} C CXX ASM)
pico_sdk_init()

add_executable(${PROJECT}
  hog_keyboard_demo.c
  keyboard.c
)

target_link_libraries(${PROJECT}
    pico_stdlib
    pico_btstack_ble
    pico_btstack_classic #not needed for BLE only demos
    pico_btstack_cyw43
    pico_cyw43_arch_none
    hardware_spi
)

pico_enable_stdio_usb(${PROJECT} 1)
pico_enable_stdio_uart(${PROJECT} 0)

target_include_directories(${PROJECT} PRIVATE
  ${CMAKE_CURRENT_LIST_DIR}
  ${PICO_SDK_PATH}/../pico-examples/pico_w/bt/config
)
pico_btstack_make_gatt_header(${PROJECT} PRIVATE "${CMAKE_CURRENT_LIST_DIR}/hog_keyboard_demo.gatt")

pico_add_extra_outputs(${PROJECT})
....

hog_keyboard_demo.gatt  examples ソースディレクトリよりコピー

static uint8_t protocol_mode = 1; // mode = 0 にするとキー入力しない。

(1)sm_set_io_capabilities(IO_CAPABILITY_DISPLAY_ONLY);
   sm_set_authentication_requirements(SM_AUTHREQ_SECURE_CONNECTION | SM_AUTHREQ_BONDING);

   Windows11は入力できるが、Androidスマホはペアリングできない。

(2)// ======= LE Secure Connections, Just Works =============
     sm_set_io_capabilities(IO_CAPABILITY_NO_INPUT_NO_OUTPUT);
     sm_set_authentication_requirements(SM_AUTHREQ_SECURE_CONNECTION| SM_AUTHREQ_BONDING);

     Windows11, Android, Raspberry pi ペアリング、キー入力できる。
[ble-keyboard-0.jpg]

回路
[ble-keyboard-c.jpg]

ソースプログラム
[ble-keyboard.tgz] 7.4Kb

2023-11-18 「NFS ポート番号固定設定」
参考1:https://ny55.blogspot.com/2016/12/how-to-configure-static-ports-for-nfs.html
   How To Configure Static Ports for NFS on Linux
   
・・・・・・
NFS サーバが使用するポートは,111, 2049のUDP,TCPはきまっているが他は不定なのでDockerコンテナでは
NFSサーバが作りにくいので固定する。RPCクォータは使用しない。

==== BOARD ( Memory 4.0MB ) ===
Raspberry Pi 4 Model B Rev 1.2
======= OS ( 64 Bits ) ========
Debian GNU/Linux 12 (bookworm)
===============================

$ uname -a
Linux 49e189bedc2c 6.1.0-rpi4-rpi-v8 #1 SMP PREEMPT Debian 1:6.1.54-1+rpt2 (2023-10-05) aarch64 GNU/Linux

★インストール

$ ssudo apt install -y nfs-kernel-server

$ sudo nano /etc/exports
---
/export 192.168.1.0/24(rw,sync,no_subtree_check,no_root_squash,all_squash)
--- 追加

$ sudo nano /etc/nfs.conf
---
[lockd]
port=32767
udp-port=32767

 ;;

[mountd]
port=32766

# debug="all|auth|call|general|parse"
manage-gids=y

 ;;

[statd]
port=32765
outgoing-port=32764

 ;;

---修正

$ sudo systemctl stop nfs-kernel-server
$ sudo systemctl restart portmap
$ sudo systemctl start nfs-kernel-server

$ sudo mount -t nfs 192.168.1.xxx:/export /home/dkr

■■■■■■■■■
Dockerコンテナ

(1)Dockerfile
....
FROM arm64v8/debian
MAINTAINER “K.Shimoura"
ENV container docker
ENV DEBIAN_FRONTEND noninteractive
#           SIGNAL=37
STOPSIGNAL SIGRTMIN+3
# root パスワード設定
RUN printf "rootdocker\nrootdocker\n"| passwd > /dev/null 2>&1
RUN apt update
# ロケール設定
RUN apt install -y locales locales-all
ENV LC_ALL ja_JP.UTF-8
ENV LANG ja_JP.UTF-8
ENV LANGUAGE ja_JP.UTF-8
ENV TZ Asia/Tokyo
RUN echo 'export LC_ALL="ja_JP.UTF-8"' >> /etc/profile
RUN echo 'export LANG="ja_JP.UTF-8"' >> /etc/profile
RUN echo 'export LANGUAGE="ja_JP:jp"' >> /etc/profile
RUN echo 'export TZ="Asia/Tokyo"' >> /etc/profile
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
# install rc.local
COPY rc.local /etc/rc.local
RUN chmod +x /etc/rc.local
RUN echo "/etc/rc.local" >> /usr/bin/entry.sh
# NFS
RUN apt install -y init
RUN apt install -y nano
RUN apt install -y nfs-kernel-server
RUN sed -i -e "/^\[statd\]/a port=32765\\noutgoing-port=32764\\n" /etc/nfs.conf
RUN sed -i -e "/^\[mountd\]/a port=32766\\n" /etc/nfs.conf
RUN sed -i -e "/^\[lockd\]/a port=32767\\nudp-port=32767\\n" /etc/nfs.conf
RUN echo "/export 192.168.1.0/24(rw,sync,no_subtree_check,no_root_squash,all_squash)" >> /etc/exports
RUN apt install -y procps
CMD ["/usr/sbin/init"]
....

(2)コンテナ作成
$ docker build -t arm64/nfs .

(3)コンテナ実行
$ docker run --privileged -ti --rm -v /home/pi/DOCKER:/export -p 111:111 -p 111:111/udp -p 2049:2049 -p 2049:2049/udp -p 32764-32767:32764-32767 -p 32764-32767:32764-32767/udp --name nfs arm64/nfs

 ディレクトリの"/home/pi/DOCKER"はext4形式のこと。ext4形式以外だとNFSがエクスポートしない。
  
(4)NFSマウント 他のPCで
$ sudo mount -t nfs 192.168.1.xxx:/export /home/dkr
2025-03-10 「Raspbery pi PICO-W micorpythonをソースから作る」
Raspberry pi PICO WのMicropythonをソースから作ってみた。

参照:
  https://www.raspberrypi.com/documentation/microcontrollers/pico-series.html#pico-1-family
  Pico 1 family
  Documentation
    Raspberry Pi Pico W
    Software Development
    -- Raspberry Pi Pico C/C++ SDK, Raspberry Pi Pico Python SDK
    -- For instructions on how to use the debugger, see Getting Started with Pico-series Microcontrollers.

  getting-started-with-pico.pdf (15 October 2024)
   "Appendix C: Manual toolchain setup"
     Use the CLI to Blink an LED in C

 connecting-to-the-internet-with-pico-w.pdf (25 November 2024)
   "Appendix A: Building MicroPython from source"

  raspberry-pi-pico-c-sdk.pdf  (20 February 2025)


環境は
==== BOARD ( Memory 4.0MB ) ===
Raspberry Pi 5 Model B Rev 1.0
======= OS ( 64 Bits ) ========
Debian GNU/Linux 12 (bookworm)
===============================

手順は

$ mkdir ~/pico
$ cd ~/pico
$ wget https://raw.githubusercontent.com/raspberrypi/pico-setup/master/pico_setup.sh
$ chmod +x pico_setup.sh
$ ./pico_setup.sh
$ sudo reboot

  例題コンパイル

$ cd ~/pico/pico/pico-examples/build_pico
$ export PICO_SDK_PATH=../../pico-sdk
$ cmake -DPICO_BOARD=pico_w -DWIFI_SSID="Your Network" -DWIFI_PASSWORD="Your Password" ..
$ make

 MICROPYTHONコンパイル

micropythonソースは、

pico
└── pico
    ├── micropython
    ├── micropython-lib
    ├── openocd
    ├── pico-examples
    ├── pico-extras
    ├── pico-playground
    ├── pico-sdk
    ├── picoprobe
    └── picotool
になるように、git cloneする。
firmware.uf2をPICOに書き込む。

$ cd ~/pico/pico
$ git clone https://github.com/micropython/micropython.git --branch master
$ git clone https://github.com/micropython/micropython-lib.git --branch master
$ cd micropython
$ make -C ports/rp2 BOARD=RPI_PICO_W submodules
$ make -C mpy-cross
$ cd ports/rp2
$ make BOARD=RPI_PICO_W
$ ls build-RPI_PICO_W
...
CMakeCache.txt       firmware.dis      frozen_mpy            pins_RPI_PICO_W.c
CMakeFiles           firmware.elf      generated             pioasm
Makefile             firmware.elf.map  genhdr                pioasm-install
_deps                firmware.hex      pico-sdk              submodules
cmake_install.cmake  firmware.uf2      pico_flash_region.ld
...
$ picotool info -a build-RPI_PICO_W/firmware.uf2
...
File build-RPI_PICO_W/firmware.uf2 family ID 'rp2040':

Program Information
 name:              MicroPython
 version:           v1.25.0-preview.365.g3823aeb0f
 features:          thread support
                    USB REPL
 frozen modules:    aioble/security, aioble/l2cap, aioble/client,
                    aioble/central, aioble/server, aioble/peripheral,
                    aioble/device, aioble/core, aioble, urequests,
                    webrepl_setup, webrepl, ssl, ntptime, mip, requests,
                    neopixel, dht, ds18x20, onewire, uasyncio, asyncio/stream,
                    asyncio/lock, asyncio/funcs, asyncio/event, asyncio/core,
                    asyncio, rp2, _boot, _boot_fat
 binary start:      0x10000000
 binary end:        0x100d5278
 embedded drive:    0x1012c000-0x10200000 (848K): MicroPython

Fixed Pin Information
 none

Build Information
 sdk version:       2.1.1
 pico_board:        pico_w
 boot2_name:        boot2_w25q080
 build date:        Mar  9 2025
 build attributes:  MinSizeRel

Metadata Blocks
 none
..
--------
上記の手順で、

debugprobe.uf2
firmware.uf2
adc_console.uf2
adc_dma_capture.uf2
hello_adc.uf2
joystick_display.uf2
microphone_adc.uf2
onboard_temperature.uf2
read_vsys.uf2
blink_any.uf2
hello_anything.uf2
blink.uf2
blink_simple.uf2
clocks_detached_clk_peri.uf2
hello_48MHz.uf2
hello_gpout.uf2
hello_resus.uf2
build_variant1.uf2
build_variant2.uf2
hello_divider.uf2
dma_channel_irq.uf2
dma_control_blocks.uf2
hello_dma.uf2
sniff_crc.uf2
flash_cache_perfctr.uf2
flash_nuke.uf2
flash_program.uf2
flash_ssi_dma.uf2
flash_xip_stream.uf2
dht.uf2
hello_7segment.uf2
hello_gpio_irq.uf2
hello_serial.uf2
hello_usb.uf2
bmp280_i2c.uf2
i2c_bus_scan.uf2
ht16k33_i2c.uf2
lcd_1602_i2c.uf2
lis3dh_i2c.uf2
mcp9808_i2c.uf2
mma8451_i2c.uf2
mpl3115a2_i2c.uf2
mpu6050_i2c.uf2
pa1010d_i2c.uf2
pcf8523_i2c.uf2
slave_mem_i2c.uf2
slave_mem_i2c_burst.uf2
ssd1306_i2c.uf2
hello_interp.uf2
hello_multicore.uf2
multicore_fifo_irqs.uf2
multicore_runner.uf2
multicore_runner_queue.uf2
picow_bt_example_a2dp_sink_demo_background.uf2
picow_bt_example_a2dp_source_demo_background.uf2
picow_bt_example_gap_inquiry_background.uf2
picow_bt_example_gap_le_advertisements_background.uf2
picow_bt_example_gatt_counter_background.uf2
picow_bt_example_gatt_counter_with_wifi_background.uf2
picow_bt_example_gatt_heart_rate_client_background.uf2
picow_bt_example_gatt_streamer_server_background.uf2
picow_bt_example_gatt_streamer_server_with_wifi_background.uf2
picow_bt_example_hid_host_demo_background.uf2
picow_bt_example_hid_keyboard_demo_background.uf2
picow_bt_example_hid_mouse_demo_background.uf2
picow_bt_example_hog_host_demo_background.uf2
picow_bt_example_hog_keyboard_demo_background.uf2
picow_bt_example_hog_mouse_demo_background.uf2
picow_bt_example_pan_lwip_http_server_background.uf2
picow_bt_example_pbap_client_demo_background.uf2
picow_bt_example_sm_pairing_central_background.uf2
picow_bt_example_sm_pairing_peripheral_background.uf2
picow_bt_example_spp_counter_background.uf2
picow_bt_example_spp_streamer_background.uf2
picow_bt_example_spp_streamer_client_background.uf2
picow_ble_temp_reader.uf2
picow_ble_temp_sensor.uf2
picow_ble_temp_sensor_with_wifi.uf2
picow_access_point_background.uf2
picow_access_point_poll.uf2
picow_blink.uf2
picow_blink_fast_clock.uf2
picow_blink_slow_clock.uf2
picow_http_client.uf2
picow_http_client_verify.uf2
picow_httpd_background.uf2
picow_iperf_server_background.uf2
picow_iperf_server_poll.uf2
picow_ntp_client_background.uf2
picow_ntp_client_poll.uf2
picow_tcpip_server_background.uf2
picow_tcpip_server_poll.uf2
picow_tls_client_background.uf2
picow_tls_client_poll.uf2
picow_tls_verify_background.uf2
picow_udp_beacon_background.uf2
picow_udp_beacon_poll.uf2
picow_wifi_scan_background.uf2
picow_wifi_scan_poll.uf2
picoboard_blinky.uf2
picoboard_button.uf2
pio_addition.uf2
pio_apa102.uf2
pio_clocked_input.uf2
pio_differential_manchester.uf2
hello_pio.uf2
pio_hub75.uf2
pio_i2c_bus_scan.uf2
pio_ir_loopback.uf2
pio_logic_analyser.uf2
pio_manchester_encoding.uf2
pio_onewire.uf2
pio_blink.uf2
pio_pwm.uf2
pio_quadrature_encoder.uf2
pio_quadrature_encoder_substep.uf2
pio_spi_flash.uf2
pio_spi_loopback.uf2
pio_squarewave.uf2
pio_squarewave_div_sync.uf2
pio_st7789_lcd.uf2
uart_pio_dma.uf2
pio_uart_rx.uf2
pio_uart_rx_intr.uf2
pio_uart_tx.uf2
pio_ws2812.uf2
pio_ws2812_parallel.uf2
hello_pwm.uf2
pwm_led_fade.uf2
pwm_measure_duty_cycle.uf2
hello_reset.uf2
hello_rtc.uf2
rtc_alarm.uf2
rtc_alarm_repeat.uf2
bme280_spi.uf2
max7219_32x8_spi.uf2
max7219_8x7seg_spi.uf2
mpu9250_spi.uf2
spi_dma.uf2
spi_flash.uf2
spi_master.uf2
spi_slave.uf2
hello_double_tap.uf2
narrow_io_write.uf2
rand.uf2
unique_board_id.uf2
hello_timer.uf2
periodic_sampler.uf2
timer_lowlevel.uf2
hello_uart.uf2
lcd_uart.uf2
uart_advanced.uf2
dev_hid_composite.uf2
dev_lowlevel.uf2
dev_multi_cdc.uf2
tinyusb_dev_audio_4_channel_mic.uf2
tinyusb_dev_audio_test.uf2
tinyusb_dev_audio_test_multi_rate.uf2
tinyusb_dev_board_test.uf2
tinyusb_dev_cdc_dual_ports.uf2
tinyusb_dev_cdc_msc.uf2
tinyusb_dev_cdc_uac2.uf2
tinyusb_dev_dfu.uf2
tinyusb_dev_dfu_runtime.uf2
tinyusb_dev_dynamic_configuration.uf2
tinyusb_dev_hid_boot_interface.uf2
tinyusb_dev_hid_composite.uf2
tinyusb_dev_hid_generic_inout.uf2
tinyusb_dev_hid_multiple_interface.uf2
tinyusb_dev_midi_test.uf2
tinyusb_dev_msc_dual_lun.uf2
tinyusb_dev_net_lwip_webserver.uf2
tinyusb_dev_uac2_headset.uf2
tinyusb_dev_uac2_speaker_fb.uf2
tinyusb_dev_usbtmc.uf2
tinyusb_dev_video_capture.uf2
tinyusb_dev_video_capture_2ch.uf2
tinyusb_dev_webusb_serial.uf2
host_cdc_msc_hid.uf2
tinyusb_host_bare_api.uf2
tinyusb_host_cdc_msc_hid.uf2
tinyusb_host_device_info.uf2
tinyusb_host_hid_controller.uf2
tinyusb_host_msc_file_explorer.uf2
hello_watchdog.uf2
blink.uf2
hello_serial.uf2
hello_usb.uf2
 ができる。

□□□□□□□□□□
Micrpython を使う。

 USB port ==================================================> PICO-W USB port 

PICO-WのUSBケーブルをボードのSWを押しながら差し込む。
表示されたマスストレージデバイスに
 ~/pico/pico/micropython/ports/rp2/build-RPI_PICO_W/firmware.uf2 ファイルをドラッグコピーする。
ファイル名が消えたら書き込まれたことになる。


配線を以下のようにする。
              +------------------+
  USB port ===| Debug Probe  (U)-+---------------オレンジ----> PICO-W GPIO-1(RX UART) pin2
              |              (D) | D  未接続     イエロー----> PICO-W GPIO-0(TX UART) pin1
              +------------------+               ブラック----> PICO-W GND  pin3

 USB port ==================================================> PICO-W USB port 

$ sudo apt install minicom

PICO-W側のUSBケーブルを接続。

$ minicom -o -D /dev/ttyACM0
改行入力

>>> from machine import UART, Pin
>>> uart0 = UART(0,baudrate=115200, tx=Pin(0), rx=Pin(1))
>>> tsData= b'Hello world!!\r\n'

デバッグプローブのUSBケーブルを接続。
別端末ウィンドウより、

$ minicom -o -D /dev/ttyACM1

次にプログラム入力中ウィドウに以下を入力する。

>>> uart0.write(tsData)

デバッグプローブ側のウィンドウに"Hello world!!"が表示される。

>>> help('modules')
__main__          asyncio/__init__  hashlib           rp2
_asyncio          asyncio/core      heapq             select
_boot             asyncio/event     io                socket
_boot_fat         asyncio/funcs     json              ssl
_onewire          asyncio/lock      lwip              struct
_rp2              asyncio/stream    machine           sys
_thread           binascii          math              time
_webrepl          bluetooth         micropython       tls
aioble/__init__   builtins          mip/__init__      uasyncio
aioble/central    cmath             neopixel          uctypes
aioble/client     collections       network           urequests
aioble/core       cryptolib         ntptime           vfs
aioble/device     deflate           onewire           webrepl
aioble/l2cap      dht               os                webrepl_setup
aioble/peripheral ds18x20           platform          websocket
aioble/security   errno             random
aioble/server     framebuf          re
array             gc                requests/__init__
Plus any modules on the filesystem
>>> print(rp2.country())                                                        
JP                                                                              
>>> import machine
>>> led = machine.Pin("LED", machine.Pin.OUT)
>>> led.on()             # PICO-Wボード緑LED点灯
>>> led.off()      # PICO-Wボード緑LED消灯

>>> import sys
>>> sys.implementation
(name='micropython', version=(1, 25, 0, 'preview'), _machine='Raspberry Pi Pico W with RP2040', _mpy=4870, _build='RPI_PICO_W')
2023-09-21 「ENC28J60 LANアダプタ Micropython WEB Serverプログラム」
参考:日経LINUX 2017年4月号 Zero用のHAT風ボード イーサネットなどを実装 p-60 ~ 65

      http://www.picfun.com/ENC28J60frame.html
      デモプログラムを自作基板で動かす

      https://www.olimex.com/Products/Modules/Ethernet/MOD-ENC28J60/
      "ATMega32 example - ATMega32 and ENC28J60-H - written by Erik Rasmussen" In Right Window 
       https://www.olimex.com/Products/Modules/Ethernet/ENC28J60-H/resources/Webserver_ATMega32_ENC28J60-H.zip

ENC28J60 LANアダプタを使ってC言語で作成された
WEBサーバー"ATMega32 example - ATMega32 and ENC28J60-H - written by Erik Rasmussen"を
Raspberry pi PICO のMicropythonに書き換えてみた。

回路:
  "ENC28J60 LANアダプタ PYTHONプログラム"で使った基板を使う。
  PHY機能動作中にエラーがあると、SPIコマンドRESETではPHY機能をRESETできないので
  GP-22と基板RESETを接続し、プログラムでハードリセット実行可能。

配線:
  LANボード     RaspberryPI PICO
  3.3V  ------------- 3.3V OUT
    GND   ------------- GND
    INT   ------------- GP 21
    CS    ------------- GP 17
    SI    ------------- GP 19
    SO    ------------- GP 16
    SCK   ------------- GP 18
    RESET ------------- GP 22

実行:
$ thonny enc28j60.py
----
..... Init() Exit .....
. HwRevID: 0x04
. Cntrl: ECON1 ECON2 ESTAT  EIR  EIE
.        0x04  0x80  0x01  0x00  0xC0
. MAC  : MACON1 MACON3 MACON4
.        0x0D   0x32   0x00
. Rx   : ERXST  ERXND  ERXWRPT ERXRDPT ERXFCON EPKTCNT MAMXFL
.        0x0000 0x19FE 0x0000  0x0000  0xB0    0x00    0x05DC
. Tx   : ETXST  ETXND  MACLCON1 MACLCON2 MAPHSUP
.        0x19FF 0x1FFF 0x0F     0x37     0x10
..........
My MAC Adrress: b'3e:3f:3f:02:11:22'
------ PHY Register ------
- PHCON1:0000
- PHCON2:0100
- PHSTAT1:1804
- PHSTAT2:0400
- PHID1:0083
- PHID2:1400
------------
Link UP
Link UP
Link UP
Recv: 60 ,Data= b'3e 3f 3f 02 11 22 xx xx xx xx ed d5 08 06 00 01 08 00 06 04 00 02 xx xx xx xx ed d5 c0 a8 01 01 3e 3f 3f 02 11 22 c0 a8 01 27 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00'
1  Sec ..
Recv: 60 ,Data= b'3e 3f 3f 02 11 22 xx xx xx xx ed d5 08 06 00 01 08 00 06 04 00 01 xx xx xx xx ed d5 c0 a8 01 01 3e 3f 3f 02 11 22 c0 a8 01 27 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00'
2  Sec ..
Recv: 60 ,Data= b'3e 3f 3f 02 11 22 xx xx xx xx ed d5 08 06 00 01 08 00 06 04 00 01 xx xx xx xx ed d5 c0 a8 01 01 3e 3f 3f 02 11 22 c0 a8 01 27 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00'
3  Sec ..
4  Sec ..
Recv: 60 ,Data= b'3e 3f 3f 02 11 22 xx xx xx xx ed d5 08 06 00 01 08 00 06 04 00 01 xx xx xx xx ed d5 c0 a8 01 01 3e 3f 3f 02 11 22 c0 a8 01 27 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00'
Recv: 60 ,Data= b'ff ff ff ff ff ff xx xx xx xx ed d5 08 06 00 01 08 00 06 04 00 01 xx xx xx xx ed d5 c0 a8 01 01 00 00 00 00 00 00 c0 a8 01 27 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00'
5  Sec ..
6  Sec ..
Recv: 60 ,Data= b'ff ff ff ff ff ff xx xx xx xx ed d5 08 06 00 01 08 00 06 04 00 01 xx xx xx xx ed d5 c0 a8 01 01 00 00 00 00 00 00 c0 a8 01 27 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00'
Recv: 60 ,Data= b'ff ff ff ff ff ff xx xx xx xx ed d5 08 06 00 01 08 00 06 04 00 01 xx xx xx xx ed d5 c0 a8 01 01 00 00 00 00 00 00 c0 a8 01 27 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00'
7  Sec ..
8  Sec ..
9  Sec ..
10  Sec ..
11  Sec ..
12  Sec ..
13  Sec ..
14  Sec ..
15  Sec ..
---

WEBサーバーは実行前に、enc28j60.py, net.pyをRaspberry pi PICOメモリに書き込んでおく。

$ thonny websrv.py
---
..... Init() Exit .....
. HwRevID: 0x04
. Cntrl: ECON1 ECON2 ESTAT  EIR  EIE
.        0x04  0x80  0x01  0x00  0xC0
. MAC  : MACON1 MACON3 MACON4
.        0x0D   0x32   0x00
. Rx   : ERXST  ERXND  ERXWRPT ERXRDPT ERXFCON EPKTCNT MAMXFL
.        0x0000 0x19FE 0x0000  0x0000  0xB0    0x00    0x05DC
. Tx   : ETXST  ETXND  MACLCON1 MACLCON2 MAPHSUP
.        0x19FF 0x1FFF 0x0F     0x37     0x10
..........
---
[web-server-enc28j60.png]
WEBブラウザで http://192.168.1.39:8080 で見る。
"Set Blue","Set Green", "Set Red", "Clear Color" をクリックすると丸の色が変わる。

プログラム:
[micro-py-enc28j60-web-srv.zip]
2023-09-07 「ENC28J60 LANアダプタ PYTHONプログラム」
参考:日経LINUX 2017年4月号 Zero用のHAT風ボード イーサネットなどを実装 p-60 ~ 65

      http://www.picfun.com/ENC28J60frame.html
      デモプログラムを自作基板で動かす

   From https://github.com/przemobe/micropy-ENC28J60.git

ENC28J60でLAN基板を作って、PYTHONで制御してみた。
まず、SPIインターフェースを有効にする。dtoverlayは設定しない。
もとのプログラムは https://github.com/przemobe/micropy-ENC28J60.git MICROPYTONのプログラムをPYTHON3に書換えました。

回路:
[enc28j60-lan-circuit.jpg]

    PHY機能動作中にエラーがあると、SPIコマンドRESETではPHY機能をRESETできないので
    GPIO24と基板RESETを接続し、PYTHONプログラムでハードリセット実行を可能にしました。

配線:
  LANボード     RaspberryPI
  3.3V  ------------- 3.3V
    GND   ------------- GND
    INT   ------------- GPIO 25
    SCS   ------------- GPIO 8 / CE0
    MOSI  ------------- GPIO 10
    MISO  ------------- GPIO 9
    SCLK  ------------- GPIO 11
    RESET ------------- GPIO 24

実行:
$ python enc28j60.py
---
My MAC Adrress: b'3e:3f:3f:02:11:22'
..... INIT() exit .....
. HwRevID: 0x04
. Cntrl: ECON1 ECON2 ESTAT  EIR  EIE
.        0x04  0x80  0x01  0x00  0xD0
. MAC  : MACON1 MACON3 MACON4
.        0x0D   0xB3   0x40
. Rx   : ERXST  ERXND  ERXWRPT ERXRDPT ERXFCON EPKTCNT MAMXFL
.        0x0000 0x17FF 0x0000  0x17FF  0xA1    0x00    0x05EE
. Tx   : ETXST  ETXND  MACLCON1 MACLCON2 MAPHSUP
.        0x1800 0x1800 0x0F     0x37     0x10
..........
Link UP
Link UP
Link UP
------ PHY Register ------
- PHCON1:0100
- PHCON2:0100
- PHSTAT1:1804
- PHSTAT2:0600
- PHID1:0083
- PHID2:1400
------------
1  Sec ..
Recv: 60 ,Data= b'3e 3f 3f 02 11 22 XX XX XX X6 ed d5 08 06 00 01 08 00 06 04 00 02 XX XX XX X6 ed d5 c0 a8 01 01 3e 3f 3f 02 11 22 c0 a8 01 27 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00'
Recv: 60 ,Data= b'3e 3f 3f 02 11 22 XX XX XX X6 ed d5 08 06 00 01 08 00 06 04 00 01 XX XX XX X6 ed d5 c0 a8 01 01 3e 3f 3f 02 11 22 c0 a8 01 27 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00'
2  Sec ..
Recv: 60 ,Data= b'3e 3f 3f 02 11 22 XX XX XX X6 ed d5 08 06 00 01 08 00 06 04 00 01 XX XX XX X6 ed d5 c0 a8 01 01 3e 3f 3f 02 11 22 c0 a8 01 27 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00'
3  Sec ..
Recv: 60 ,Data= b'3e 3f 3f 02 11 22 XX XX XX X6 ed d5 08 06 00 01 08 00 06 04 00 01 XX XX XX X6 ed d5 c0 a8 01 01 3e 3f 3f 02 11 22 c0 a8 01 27 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00'
4  Sec ..
Recv: 60 ,Data= b'ff ff ff ff ff ff XX XX XX X6 ed d5 08 06 00 01 08 00 06 04 00 01 XX XX XX X6 ed d5 c0 a8 01 01 00 00 00 00 00 00 c0 a8 01 27 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00'
5  Sec ..
Recv: 60 ,Data= b'ff ff ff ff ff ff XX XX XX X6 ed d5 08 06 00 01 08 00 06 04 00 01 XX XX XX X6 ed d5 c0 a8 01 01 00 00 00 00 00 00 c0 a8 01 27 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00'
6  Sec ..
Recv: 60 ,Data= b'ff ff ff ff ff ff XX XX XX X6 ed d5 08 06 00 01 08 00 06 04 00 01 XX XX XX X6 ed d5 c0 a8 01 01 00 00 00 00 00 00 c0 a8 01 27 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00'
7  Sec ..
8  Sec ..
9  Sec ..
10  Sec ..
11  Sec ..
12  Sec ..
13  Sec ..
14  Sec ..
15  Sec ..
---

$ python sntp.py
---
..... INIT() exit .....
. HwRevID: 0x04
. Cntrl: ECON1 ECON2 ESTAT  EIR  EIE
.        0x04  0x80  0x01  0x00  0xD0
. MAC  : MACON1 MACON3 MACON4
.        0x0D   0xB3   0x40
. Rx   : ERXST  ERXND  ERXWRPT ERXRDPT ERXFCON EPKTCNT MAMXFL
.        0x0000 0x17FF 0x0000  0x17FF  0xA1    0x00    0x05EE
. Tx   : ETXST  ETXND  MACLCON1 MACLCON2 MAPHSUP
.        0x1800 0x1800 0x0F     0x37     0x10
..........
MAC ADDR: 3e:3f:3f:02:12:34
ENC28J60 revision ID: 0x04
[SNTP] Connecting...
ARP Request= b'ff ff ff ff ff ff 3e 3f 3f 02 12 34 08 06 00 01 08 00 06 04 00 01 3e 3f 3f 02 12 34 c0 a8 01 27 00 00 00 00 00 00 c0 a8 01 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00'
RECV= b'3e 3f 3f 02 12 34 XX xX XX X6 ed d5 08 06 00 01 08 00 06 04 00 02 XX xX XX X6 ed d5 c0 a8 01 01 3e 3f 3f 02 12 34 c0 a8 01 27 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00'
Rx ARP oper=2
ARP Register: 192.168.1.1 is at XX:XX:XX:X6:ED:D5
[SNTP] Connected
SNTP Request= b'1b 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00'
SEND NTP request: b'XX xX XX X6 ed d5 3e 3f 3f 02 12 34 08 00 45 00 00 4c 00 00 00 00 80 11 0e 31 c0 a8 01 27 a2 9f c8 01 1f bb 00 7b 00 38 97 d7 1b 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00'
RECV= b'3e 3f 3f 02 12 34 XX xX XX X6 ed d5 08 00 45 00 00 4c 7f bb 40 00 38 11 96 75 a2 9f c8 01 c0 a8 01 27 00 7b 1f bb 00 38 1f da 1c 03 00 e7 00 00 21 70 00 00 00 2f 0a 98 08 05 e8 9c 74 55 70 d5 43 24 00 00 00 00 00 00 00 00 e8 9c 74 a3 02 c4 c5 97 e8 9c 74 a3 02 c9 ab 45'
Rx my IP proto=17
[SNTP] Response received: time= 2023-09-01 23:33:07 (JST)
---

プログラム:
[python-enc28j60.zip]
2023-09-07  「抵抗−2RラダーDAC」
参考:トランジスタ技術 2001年3月号 P-343~347

[mcp23s17.jpg]
Microchip SPI 16bit Expander MCP23S17 を使って抵抗ラダーDACを作ってみた。 回路: [ladder-adc.jpg]
配線:   DACボード     RaspberryPI   5V ------------- 5V GND ------------- GND CS ------------- GPIO 8 / CE0 SI ------------- GPIO 10 SO ------------- GPIO 9 CLK ------------- GPIO 11 プログラム: 参照: https://hw101.tbs1.de/mcp23s17/ MCP23S17 I/O Expander Ansteuerungen grundlegender Hardwarebausteine $ nano MCP23S17.py --- import spidev class MCP23S17: def __init__(self, slave_address, busnumber, chipnumber): assert busnumber in [0, 1] assert chipnumber in [0, 1] self.controlbyte_write = 0x40 |(slave_address<<1) # <<==修正 self.controlbyte_read = 0x40 |((slave_address<<1)+1) # <<==修正 self.spi = spidev.SpiDev() self.spi.open(busnumber, chipnumber) self.spi.max_speed_hz = 10000000 # configure default registers self._regs = {'conf': {'A': 0x00, 'B': 0x01}, 'input': {'A': 0x12, 'B': 0x13}, 'output': {'A': 0x14, 'B': 0x15}} def write_config(self, portab, value): assert portab in ['A', 'B'] reg = self._regs['conf'][portab] self.spi.xfer([self.controlbyte_write, reg, value]) def read_config(self, portab): assert portab in ['A', 'B'] reg = self._regs['conf'][portab] return self.spi.xfer([self.controlbyte_read, reg, 0])[2] def write_output(self, portab, value): assert portab in ['A', 'B'] reg = self._regs['output'][portab] self.spi.xfer([self.controlbyte_write, reg, value]) def read_output(self, portab): assert portab in ['A', 'B'] reg = self._regs['output'][portab] return self.spi.xfer([self.controlbyte_read, reg, 0])[2] def read_input(self, portab): assert portab in ['A', 'B'] reg = self._regs['input'][portab] return self.spi.xfer([self.controlbyte_read, reg, 0])[2] --- $ nano macp23s1.py --- import MCP23S17 import time import math mcp = MCP23S17.MCP23S17(0,0,0) mcp.write_config('A',0x00) mcp.write_config('B',0x00) mcp.write_output('A',0x00) mcp.write_output('B',0x00) while 1: for d in range(256): mcp.write_output('A',d) mcp.write_output('B',d) time.sleep(0.5) --- 0〜255の変換。 [0-255-ladder-adc.jpg]
$ nano mcp23s2.py --- import MCP23S17 import time import math mcp = MCP23S17.MCP23S17(0,0,0) mcp.write_config('A',0x00) mcp.write_config('B',0x00) mcp.write_output('A',0x00) mcp.write_output('B',0x00) while 1: for d in range(0, 360, 5): s = math.sin( (math.pi * d) / 180.0 ) + 1.0 a = int(s * 127) mcp.write_output('A',a & 0xFF) mcp.write_output('B',a & 0xFF) #time.sleep(0.01) --- sin波形出力。 [sin-ladder-dac.jpg]
2023-07-12  「Raspberry Pi Bullseye OS にCAN ボード追加」
参考:(1)https://www.beyondlogic.org/adding-can-controller-area-network-to-the-raspberry-pi/
      Adding CAN to the Raspberry PI
      (2)https://qiita.com/suzutsuki0220/items/8642b1c3ea51859a95ad
        Raspberry PiでOBD-II (CAN)の情報を取得するための基板を自作する
   (3)https://westgate-lab.hatenablog.com/entry/2021/08/15/183000
        RaspberryPiでCAN通信(ドーターボード回路図付き)
      (4)http://reclearnengoolong.blog.fc2.com/blog-entry-1161.html
         動かして学ぶCAN通信(12)
   (5)https://stackoverflow.com/questions/73080694/how-to-install-a-rx-callback-with-python-can
         How to install a rx callback with python-can?
      (6)python-can PDFドキュメント Release 4.2.2  (Jun 30, 2023)


RasPi PICOに使ったCAN基板を使う。
OS はBullseye arm32 で設定。

配線:
   CAN基板    Ras PI
   CS   --------- GPIO 8
      SO   --------- GPIO 9
      SI   --------- GPIO 10
      SCK  --------- GPIO 11
      INT  --------- GPIO 25
      VCC  --------- 3.3V
      GND  --------- GND

      J1 ショート

設定:

$ sudo nano /boot/config.txt
---
dtparam=spi=on
dtoverlay=mcp2515-can0,oscillator=8000000,interrupt=25
---追加

動作確認:
$ sudo reboot

$ ip a
か
$ ifconfig

  can0 があればよい

$ sudo apt install can-utils
$ sudo ip link set can0 type can bitrate 500000 loopback on
$ sudo ip link set can0 up
$ candump can0 -x
別の端末WINDOWで
$ cansend can0 123#12345678
 candumpのWINDOWで送受信データが出ればOK.


$ sudo nano /etc/network/interfaces.d/can0.conf
----
auto can0
iface can0 inet manual
    pre-up /sbin/ip link set can0 type can bitrate 500000
    up /sbin/ip link set  can0 up
    down /sbin/ip link set can0 down
---作成

$ sudo reboot

Raspberry PiのMCP2515 CAN基板 と Raspberry Pi PICO のMCP2515 CAN基板を2線で接続する。

実行:

Raspberry Pi PICO側:             Raspberry Pi Bullseye OS側
 Thonny で MCP5215.py を実行する。      端末1 $ candump -x cano
                                                  端末2 $ cansend can0 123#12

  シェル: recv: ['0x12'] 表示                   端末1に  can0  TX - -  123   [1]  12
                                can0  RX - -  156   [4]  01 等が表示

となるところなのだが、PICO側MCP2515.pyの設定では反応がない。
CAN 500KBPS となっていないかもしれないので設定を調べる。


can CNF1,CNF2,CNF3を調べる
***************

mcp251x.c を 使ってCNF設定を調べる。
ビットタイミングの設定値はドライバーの別モジュールで計算されたものがlink upでmcp2515ドライバーに
渡される。

手順:

https://www.raspberrypi.org/documentation/linux/kernel/building.md
のLocal building のソースプログラム取得より

$ git clone --depth=1 https://github.com/raspberrypi/linux
ダウンロードされたら
 linux/drivers/net/can/spi/mcp251x.c をコピーする。

$ sudo apt install git bc bison flex libssl-dev make
  ほぼインストールされていると思うが。
  
$ nano Makefile
---
obj-m:=mcp251x.o

all:
	make -C /lib/modules/$(shell uname -r)/build M=${PWD} CFLAGS_$(obj-m)="-DDEBUG" modules

clean:
	make -C /lib/modules/$(shell uname -r)/build M=${PWD} clean

install:
	rm -f mcp251x.ko.xz
	xz mcp251x.ko
	cp mcp251x.ko.xz /lib/modules/$(shell uname -r)/kernel/drivers/net/can/spi/
---作成

 .xzのファイルでないとモジュールがロードされない。
 CFLAGS_$(obj-m)="-DDEBUG" でdev_dbg()が有効となってdmesgでCNFの内容がわかる。

$ make
$ sudo make install
$ sudo reboot
   /boot/config.txt のdtoverlayは設定済のこと。

設定調査手順:

sudo ip link set can0 down
sudo ip link set can0 type can bitrate 125000
        800KBPS以上は設定できないとなる。
    /bbo/config.txt の dtoverlay設定でXtal周波数がもっと高ければ,
        なんて仮定したらどうなるかは dtoverlay設定でXtal周波数を高くして定義して
    やってみるとOKとなる。
    もっと早いボーレートの場合は、もっと高いXtal周波数でないとだめ。

sudo ip link set can0 up
   これでMCP2515 のCNF1,CNF2,CNF3が設定される。
   600KBPSでワーニングが出る。
    mcp251x spi0.0 can0: bitrate error 4.7%
    mcp251x spi0.0: CNF: 0x00 0x89 0x01

dmesg | tail
ーーー
                 CNF1 CNF2 CNF3
    500KBPS      0x00 0x91 0x01
    250KBPS      0x00 0xB5 0x01
    125KBPS      0x01 0xB5 0x01
    100KBPS      0x01 0xBF 0x02
  

PYTHONプログラム:
  相手はPICO側のプログラムを実行する。
    ビットボーレートは設定してあるもの(/etc/network/interfaces.d/can0.conf)で実行される。

$ sudo apt install python3-can
  CANモジュールインストール

$ nano can.py
---
import os
import can
import time

def print_message(msg) -> None:
    if msg.is_error_frame is False:
      print('ID:',hex(msg.arbitration_id), ' DATA:', msg.data.hex() )
    else:
      print("Error recv()")

filter = [
{"can_id": 0x156, "can_mask": 0x7FF, "extended": False},
]

can0 = can.interface.Bus(channel = 'can0', bustype = 'socketcan', can_filters=filter) # socketcan_native
n = 0
smsg = [0x10,0x20,0x30,0x40,0x50,0x60,0x70,0x80]

notifier = can.Notifier(can0, [print_message])

try:
    while True:
        msg = can.Message(arbitration_id=0x123, data=smsg[n%8:], is_extended_id=False)
        try:
            can0.send(msg, timeout=3.0)  # ID:0x156 ==> ID:0x123
        except Exception as e:
            print("Error send()")

        n += 1
        time.sleep(0.5)

except KeyboardInterrupt:
    print('')
    notifier.stop()
    can0.shutdown()

--作成
  フィルター設定があるので指定IDしか受信しない。

$ python can.py

PICO ThonnyでCANプログラム実行

--- 結果---
Error recv()
Error recv()
ID: 0x156  DATA: 0102030405060708
ID: 0x156  DATA: 01
ID: 0x156  DATA: 0102
ID: 0x156  DATA: 010203
ID: 0x156  DATA: 01020304
ID: 0x156  DATA: 0102030405
ID: 0x156  DATA: 010203040506
ID: 0x156  DATA: 01020304050607
ID: 0x156  DATA: 0102030405060708
ID: 0x156  DATA: 01
ID: 0x156  DATA: 0102
ID: 0x156  DATA: 010203
ID: 0x156  DATA: 01020304
ID: 0x156  DATA: 0102030405

---PICO側シェル 結果---
...
init...
send data...
0x123 ['0x30', '0x40', '0x50', '0x60', '0x70', '0x80']
0x123 ['0x40', '0x50', '0x60', '0x70', '0x80']
0x123 ['0x50', '0x60', '0x70', '0x80']
0x123 ['0x60', '0x70', '0x80']
0x123 ['0x70', '0x80']
0x123 ['0x80']
0x123 ['0x10', '0x20', '0x30', '0x40', '0x50', '0x60', '0x70', '0x80']
0x123 ['0x20', '0x30', '0x40', '0x50', '0x60', '0x70', '0x80']
0x123 ['0x30', '0x40', '0x50', '0x60', '0x70', '0x80']
0x123 ['0x40', '0x50', '0x60', '0x70', '0x80']
0x123 ['0x50', '0x60', '0x70', '0x80']

2023-07-12  「Raspberry Pi PICO CAN 通信」
PICOでCAN通信ができるかやってみた。
使ったのはamazon で買った「MCP2515 CAN バス モジュール TJA1050 SPI レシーバー」3個セット。

[pico-can-board.jpg]
[pico-can-can.jpg] 参考:https://www.waveshare.com/wiki/Pico-CAN-B    WIKI Pico-CAN-B を参考にmicropython 上でWIKI Pico-CAN-B にあるPYTHONサンプルを使用した。 配線:   CAN基板    PICO   VCC -------- 3.3V OUT GND -------- GND CS -------- GP5 SO -------- GP4 SI -------- GP7 SCK -------- GP6 INT -------- GP21 J1 ショート  終端抵抗あり CAN-H ------- CAN-H CAN-L ------- CAN-L プログラム: サンプルプログラムは、IDが何でも受信するようになっているのでそれをID一致に修正した。 $ nano MCP5215.py --- from machine import Pin,SPI import time # Config Reg CANSTAT = 0x0E CANCTRL = 0x0F BFPCTRL = 0x0C CNF3 = 0x28 CNF2 = 0x29 CNF1 = 0x2A CANINTE = 0x2B CANINTF = 0x2C EFLG = 0x2D TXRTSCTRL = 0x0D # Recieve Filters RXF0SIDH = 0x00 RXF0SIDL = 0x01 RXF0EID8 = 0x02 RXF0EID0 = 0x03 # Receive Masks RXM0SIDH = 0x20 RXM0SIDL = 0x21 RXM0EID8 = 0x22 RXM0EID0 = 0x23 # Tx Buffer 0 TXB0CTRL = 0x30 TXB0SIDH = 0x31 TXB0SIDL = 0x32 TXB0EID8 = 0x33 TXB0EID0 = 0x34 TXB0DLC = 0x35 TXB0D0 = 0x36 TXB0D1 = 0x37 TXB0D2 = 0x38 TXB0D3 = 0x39 TXB0D4 = 0x3A TXB0D5 = 0x3B TXB0D6 = 0x3C TXB0D7 = 0x3D # Rx Buffer 0 RXB0CTRL = 0x60 RXB0SIDH = 0x61 RXB0SIDL = 0x62 RXB0EID8 = 0x63 RXB0EID0 = 0x64 RXB0DLC = 0x65 RXB0D0 = 0x66 RXB0D1 = 0x67 RXB0D2 = 0x68 RXB0D3 = 0x69 RXB0D4 = 0x6A RXB0D5 = 0x6B RXB0D6 = 0x6C RXB0D7 = 0x6D # CANCTRL REQOP_CONFIG = 0x80 REQOP_LISTEN = 0x60 REQOP_LOOPBACK =0x40 REQOP_SLEEP = 0x20 REQOP_NORMAL = 0x00 ABORT = 0x10 # CANSTAT OPMODE_CONFIG= 0x80 OPMODE_LISTEN= 0x60 OPMODE_LOOPBACK =0x40 OPMODE_SLEEP = 0x20 OPMODE_NORMAL= 0x00 # CAN Command CAN_RESET = 0xC0 CAN_READ = 0x03 CAN_WRITE = 0x02 CAN_RTS = 0x80 CAN_RTS_TXB0 = 0x81 CAN_RTS_TXB1 = 0x82 CAN_RTS_TXB2 = 0x84 CAN_RATE = { # 8MHz Xtal "5KBPS" : [0x31, 0XB5, 0x01], "10KBPS" : [0x18, 0XB5, 0X01], "20KBPS" : [0x09, 0XBF, 0x02], "50KBPS" : [0x04, 0XB5, 0x01], "100KBPS" : [0x01, 0xBF, 0x02], "125KBPS" : [0x01, 0xB5, 0x01], "250KBPS" : [0x00, 0xB5, 0x01], "500KBPS" : [0x00, 0x91, 0x01], } class MCP2515(): def __init__(self, my_id=0, intPin=21): self.intPin = intPin self.my_id = my_id self.SPI0_CS0 = 5 self.spi = SPI(0) self.spi = SPI(0,10000_000) self.spi = SPI(0,10000_000,polarity=0, phase=0,sck=Pin(6),mosi=Pin(7),miso=Pin(4)) self.cs = Pin(self.SPI0_CS0,Pin.OUT) def ReadByte(self, addr): self.cs(0) self.spi.write(bytearray([CAN_READ])) self.spi.write(bytearray([addr])) res = self.spi.read(1) self.cs(1) return int.from_bytes(res,'big') def WriteByte(self, addr): self.cs(0) self.spi.write(bytearray([addr])) self.cs(1) def WriteBytes(self, addr, data): self.cs(0) self.spi.write(bytearray([CAN_WRITE])) self.spi.write(bytearray([addr])) self.spi.write(bytearray([data])) self.cs(1) def Reset(self): self.cs(0) self.spi.write(bytearray([CAN_RESET])) self.cs(1) def Init(self, speed="500KBPS"): self.Reset() time.sleep(0.1) self.WriteBytes(CNF1, CAN_RATE[speed][0]) self.WriteBytes(CNF2, CAN_RATE[speed][1]) self.WriteBytes(CNF3, CAN_RATE[speed][2]) self.WriteBytes(TXB0SIDH,0xFF) self.WriteBytes(TXB0SIDL,0xE0) self.WriteBytes(TXB0DLC, 0) self.WriteBytes(RXB0SIDH,0x00) self.WriteBytes(RXB0SIDL,0x60) self.WriteBytes(RXB0CTRL,0x00) # match id self.WriteBytes(RXB0DLC, 0) self.WriteBytes(RXF0SIDH,(self.my_id>>3)&0xFF) self.WriteBytes(RXF0SIDL,(self.my_id&0x07)<<5) self.WriteBytes(RXM0SIDH,0xFF) self.WriteBytes(RXM0SIDL,0xE0) self.WriteBytes(CANINTF,0x00) # clean interrupt flag self.WriteBytes(CANINTE,0x00) # Recv Int self.WriteBytes(CANCTRL, REQOP_NORMAL) self.pInt = Pin(self.intPin, Pin.IN) self.pInt.irq(trigger=Pin.IRQ_FALLING, handler=self.call_read) self.WriteBytes(CANINTE,0x01) # Enabled Recv Interrupt def Send(self, CAN_ID, CAN_TX_Buf, length1): while (self.ReadByte(TXB0CTRL) & 0x08): time.sleep(0.01) # Wait Tx Busy self.WriteBytes(TXB0SIDH, (CAN_ID>>3)&0XFF) self.WriteBytes(TXB0SIDL, (CAN_ID&0x07)<<5) self.WriteBytes(TXB0EID8, 0) self.WriteBytes(TXB0EID0, 0) self.WriteBytes(TXB0DLC, length1) for j in range(0, length1): self.WriteBytes(TXB0D0+j,CAN_TX_Buf[j]) self.WriteBytes(TXB0CTRL, 0) # clean flag self.WriteByte(CAN_RTS_TXB0) def Receive(self): CAN_RX_Buf = [] len = self.ReadByte(RXB0DLC) for i in range(0, len): CAN_RX_Buf.append(hex(self.ReadByte(RXB0D0+i))) self.WriteBytes(CANINTF, 0) rid = (self.ReadByte(RXB0SIDH)<<3)|((self.ReadByte(RXB0SIDL)>>5)&0x07) # clean return [rid,CAN_RX_Buf] def call_read(self, p): msg = self.Receive() print(hex(msg[0]), msg[1]) if __name__ == '__main__': print("...") To_id = 0x156 can = MCP2515(my_id=0x123) print("init...") can.Init(speed='500KBPS') print("send data...") data = [65, 66, 67, 68, 69, 70, 71, 72] n = 0 try: while(1): can.Send(To_id, data, (n % 8) + 1) n += 1 time.sleep(0.3) except KeyboardInterrupt: print("\n...") --- 実行: ... init... send data... 0x123 ['0x30', '0x40', '0x50', '0x60', '0x70', '0x80'] 0x123 ['0x40', '0x50', '0x60', '0x70', '0x80'] 0x123 ['0x50', '0x60', '0x70', '0x80'] 0x123 ['0x60', '0x70', '0x80'] 0x123 ['0x70', '0x80'] 0x123 ['0x80'] 0x123 ['0x10', '0x20', '0x30', '0x40', '0x50', '0x60', '0x70', '0x80'] 0x123 ['0x20', '0x30', '0x40', '0x50', '0x60', '0x70', '0x80'] 0x123 ['0x30', '0x40', '0x50', '0x60', '0x70', '0x80'] 0x123 ['0x40', '0x50', '0x60', '0x70', '0x80'] 0x123 ['0x50', '0x60', '0x70', '0x80'] 0x123 ['0x60', '0x70', '0x80'] 0x123 ['0x70', '0x80'] 0x123 ['0x80'] 0x123 ['0x10', '0x20', '0x30', '0x40', '0x50', '0x60', '0x70', '0x80'] 0x123 ['0x20', '0x30', '0x40', '0x50', '0x60', '0x70', '0x80']
2023-06-29 「RasPI PICO LANケーブル接続」
Raspberry pi PICOにW5500 IC 基板でLANケーブルを接続する。
micropythonのW5500用のNetworkモジュールを追加したものを作成する。
[raspi-pico-page-http.jpg]

https://rafaelaroca.wordpress.com/2022/02/13/building-micropython-for-the-raspberry-pi-pico-with-ethernet-and-webrepl-support/
Yet Another Technology Blog
Building MicroPython for the Raspberry Pi PICO with Ethernet and WebREPL support
の中の 「Ethernet and Raspberry Pi Pico」
を参考にする。

$ git clone https://github.com/rafaelaroca/RP2040-HAT-MicroPython
$ cd RP2040-HAT-MicroPython
$ git submodule add https://github.com/micropython/micropython-lib/
$ cmake CMakeLists.txt
$ cd libraries
$ make -C mpy-cross
$ cd ports/rp2

$ nano boards/manifest.py
 ---
freeze("$(PORT_DIR)/modules")
freeze("$(MPY_DIR)/drivers/onewire")
freeze("$(MPY_DIR)/drivers/dht", "dht.py")
include("$(MPY_DIR)/extmod/uasyncio/manifest.py")
include("$(MPY_DIR)/drivers/neopixel/manifest.py")

freeze("$(MPY_DIR)/tools", ("upip.py", "upip_utarfile.py"))
freeze("$(MPY_DIR)/drivers/display", "ssd1306.py")
include("$(MPY_DIR)/extmod/webrepl/manifest.py")

# Libraries from micropython-lib, include only if the library directory exists
if os.path.isdir(convert_path("$(MPY_LIB_DIR)")):
    # file utilities
    freeze("$(MPY_LIB_DIR)/micropython/upysh", "upysh.py")

    # requests
    freeze("$(MPY_LIB_DIR)/python-ecosys/urequests", "urequests.py")
    freeze("$(MPY_LIB_DIR)/micropython/urllib.urequest", "urllib/urequest.py")

    # umqtt
    freeze("$(MPY_LIB_DIR)/micropython/umqtt.simple", "umqtt/simple.py")
    freeze("$(MPY_LIB_DIR)/micropython/umqtt.robust", "umqtt/robust.py")
---修正

$ make

  できた build-PICO/firmware.uf2  をPICOに書き込む。

配線:
	GPIO16  ---- MISO  W5500
	GPIO17	---- SCS   W5500
	GPIO18	---- SCLK  W5500
	GPIO19	---- MOSI  W5500
	GPIO20	---- RST   W5500
	GPIO21	---- INT   W5500
        3.3V    ---- 3.3V  W5500
        GND     ---- GND   W5500

        USB     ---- Raspberry Pi USB

実行:
 Thonny で RP2040-HAT-MicroPython-00/examples/HTTP/HTTP_Serverを開く。
ーーー
from usocket import socket
from machine import Pin,SPI
import network
import rp2
import time

led = Pin(25, Pin.OUT)

#W5x00 chip init
def w5x00_init():
    spi=SPI(0,2_000_000, mosi=Pin(19),miso=Pin(16),sck=Pin(18))
    nic = network.WIZNET5K(spi,Pin(17),Pin(20)) #spi,cs,reset pin
    nic.ifconfig(('192.168.1.20','255.255.255.0','192.168.1.1','8.8.8.8'))
    while not nic.isconnected():
        time.sleep(1)
        print(nic.regs())
    
def web_page():
    if led.value()==1:
        led_state="ON"
    else:
        led_state="OFF"
        
    html = """
    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Raspberry Pi Pico Web server - WIZnet W5100S</title>
    </head>
    <body>
    <div align="center">
    <H1>Raspberry Pi Pico Web server & WIZnet Ethernet HAT</H1>
    <h2>Control LED</h2>
    PICO LED state: <strong>""" + led_state + """</strong>
    <p><a href="/?led=on"><button class="button">ON</button></a><br>
    </p>
    <p><a href="/?led=off"><button class="button button2">OFF</button></a><br>
    </p>
    </div>
    </body>
    </html>
    """
    return html

def main():
    w5x00_init()
    s = socket()
    s.bind(('192.168.1.20', 80))
    s.listen(5)

    while True:
        conn, addr = s.accept()
        print('Connect from %s' % str(addr))
        request = conn.recv(1024)
        request = str(request)
        #print('Content = %s' % request)
        led_on = request.find('/?led=on')
        led_off = request.find('/?led=off')
        if led_on == 6:
            print("LED ON")
            led.value(1)
        if led_off == 6:
            print("LED OFF")
            led.value(0)
        response = web_page()
        conn.send('HTTP/1.1 200 OK\n')
        conn.send('Connection: close\n\n')
        conn.send(response)
        time.sleep(0.1)    # <<== 追加
        conn.close()

if __name__ == "__main__":
    main()
ーーー修正
DHCP IPアドレスは獲得できない。ifconfig()固定アドレスとなる。

実行する。

[raspi-pico-lan-http.png]
ブラウザでhttp://192.168.1.20 で LED ON/OFFボタンをクリックするとPICO基板のLEDが点灯・消灯する。
2023-06-24 「雑誌MabPi」
雑誌 The MagPi が issue 130 から、月末にアップロードされたが、次の月の15日にならないとPDF Freeダウンロード
できなくなった。

2023-08-07 「RasPI ZERO W5500、ENC29J60 LANアダプタ接続」
[Raspi-zero-enc28j60.jpg]
参考:日経LINUX 2017年4月号 Zero用のHAT風ボード イーサネットなどを実装 p-60 ~ 65

      http://www.picfun.com/ENC28J60frame.html
      デモプログラムを自作基板で動かす

ENC28J60でLAN基板を作ってみた。
ENC28J60はチップのREVSIONが4種類ある。
今回使うのを調べてみた。
まず、SPIインターフェースを有効にする。(まだ、dtoverlayは設定しない)
pythonプログラム
$ nano enc.py
---
import spidev
import time

spi = spidev.SpiDev()
spi.open(0, 0)
spi.max_speed_hz = 1200000

spi.xfer2([0xff]) # reset enc28j60
time.sleep(0.5)
spi.xfer2([0x9f,0x03])  # select enc28j60 banck 3
rev = spi.xfer2([0x12,0x00])  # read enc28j60 EREVID
print(rev[1]) # 4
spi.close()
---作成

$ python enc.py
...
4
...
EREVIP が4である。

回路:
[enc28j60-lan-circuit.jpg]

配線:
  LANボード     RaspberryPI
  3.3V  ------------- 3.3V
    GND   ------------- GND
    INT   ------------- GPIO 25
    CS    ------------- GPIO 8 / CE0
    SI    ------------- GPIO 10
    SO    ------------- GPIO 9
    SCLK  ------------- GPIO 11

OS: 2023-05-03 arm32 bullseye Desctopイメージ

設定:
  raspi-config     SPI インターフェース ON

  /boot/config.txt
    ------
    dtoverlay=enc28j60,int=pin=25
    -----追加

  /etc/dhcpcd.conf
    -----
    interface eth0
    static ip_address=192.168.1.5x/24
    static routers=192.168.1.x
    static domain_name_servers=192.168.1.x
    -----追加(固定IPアドレス)

★★★★他のLAN基板↓↓

[w5500-1.jpg]
[w5500-2.jpg]

Raspberry pi ZERO (WIFIなし)にMicroChip ENC28J60を同様なLANカードを接続する。
W5500が実装されたボードがAMAZONで売られているので買ってやってみた。

Copuhgima W5500イーサネットネットワークモジュールハードウェア / IP 51 / St2
マイクロコントローラプログラムオーバー W5100

配線:
  LANボード     RaspberryPI
  3.3V  ------------- 3.3V
    GND   ------------- GND
    INT   ------------- GPIO 25
    SCS   ------------- GPIO 8 / CE0
    MOSI  ------------- GPIO 10
    MISO  ------------- GPIO 9
    SCLK  ------------- GPIO 11
    5V     NC
    RST    NC

OS: 2023-05-03 arm32 bullseye Desctopイメージ

.... osinfo ....
==== BOARD ( Memory 0.5MB ) ===
Raspberry Pi Zero Rev 1.3
======= OS ( 32 Bits ) ========
Raspbian GNU/Linux 11 (bullseye)
===============================

設定:
  raspi-config     SPI インターフェース ON

  /boot/config.txt
    ------
    dtoverlay=w5500,int=pin=25,speed=20000000
    -----追加

  /etc/dhcpcd.conf
    -----
    interface eth0
    static ip_address=192.168.1.5x/24
    static routers=192.168.1.x
    static domain_name_servers=192.168.1.x
    -----追加(固定IPアドレス)

   DHCPでアドレスをふるようになってる場合はリブートするたびにアドレスが変わるので面倒な場合は
   固定IPアドレスにするのがよい。(MACアドレスがランダムに自動割当される)

設定が終わったら、リブートする。
dtoverlayではW5500を指定するのですがlsmodするとw5100となっている。
2023-06-13  「octave GPIO」
google検索の途中にたまたま引っかかったのでやってみた。
大分前にやったことがあったが、今はGUIも付いて変わっている。
CPPで作った関数が使えるんだとのこと。

sudo apt install octave
sudo apt install liboctave-dev  (実行ファイル mkoctfile)

wget http://www.airspayce.com/mikem/bcm2835/bcm2835-1.68.tar.gz
tar xzvf bcm2835-1.68.tar.gz
cd bcm2835-1.68/
./configure CFLAGS=-fPIC
make
sudo make install

cd ..

git clone https://github.com/gnu-octave/octave-rpi-gpio.git

cd octave-rpi-gpio

make

nano test_bcm2835oct.m
 ---
 sleep(x) を pause(x) に修正。
 ---

LEDと抵抗を40ピン 26(GPIO-7) と 30(GND)に配線。

octave
  端末でOCTAVE

 >> test_bcm2835oct

  test_bcm2835oct.m 実行。LEDが点滅する。

2023-06-25 「Raspberry Pi の小ワザ」
▲▲▲▲
PYTHONでファイルの種類を確認する。
・その1
sudo apt install python3-magic

>>> import magic
>>> f.from_file('345', mime=True)
'text/plain'
>>> f.from_file('pic01', mime=True)
'image/png'

・その2
>>> from subprocess import getoutput
>>> getoutput('file 345')
'345: UTF-8 Unicode text'
>>> getoutput('file pic01')
'pic01: PNG image data, 620 x 491, 8-bit/color RGBA, non-interlaced'

▲▲▲▲
Windowsで漢字ファイル名の入ったZIPファイルを解凍する。

 そのまま解凍すると文字化けになる。convmvでも変換できない。そんな時、
 $ sudo apt install unar
 $ unar xxxx.zip
▲▲▲▲
サービスの一覧

sudo service --status-all
sudo systemctl list-units --type=service

▲▲▲▲
https://www.raspberrypi.org/forums/viewtopic.php?t=96273
Mouse cursor 
より
・・・・・
白いカーソルにする。黒いのも。

sudo apt install  dmz-cursor-theme

メインメニュー → ルックアンドフィールの設定をする(メインメニューエディターでチェックを入れる)→ マウスカーソル タグ → DMZ(白)で選択する

大きさの設定はメインメニュー → Appearance Settings → System → Mouse Cursor で大中小サイズ選択

▲▲▲▲
GREP でPerlの正規表現を使う。
指定文字列以外の行。

gerp -P '(?!1234)' test.txt

カッコ,?,!にはエスケープシーケンスはいらない。

▲▲▲▲
nanoエディタ行番号表示
~/.nanorc
ーーー
set linenumbers
追加。

▲▲▲▲
WiFi POWER ON/OFF

https://raspberrypi.stackexchange.com/questions/73727/turning-off-wifi-bluetooth-module
Turning off Wifi/ Bluetooth module
より

ON :
 rfkill unblock wifi
OFF:
 rfkill block wifi

▲▲▲▲
sshfs でシンボリックリンクを扱う

sshfs pi@192.168.xx.xxx:/home/xxx mnt -o follow_symlinks
2023-05-23 「USBシリアルケーブルでシリアルコンソール追加」
本体のUART PINはそのまま使って、シリアルコンソールを使いたい場合はUSBシリアルケーブルを差し込んでそれを
シリアルコンソールとして使う。デバイス名が変化する場合はUDEVルールでデバイス名をシンボリックリンクで設定する。

$ sudo mkdir -p /etc/systemd/system/getty@ttyUSB0.service.d
$ sudo nano /etc/systemd/system/getty@ttyUSB0.service.d/autologin.conf
---
[Service]
ExecStart=
ExecStart=-/sbin/agetty --autologin pi --noclear %I 115200,38400,9600 vt220
---
  自動ログインを希望しない場合は、"--autologin pi" を削除。

$ sudo ln -s  /lib/systemd/system/getty@.service /etc/systemd/system/getty.target.wants/getty@ttyUSB0.service
$ sudo reboot
...
参考:https://gist.github.com/yoggy/de9a4a6405834f52accc
   yoggy/電源を入れたときにtty1を自動ログインする設定あれこれ集.md

      https://archlinuxarm.org/forum/viewtopic.php?f=31&t=5640
      Serial Console Configuration Question
2023-05-23 「Micropython TELNET サーバー」
2.4Ghz Wifi TELNET Server
Raspberry piのLAN経由で接続ができなくなったときとか、ただのWIFIリモートUARTケーブルとして使う。

Pico-wとESP32のMicropythonで動作。
Pico-W,ESP32のmain.pyと同じところにファイル"wifi.conf"は書き込む。

++配線++
raspberry pi                   PIco-W
 5V ----------------▶|--------VSYS
                  ダイオード
 GND ---------------------------GND
 GPIO 14(txd) ------------------GP1(RX)
 GPIO 15(rxd)-------------------GP0(TX)
                GP10 -----/\/\/\---▶|-----+
                                           1K      LED   |
                                GND ------------------------+
                                     TELNET接続時 UARTスピードにより
                   点滅時間が違う。
                   2秒以上点灯がある場合はLAN接続エラー。
ESP32
 LED = IO 5
  TXD = IO 17
  RXD = IO 16
 
++設定++
Raspberry pi
 シリアルコンソール有効
または、
Raspberry pi
  USBシリアルケーブルをシリアルコンソール設定する。
 このときは TXD ーーーー GP1
       RXD ーーーー GP0
 に接続する。
  USBシリアルケーブルはPICO ProbeをコンパイルしてPICOに書き込んだものでもよい。


---wifi.conf---
ssid=xxxSSIDxxx
passwd=xxxPASSWORDxxx
network=192.168.12.xxx,255.255.255.0,192.168.12.1,192.168.1.1
port=23
led=5
-------
port省略時は、23。led省略時は10。
networkは、固定IP,ネットワークマスク、GATEWAY,DNSサーバアドレスの順。省略時は、DHCPによる。

---program----
# (c) K.Shimomura (The MIT License)
from machine import UART, Pin,Timer
import machine
import network, time
import socket
import select
import _thread
import re
import uos

# for micropython

baud = (115200, 57600, 38400, 19200, 9600, 0)
bidx = 0
btmr = 0
mname = uos.uname()[0]

'''
    Timer Interrupt
'''
def RemoteGets(Timer):
    global btmr, pa, bidx

    # Run Wifi and Run UART speed by LED
    btmr += 1
    btmr &= 0xFF
    if (btmr & (1<<(bidx+1))):
        pa.value(1)  
    else:
        pa.value(0)

'''
   Telnet Protocol
'''
def will(id):
    return b'\xff\xfb' + id
    #print('will:',id)

def do(id):
    return b'\xff\xfd' + id
    #print('do:',id)

def wont(id):
    return b'\xff\xfc' + id
    #print('wont:',id)

def dont(id):
    return b'\xff\xfe' + id
    #print('dont:',id)

def negotiation(cl,polan):
    tcmd = b''
    subc = b'\x00'
    while True:
        res = polan.poll(300)
        if not res:
            c = None
            break
        c = cl.recv(1)
        if c == b'\xFF':  # IAC ?
            c = cl.recv(1)
            if c == b'\xfb':  # WILL ?
                tcmd += wont(cl.recv(1))
            elif c == b'\xfd': # DO ?
                tcmd += dont(cl.recv(1))
            elif c == b'\xfc': # WON'T ?
                tcmd += wont(cl.recv(1))
            elif c == b'\xfe': # DON'T ?
                tcmd += dont(cl.recv(1))
            elif c == b'\xfa': # sub ?
                subc = cl.recv(1)
                continue
            elif c == b'\xf0': # sub end ?
                tcmd += wont(subc)
                subc = b'\x00'
            else:
                if subc != b'\x00':
                    continue
                else:
                    break
        else:
            if subc != b'\x00':
                continue
            else:
                break
    if len(tcmd) > 0:
        cl.send(tcmd)
    return c

'''
  Password File 'wifi.conf'
   ssid=xxxSSIDxxx
    passwd=xxxPASSWORDxxx
    network=192.168.12.xxx,255.255.255.0,192.168.12.1,192.168.1.1
    port=23
    led=5
'''
def Get_Wificonf():
    ssid = ''
    passwd = ''
    content = ''
    netw = [ '' ]
    nport = 23
    ledpin = 10
    with open("wifi.conf", 'r') as file:
        content = file.read()
    if content != "":
        configs = content.split("\n") 
        pattn = re.compile(r'=')
        for c in configs:
            if c == "":
                continue
            id = pattn.split(c)
            if id[0].lower() == 'ssid':
                ssid = id[1]
            elif id[0].lower() == 'passwd':
                passwd = id[1]
            elif id[0].lower() == 'network':
                netw = id[1].split(",")
                if len(netw) < 4:
                    netw = [ "" ]
            elif id[0].lower() == 'port':
                try:
                    nport = int(id[1])
                except:
                    pass
            elif id[0].lower() == 'led':
                try:
                    ledpin = int(id[1])
                except:
                    pass
            else:
                pass
    return (ssid, passwd, netw, nport, ledpin)

'''
   Find null and write to serial console
'''
def CandSend(bstr, u0):
    s = bstr.replace(b'\r\000', b'\r')
    s = s.replace(b'\r\n',b'\r')
    if s != b'\000':
        u0.write(s)

'''
   Telnet Server for micropython
     Main
'''        
network.country('JP')

if mname == 'rp2':
    tim = Timer()
else:
    tim = Timer(0)

if mname == 'rp2':
    u0 = UART(0,baud[bidx],timeout=0)
else:
    u0 = UART(2,baud[bidx],timeout=0, tx=17, rx=16)

while u0.any():
    c = u0.read(1)
    time.sleep_ms(5)

#print("UART baud:", baud[bidx])
u0_poll = select.poll()

'''
   Initial Network and Connect WIFI
'''
wconf = Get_Wificonf()
wlssid = wconf[0]
wlpasswd = wconf[1]
wlnet = wconf[2]
wlport = wconf[3]
pa = Pin(wconf[4], Pin.OUT, value=0)
wlan = network.WLAN(network.STA_IF)
print('connecting to network...')
wlan.active(True)
# Set to Fixed IP address
if len(wlnet) == 4:
    wlan.ifconfig((wlnet[0], wlnet[1], wlnet[2], wlnet[3]))
else:
    pass
# Connect WIFI
wlan.connect(wlssid, wlpasswd)

max_wait = 10
while max_wait > 0:
    if wlan.isconnected():
        break
    max_wait -= 1
    print('waiting for connection...')
    time.sleep(1)

if not wlan.isconnected():
    pa.value(1)
    if wlan.status() != 3:
        time.sleep(2)
    else:
        time.sleep(5)
    machine.soft_reset()
    #raise RuntimeError('network connection failed')
else:
    print('connected')

print(wlan.ifconfig())

# Waiting a client
addr = socket.getaddrinfo('0.0.0.0', wlport)[0][-1]

s = socket.socket()

poller = select.poll()

s.bind(addr)
s.listen(1)

print('listening on', addr)

while True:
    '''
       Connect Client
    '''
    cl, addr = s.accept()
    poller.register(cl, select.POLLIN)
    print('client connected from', addr)
    # Start Interrupt Timer 10msec
    #   (Read Terminal Console to write client socket and LED ON)
    tim.init(period=10, mode=Timer.PERIODIC, callback=RemoteGets)
    u0.deinit()
    #bidx = 0
    if mname == 'rp2':
        u0 = UART(0,baud[bidx],timeout=0)
    else:
        u0 = UART(2,baud[bidx],timeout=0, tx=17, rx=16)
    while u0.any():
        c = u0.read(1)
        time.sleep_ms(5)
    time.sleep_ms(100)
    u0_poll.register(u0, select.POLLIN)
    # Send protocol
    cl.send(will(b'\x01')) # will
    cl.send(do(b'\x22'))   # do
    while True:
        res = poller.poll(0)
        if not res:
            continue
        else:
            r = negotiation(cl,poller)
            if r != None:
                CandSend(r, u0)
            else:
                pass
            break
    # Send Help Message
    cl.send(b'Pico-w TELNET Server\r\n Change UART Baudrate with "~~".\r\n')
    #
    r0 = b'\00'
    
    while True:
        '''
           Loop TELNET data Read
        '''

        try:
            res = poller.poll(0)
            if res:
                r = cl.recv(128)
                # Check Close socket (Disconnect Client)
                if r == b'':
                    break
                else:
                    pass
                #
                if r == b'~' and r0 == b'~':
                    # USRT baudrate change
                    u0_poll.unregister(u0)
                    u0.deinit()
                    bidx += 1
                    if baud[bidx] == 0:
                        bidx = 0
                    else:
                        pass
                    #print("UART baud:", baud[bidx])
                    if mname == 'rp2':
                        u0 = UART(0,baud[bidx],timeout=0)
                    else:
                        u0 = UART(2,baud[bidx],timeout=0, tx=17, rx=16)
                    # Read Noise data
                    while u0.any():
                        c = u0.read(1)
                        time.sleep_ms(5)

                    u0_poll.register(u0, select.POLLIN)
                    # Confirm To baudrate
                    # Check Printabled character
                    #u0.write(b'\r')
                    r0 = b' '
                    continue
                else:
                    if r0 == b'~':
                        u0.write(r0)
                    else:
                        pass
                if r0 != b'~' and r == b'~':
                    r0 = r
                    continue
                else:
                    pass
                r0 = r
                # Check Enter key code
                CandSend(r, u0)
            else:
                pass
        except:
            print("except")
        try:
            rtn = u0_poll.poll(0)
            if rtn:
                r = u0.read(128)
                cl.send(r)
            else:
                pass
        except:
            print("int-except")

    # Close Connect Client
    #   Close Timer Interrupt
    tim.deinit()
    time.sleep(0.2)
    poller.unregister(cl)
    # Connect LED OFF
    pa.value(0)  
    cl.close()

2023-04-08 「Rasperry pi PICO-W」
Raspberry pi PICO Wが発売になったのでひとつ買ってみた。
デバッグプローブも欲しかったのでセットになったものを入手。

[pico-w.jpg]

環境は
===== BOARD ( Memory 4MB ) ====
Raspberry Pi 400 Rev 1.0
======= OS ( 64 Bits ) ========
Debian GNU/Linux 11 (bullseye)  2023-2-21 bullseye Desktopイメージです。
===============================
または、
===== BOARD ( Memory 8MB ) ====
Raspberry Pi 4 Model B Rev 1.5
======= OS ( 64 Bits ) ========
Debian GNU/Linux 11 (bullseye)
===============================

NTPサーバより時刻データを取り込み表示する。
micropythonプログラム。
ssd1306モジュールはThonnyを使い取り込み、以下のプログラムはPICO-W基板へ"main.py"でセーブする。
----
# NTP Clock
from machine import Pin, I2C, RTC
import ssd1306  # 表示ライブラリ Thonnyで追加
import time
import network
import socket
import struct
import _thread

NTP_DELTA = 2208988800
host = "pool.ntp.org"
ssid = 'xxYour SSIDxx'
password = 'xxYour PASSWORDxx'
srtc = 0
rp2.country('JP')

def set_time(rtc):
    NTP_QUERY = bytearray(48)
    NTP_QUERY[0] = 0x23  # NTP V.4 , client, 設定時刻なし(RFC5905)
    addr = socket.getaddrinfo(host, 123)[0][-1]
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    try:
        #s.settimeout(1)
        res = s.sendto(NTP_QUERY, addr)
        msg = s.recv(48)
        val = struct.unpack("!I", msg[40:44])[0]
        t = val - NTP_DELTA + 9 * 3600  # JST
        tm = time.gmtime(t)
        #print(tm)
        rtc.datetime((tm[0], tm[1], tm[2], tm[6] + 1, tm[3], tm[4], tm[5], 0))
    finally:
        s.close()

def ntptime(rtc):
    wlan = network.WLAN(network.STA_IF)
    wlan.active(True)
    wlan.connect(ssid, password)
    max_wait = 10
    while max_wait > 0:
        if wlan.status() < 0 or wlan.status() >= 3:
            break
        max_wait -= 1
        print('connection...')
        time.sleep(1)
    if wlan.status() != 3:
        print("Network connection Failed!")
    else:
        print('connected')
        status = wlan.ifconfig()
        print( 'ip = ' + status[0] )
        set_time(rtc)
    wlan.deinit()

def Clock():
    rtc = RTC()
    # I2C設定
    i2c = I2C(0, sda=Pin(8), scl=Pin(9) )
    addr = i2c.scan()
    print( "I2C Address :" + hex(addr[0]) )
    # 表示設定
    display = ssd1306.SSD1306_I2C(128, 64, i2c)
    display.poweron()
    while True:
        timd = rtc.datetime()
        tsr ="%4d-%02d-%02d %d %02d:%02d:%02d %d" % timd 
        display.fill(0)
        display.text("Time",48,10)
        display.text(tsr[:10], 24, 30)
        display.text(tsr[13:21],32, 40)
        display.show()
        time.sleep(1)

rtc = RTC()
ntptime(rtc)
print("%4d-%02d-%02d [%d] %02d:%02d:%02d %d" % rtc.datetime()) 
_thread.start_new_thread(Clock, ())

while True:
    timd = rtc.datetime()
    if srtc != timd[2] and timd[3] == 0:
        ntptime(rtc)
        srtc = timd[2]
    else:
        time.sleep(3600)
-----
[ntpclock.jpg]

□□□□□□□□□□
Debug Probe なしで使う

 USB port ==================================================> PICO-W USB port 

デバッグプローブUSBはまだUSBポートに差し込まない。
PICO-WのUSBケーブルをボードのSWを押しながら差し込む。
表示されたマスストレージデバイスに
 ~/pico//micropython/ports/rp2/build-PICO/firmware.uf2 ファイルをドラッグコピーする。
ファイル名が消えたら書き込まれたことになる。

配線を以下のようにする。
              +------------------+
  USB port ===| Debug Probe  (U)-+---------------オレンジ----> PICO-W GPIO-1(RX UART) pin2
              |              (D) | D  未接続     イエロー----> PICO-W GPIO-0(TX UART) pin1
              +------------------+               ブラック----> PICO-W GND  pin3

 USB port ==================================================> PICO-W USB port 

$ sudo apt install minicom

PICO-W側のUSBケーブルを接続。

$ minicom -o -D /dev/ttyACM0
改行入力

>>> from machine import UART, Pin
>>> uart0 = UART(0,baudrate=115200, tx=Pin(0), rx=Pin(1))
>>> tsData= b'Hello world!!\r\n'

デバッグプローブのUSBケーブルを接続。
別端末ウィンドウより、

$ minicom -o -D /dev/ttyACM1

次にプログラム入力中ウィドウに以下を入力する。

>>> uart0.write(tsData)

デバッグプローブ側のウィンドウに"Hello world!!"が表示される。

>>> help('modules')
__main__          lwip              uasyncio/lock     ure
_boot             math              uasyncio/stream   urequests
_boot_fat         micropython       ubinascii         uselect
_onewire          mip/__init__      ucollections      usocket
_rp2              neopixel          ucryptolib        ussl
_thread           network           uctypes           ustruct
_uasyncio         ntptime           uerrno            usys
_webrepl          onewire           uhashlib          utime
builtins          rp2               uheapq            uwebsocket
cmath             uarray            uio               uzlib
dht               uasyncio/__init__ ujson             webrepl
ds18x20           uasyncio/core     umachine          webrepl_setup
framebuf          uasyncio/event    uos
gc                uasyncio/funcs    urandom                                     
Plus any modules on the filesystem                                              
>>> print(rp2.country())                                                        
XX                                                                              
>>> rp2.country('JP')                                                           
>>> print(rp2.country())                                                        
JP                                                                              

□□□□□□□□□□
Debug Probe を使う
getting_started_with_pico.pdf page-62

$ cd ~/pico
$ sudo apt install automake autoconf build-essential texinfo libtool libftdi-dev libusb-1.0-0-dev
$ git clone https://github.com/raspberrypi/openocd.git --branch rp2040 --depth=1
$ cd openocd
$ ./bootstrap
$ ./configure
$ make -j4
$ sudo make install

 configureに引数はDebug Probeのときはない。

  USB picoprobeのパーミッションの変更
  sudo nano /etc/udev/rules.d/98-p-probe.rules
   ---
   ATTRS{idVendor}=="2e8a", ATTRS{idProduct}=="000c", MODE="0666"
   ---作成
  sudo reboot

  USBベンダーとプロダクトはlsusbコマンドで表示されるもの。
  "ID 2e8a:000c Raspberry Pi Debug Probe (CMSIS-DAP)"
   作成したら、リブートして有効にすること。
   有効にしないとコンパイルはできるがデバッグができない。

$ cd ~/pico/pico-examples/blink
$ nano blink.c
  -----
    const uint LED_PIN = 15;
  -----修正

$ cd ~/pico/pico-examples/build/blink
$ make -j4

配線を以下のようにする。
 LEDに抵抗1KΩを直列に配線する。

 GPIO-15(20) -\/\/\---▶|---- GND(18)
               1K

              +------------------+
  USB port ===| Debug Probe  (U)-+---------------オレンジ----> PICO-W GPIO-1(RX UART) pin2
              |                  |               イエロー----> PICO-W GPIO-0(TX UART) pin1
              |                  |          ブラック----> PICO-W GND  pin3
              |                  |
              |              (D)-+---------------オレンジ----> PICO-W SWCLK
              +------------------+               ブラック----> PICO-W GND
                                      イエロー----> PICO-W SWDIO

 USB port ==================================================> PICO-W USB port 

[probe-conn.jpg]

$ openocd -f interface/cmsis-dap.cfg -c "adapter speed 5000" -f target/rp2040.cfg -c "program blink.elf verify reset exit"

 Debug Probeが刺さっていないとMSIS-DAPがないとエラーになる。
 プログラムの書き込み。LEDが点滅する。

■GDBでデバッグ
Firewallが設定してある場合は、IPV6許可をする。

$ sudo apt install gdb-multiarch
 最初のインストールで一緒に入るのかも。

$ cd ~/pico/pico-examples
$ cd build
$ export PICO_SDK_PATH=../../pico-sdk
$ cmake -DCMAKE_BUILD_TYPE=Debug ..
$ cd hello_world/serial
$ make -j4

配線を上記のまま使う。

$ openocd -f interface/cmsis-dap.cfg  -c "adapter speed 5000" -f target/rp2040.cfg

デバッグプローブ接続を先に接続して、別ウィンドウ1で
$ minicom -o -D /dev/ttyACM0

別ウィンドウ2で、

$ cd ~/pico/pico-examples/build/hello_world/serial
$ gdb-multiarch hello_serial.elf

(gdb) target remote localhost:3333

 これを省略するには、
 ~/.gdbinit  ファイルに
 ----
  target remote localhost:3333
  ----
  とする。

(gdb) load
(gdb) monitor reset init
(gdb) b main
(gdb) continue
 main()で止まる
(gdb) continue

  別ウィンドウ1で "Hello, world!" が表示される。

□□□□□□□□□□
自分のプロジェクト・WIFIアクセスポイント作成

$ cd ~/pico
$ git clone https://github.com/raspberrypi/pico-project-generator.git --branch master
$ cd pico-project-generator
$ ./pico_project.py --gui

Project Name: picow_access_point
 ソース名になる
Location: 適当な場所
Board Type: pico_W
Pico Wireless OPtion: BAckground lwIP  または、 Polled IwIP
Build Option: Run Build after generation
IDE OPtuin: SWD
[OK] クリック。雛形で生成コンパイルさせる。

その後、
~/pico/pico-examples/pico_w/wifi/access_point/ のディレクトリ dhcpserver、dnsserver と picow_access_point.cを
プロジェクトのディレクトリに上書きする。

├── CMakeLists.txt
├── build
├── dhcpserver
├── dnsserver
├── lwipopts.h
├── pico_sdk_import.cmake
└── picow_access_point.c

プログラム修正
$ nano picow_access_point.c
---
int main() {
    stdio_init_all();

    TCP_SERVER_T *state = calloc(1, sizeof(TCP_SERVER_T));
    if (!state) {
        DEBUG_printf("failed to allocate state\n");
        return 1;
    }

    //if (cyw43_arch_init()) {
    if (cyw43_arch_init_with_country(CYW43_COUNTRY_JAPAN)) {  <<==修正 国コードJP 設定
        DEBUG_printf("failed to initialise\n");
        return 1;
    }
    uint32_t c_code = cyw43_arch_get_country_code();      <<==追加 国別コード
    printf("contry-code:%c%c\n", c_code&0xFF,c_code>>8);    <<==追加

    const char *ap_name = "bxxxxx"; <<==SSID修正
#if 1
    const char *password = "5xxxxx"; <<==パスワード修正
#else
    const char *password = NULL;
#endif

    cyw43_arch_enable_ap_mode(ap_name, password, CYW43_AUTH_WPA2_AES_PSK);

--- 追加,修正する

$ nano CMakeLists.txt
---
add_executable(picow_access_point picow_access_point.c
        dhcpserver/dhcpserver.c                         # カッコ内に2業追加
        dnsserver/dnsserver.c              #
 )
 ;;

 ;;
target_include_directories(picow_access_point PRIVATE
  ${CMAKE_CURRENT_LIST_DIR}
  ${CMAKE_CURRENT_LIST_DIR}/.. # for our common lwipopts or any other standard includes, if required
  ${CMAKE_CURRENT_LIST_DIR}/dhcpserver   # 2行追加
  ${CMAKE_CURRENT_LIST_DIR}/dnsserver    #
)

---

プロジェクトのbuildデイレクトリで

$ make

エラーがなければ、

$ openocd -f interface/cmsis-dap.cfg -c "adapter speed 5000" -f target/rp2040.cfg -c "program picow_access_point.elf verify reset exit"

書き込み。

$ minicom -o -D /dev/ttyACM0

PICO-Wをリセットし、プログラムに設定したWIFI SSIDに接続して、ブラウザで、
http://192.168.4.1
URLでWEBページが表示される。LED ON/OFFをクリックするとUSBコネクタ脇の緑LEDが点滅する。

[access-point.png]

参照ドキュメント

 PicoW-A4-Pinout.pdf
 debug-connector-specification.pdf
 getting-started-with-pico.pdf
 pico-w-datasheet.pdf
 raspberry-pi-pico-c-sdk.pdf
 raspberry-pi-pico-python-sdk.pdf
  connecting-to-the-internet-with-pico-w.pdf

  https://www.raspberrypi.com/documentation/microcontrollers/debug-probe.html
  Raspberry Pi Debug Probe - About the Debug Probe

2023-12-01 「オートフォーカスカメラIMX519 INSTALL」
Piカメラ Arducam 16MP IMX519搭載 オート フォーカス [B0371]
==== bookworm =======arm64=======
Quick Start
https://docs.arducam.com/Raspberry-Pi-Camera/Native-camera/Quick-Start-Guide/

libcamera and libcamera-apps
https://docs.arducam.com/Raspberry-Pi-Camera/Native-camera/Libcamera-User-Guide/#autofocusmanual-focus-function
...

Quick Start / SOFTWARE GUIDE for IMX519 Autofocus Camera

wget -O install_pivariety_pkgs.sh https://github.com/ArduCAM/Arducam-Pivariety-V4L2-Driver/releases/download/install_script/install_pivariety_pkgs.sh

chmod +x install_pivariety_pkgs.sh

./install_pivariety_pkgs.sh -p libcamera

./install_pivariety_pkgs.sh -p libcamera_apps

sudo nano /boot/config.txt 
...
dtoverlay=imx519
...追加

sudo reboot

libcamera-jpeg -o test.jpg
libcamera-still -t 5000
libcamera-still -t 5000 -n -o test.jpg
libcamera-still -t 0 --autofocus-mode auto
libcamera-vid -t 10000 -o test.h264
libcamera-still -t 5000 --datetime -n --timelapse 1000
libcamera-vid -t 50000 --autofocus-mode continuous  --framerate 1 --autofocus-speed fast -n -o test.h264

2023-11-09 「google翻訳」
●Google翻訳,スピーチ

$ sudo apt install python3-venv
$ sudo apt install sox libsox-fmt-all
$ python3 -m venv venv
$ source venv/bin/activate

(venv) pi@xxxxx:~ $ pip3 install googletrans==4.0.0-rc1

(venv) pi@xxxxx:~ $ nano tr.py
---
from googletrans import Translator
tr = Translator()
txt = "I'm here."
ja1 = tr.translate(txt, src="en", dest="ja")
print("翻訳結果:",end='')
print(txt,end='')
print(" ==> ",end='')
print(ja1.text)
---
(venv) pi@xxxxx:~ $ python tr.py
翻訳結果:I'm here. ==> 私はここにいます。

(venv) pi@xxxxx:~ $ pip3 install google-speech

(venv) pi@xxxxx:~ $ google_speech -h

sox EFFECTを追加する。(-e の位置注意)
(venv) pi@xxxxx:~ $ google_speech -e speed 0.8 -l en "Hello"
ファイルへ。
(venv) pi@xxxxx:~ $ google_speech -l en -o out1.mp3 "Hello"; sox out1.mp3 out2.mp3 speed 0.8

●DOCKERコンテナ

1.Dockerfile

---
# translate/Dockerfile
FROM arm64v8/debian
MAINTAINER “K.Shimoura"
ENV container docker
ENV DEBIAN_FRONTEND noninteractive
#           SIGNAL=37
STOPSIGNAL SIGRTMIN+3
# root パスワード設定
RUN printf "rootdocker\nrootdocker\n"| passwd > /dev/null 2>&1
RUN apt update
# ロケール設定
RUN apt install -y locales locales-all
ENV LC_ALL ja_JP.UTF-8
ENV LANG ja_JP.UTF-8
ENV LANGUAGE ja_JP.UTF-8
ENV TZ Asia/Tokyo
RUN echo 'export LC_ALL="ja_JP.UTF-8"' >> /etc/profile
RUN echo 'export LANG="ja_JP.UTF-8"' >> /etc/profile
RUN echo 'export LANGUAGE="ja_JP:jp"' >> /etc/profile
RUN echo 'export TZ="Asia/Tokyo"' >> /etc/profile
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
# 1 ユーザ登録
# ユーザ作成
RUN echo "pi:pidocker:1000:1000:,,,:/home/pi:/bin/bash"|newusers
# ユーザ 設定
RUN cp -r /etc/skel/.[a-z]* /home/pi
RUN chown -R pi:pi /home/pi
RUN adduser pi audio
# アプリケーションインストール
RUN apt install -y alsa-utils
RUN apt install -y nano python3 python3-pip git
RUN apt install -y python-is-python3
RUN apt install -y python3-venv
RUN apt install -y sox libsox-fmt-all
RUN su - pi -c "python3 -m venv /home/pi/venv"
RUN su - pi -c "/bin/bash -c 'source /home/pi/venv/bin/activate;pip3 install googletrans==4.0.0-rc1'"
RUN su - pi -c "/bin/bash -c 'source /home/pi/venv/bin/activate;pip3 install google-speech'"
RUN apt install -y sudo
RUN printf 'pi ALL=(ALL) NOPASSWD: ALL\n' > /etc/sudoers.d/010_pi-nopasswd
RUN echo "if [ -n \$VIRTUAL_ENV_PROMPT ]; then PS1=\"\$VIRTUAL_ENV_PROMPT\$PS1\";fi"| tee -a /home/pi/.bashrc
# ユーザpiで実行
WORKDIR /home/pi
COPY config.sh /home/pi
RUN chmod +x /home/pi/config.sh
RUN chown pi:pi /home/pi/config.sh
USER pi
CMD ["/home/pi/config.sh"]
#CMD ["/home/pi/config.sh", "USB Sound Device" ]
#  コンテナ内でaplay -l での一覧でMP3,声を再生するデバイス名を引数で与える
#  声を再生しないときはデバイス名を省略する
---

2.環境設定
   $ nano config.sh
---
#!/bin/bash
# P1: sound device
if [ "$1" != "" ]; then
  sa=`aplay -l | grep "$1"| sed -e "s/^[^0-9]\+\([0-9]\+\).*$/\1/"`
  printf "defaults.pcm.card ${sa}\ndefaults.ctl.card ${sa}\n" | sudo tee /etc/asound.conf
fi
source /home/pi/venv/bin/activate;/bin/bash
---作成

3.コンテナ作成

   $ docker build -t arm64/translate .

4.コンテナ実行

   $ docker run -ti --rm -v ~/mp3:/home/pi/mp3 --name translate arm64/translate
     音を出す場合は、--privileged を指定する。mp3ファイル作成はいらない。

5.コマンド実行

   (venv) pi@xxxxxxxx:~$ nano tr.py
   ---
   from googletrans import Translator
   tr = Translator()
   txt = "I'm here."
   ja1 = tr.translate(txt, src="en", dest="ja")
   print("翻訳結果:",end='')
   print(txt,end='')
   print(" ==> ",end='')
   print(ja1.text)
   ---
   (venv) pi@xxxxxxxx:~$ python tr.py
   翻訳結果:I'm here. ==> 私はここにいます。

   (venv) pi@xxxxxxxx:~$ google_speech -h
   (venv) pi@xxxxxxxx:~$ google_speech -l en -o mp3/out1.mp3 "Hi, How are you?"
   (venv) pi@xxxxxxxx:~$ sox mp3/out1.mp3 mp3/out2.mp3 speed 0.8

5.コンテナ終了

  (venv) pi@xxxxxxxx:~$ exit
2023-03-07 「jupyter notebook, scikit-learn インストール」
■東京大学のデータサイエンティスト育成講座
 塚本邦尊、 山田典一、 大澤文孝 著      マイナビ出版 2019(1),2022(17)

 サンプルデータをダウンロードしてやってみた。
 サンプルデータはまだ修正されていなので本のプログラムのように修正する。

☆Chapter2-3-2-2 固有値と固有ベクトル
 # 固有値と固有ベクトル
 eig_value, eig_vector = linalg.eig(matrix)

 # 固有値と固有ベクトル
 print('固有値')
 print(eig_value)
 print('固有ベクトル')
 print(eig_vector)
  ------
  固有値
  [-1.+0.j  2.+0.j  2.+0.j]
  固有ベクトル
  [[-0.577 -0.578  0.579]
   [-0.577 -0.21  -0.788]
   [-0.577  0.788  0.209]]
  ----
  numpy.linag.eig()でも同じ
 Windowsマシンでもやってみたが本に記載されたような数値にはならない。
  ----
  import numpy as np
  import scipy as sc
  a = np.array([[1,-1,-1],[-1,1,-1],[-1,-1,1]])
  sc.linalg.eig(a)

  (array([-1.+0.j,  2.+0.j,  2.+0.j]),
   array([[ 0.57735027,  0.81649658,  0.40824829],
          [ 0.57735027, -0.40824829, -0.81649658],
          [ 0.57735027, -0.40824829,  0.40824829]]))
  ---

 WEB上の他の配列データを見てやってみたが、示されている数値になるものはある。
 本の配列データは誤差が大きくなるものなんだろうか?
 データサイエンスをやって見るにはいいきっかけなのかもしれない。

☆Chapter4-4-3-1 で3Dグラフが書けないのが気になって調べてみた。

 ”<Figure size 600x400 with 0 Axes>”これは3Dグラフから出るメッセージなんだ。
 グラフは出ない。

 参考: https://matplotlib.org/2.0.2/mpl_toolkits/mplot3d/tutorial.html
     mplot3d tutorial            より
 そこでplot_wireframe()例にあるように修正する。
 ----
  fig = plt.figure(dpi=100)

  # ax = Axes3D(fig)
  ax = fig.add_subplot(111, projection='3d') # <<<===
  ax.plot_wireframe(x, y, z)

  # x,y,zラベルの設定など
  ax.set_xlabel('x')
  ax.set_ylabel('y')
  ax.set_zlabel('f(x, y)')
  ----

 その他に、
 ---
  %matplotlib notebook
  ---
  とするとマウスでグルグル回せることがわかった。

 もうひとつ、この本はanaconda環境でやると便利といっていますが、Raspberry piでは今のところインストール環境が
 ない。minicondaがあるというので検索してみた。
 元ネタ:https://stackoverflow.com/questions/71150891/raspberry-pi-3-miniconda-install-aarch64-error
     Raspberry Pi 3 Miniconda install aarch64 error
 この手順でやってみた。
 ーー
 $ wget https://github.com/conda-forge/miniforge/releases/download/22.11.1-4/Mambaforge-22.11.1-4-Linux-aarch64.sh
 $ bash Mambaforge-22.11.1-4-Linux-aarch64.sh
  ライセンス表示、インストールするかの質問がくる。
 インストールが終わると、「Do you wish the installer to initialize Mambaforge by running conda init?」
 と聞かれてyesとすると.bashrcに自動的に端末ターミナルを開くとconda initが実行されるスクリプトが追加される。
 NOとする。
 $ nano ~/.bashrc
  ---
  export PATH="/home/ユーザ名/mambaforge/bin:$PATH"
  ---を最後に追加する。
 $ source ~/.bashrc
   PATHが追加される。
 $ conda init
  $ conda list
   インストールされているのが表示される。なにもない。conda環境だけである。
 元ネタではsudoコマンドであるがsudoにすると/root/.bashrc , /rootに環境ができてしまう。
 本には使うモジュールはまとまって記載されているので手でやってもいいかなと思う。
 特にCONDA環境でなくてもできるので使わないことにした。

☆Chapter5-3-3-3 微分方程式の計算
 3Dグラフが出ない。3Dの設定の関数呼び出しが誤りになっている。
 mplot3d tutorialより、同様に修正する
 ---
  # 関数の呼び出し
  v = odeint(lorenz_func, v0, t, args=(p, r, b))

  # 可視化
  fig = plt.figure()
 # ax = fig.gca(projection='3d')
  ax = fig.add_subplot(111,projection='3d')  # <<<=== 修正
  ax.plot(v[:, 0], v[:, 1], v[:, 2])

  # ラベルなど
  plt.title('Lorenz')
  plt.grid(True)
  ---
☆Chapter6  数値が半分くらいのがある。
      他にもある。
 『手を動かして学ぶデータ分析』なんです。
 表示された数値があっていたり、末尾の数値が1,2桁違っていたとしたら正しいと思えるが、それ以外は
 グラフのプロットする位置が違っていたり、数値が半分、倍の時っはなんとも言えない。

 バカが開けてはいけない”データサイエンス”の扉かもしれない。

☆Chapter10でload_boston()が使われていた。エラーメッセージに表示される手順でやってみた。

 [load_boston]

 ---- Iload_boston.ipynb -------
# # ボストンデータをインターネットから読み込む
# 
#   load_boston() で出るエラーメッセージより作成

# In[1]:


import pandas as pd
import numpy as np
from sklearn.utils import Bunch
from io import StringIO
import requests

def Iload_boston():
    data_url = "http://lib.stat.cmu.edu/datasets/boston"
    try:
        file_data = requests.get(data_url).text
        # bostonテキスト行データ
    except:
        print("インターネットデータ退避できていません")
        return None
    
    idata = pd.read_csv(StringIO(file_data), sep="\s+", skiprows=22, header=None)
    # 先頭22行読み飛ばし BOSTONデータ数値抽出
    vdata = np.hstack([idata.values[::2, :], idata.values[1::2, :2]])
    # 現行 1カラム目から、11データ 次の行に 1カラム目から、2データ = BOSTON数値データ
    target = idata.values[1::2, 2]
    # 次の行の 3カラム目をtaget データ
    raw_feature_names = pd.read_csv(StringIO(file_data), sep="\s+", skiprows=7,nrows=13,usecols=[0], header=None)
    # ファイル 8行目から、13行分が boston データ表のタイトル
    feature_names = raw_feature_names[0].to_list()
    # タイトルの行型データから、リスト型に変換
    return Bunch(data=vdata,target=target,feature_names=feature_names)


# In[2]:


qdata = Iload_boston()

# DataFrameにデータを格納
X = pd.DataFrame(qdata.data, columns=qdata.feature_names)

# 住宅価格の中央値(MEDV)のデータを用意
y = pd.Series(qdata.target, name='MEDV')

# Xとyを結合して先頭の5行を表示
X.join(y).head() 
-----

■jupyter-notebook インストール

  $ sudo apt install -y jupyter-notebook
   $ jupyter notebook --generate-config

   jupyter notebook 環境設定 パスワード設定
   $ jupyter notebook password
  
   実行は、プログラム格納ディレクトリで
  $ jupyter notebook
   (X winowのデスクトップOSでlocalhost接続でブラウザが起動する)

  $ jupyter notebook --ip=* --no-browser
   (別PCのブラウザで使う)
  
   python言語以外でも使おうと思えば、”!シェルスクリプト”で stdoutの結果が残せるのでいいかも。

■英文構文解析
 参考:https://qiita.com/krang/items/6e34c595ac77e46c3650
    pythonのnltkライブラリを使ってstanford parserを導入する

 java インストールを追加した。
 RUN apt install -y openjdk-17-jdk

 [構文解析]
 
 docker run  {scikit-learnデモ解凍ディレクトリ} に、
 
  https://stanfordnlp.github.io/CoreNLP/
  Stanford CoreNLP – Natural language software

  [Download CoreNLP 4.5.2] ボタンクリックしてダウンロードしたものを解凍する。
 その後、コンテナを起動する。

----- jupyter notebook -----
# In[1]:


from nltk.parse.stanford import *
# stanford corenlp ダウンロードしたディレクトリ(Docker内から見えるのもの)
JAR_FILE = "/home/pi/EXT/stanford-corenlp-4.5.2/stanford-corenlp-4.5.2.jar"
MODEL_FILE = "/home/pi/EXT/stanford-corenlp-4.5.2/stanford-corenlp-4.5.2-models.jar"
sentence = 'The brown fox is quick and he is jumping over the lazy dog.'
parser = StanfordParser(JAR_FILE,MODEL_FILE)
out = parser.raw_parse(sentence)
trees = list(out)


# In[2]:


from IPython.display import display, SVG, HTML
from nltk.tree import Tree, TreePrettyPrinter

print("英文解析のやり方=",len(trees))
tree = trees[0]
ctree = str(tree)
print("\n   --- キャラクタグラフィック ---")
tree.pretty_print()
print("\n   --- SVGグラフィック ---")
display(SVG(TreePrettyPrinter(Tree.fromstring(ctree)).svg()))
---- jupyter end ------------

   ====================================================
   JAVAで起動する stanfordnlpは、使い方に2種類の方法がある。
  上記のように解釈するたびに起動する方法とサーバーとして動作させる
  方法がある
  SVGの作成は、
  ①TreePrettyPrinter(Tree.fromstring(ctree)).svg()
  ②img = svgling.draw_tree(trees[0])
     svg_data = img.get_svg()
   パーサデータで木構造SVGを作るには, nltk, svglingで作成する2種類ある
   ====================================================

 [音声録音]

  音声で確認する。

 java インストールを追加した。
  ..
  # sound インストール
  RUN apt install -y alsa-utils
  RUN printf 'defaults.pcm.card 2\ndefaults.ctl.card 2\n' > /etc/asound.conf
  RUN apt install -y sox libsox-fmt-all
  ;;
  RUN pip3 install googletrans==4.0.0-rc1
  RUN pip3 install google_speech
  RUN echo 'rootdocker'| su - root -c "adduser pi audio"
  ..

  docker run に 、--privileged を指定する

-----jupyter notebook -----
# In[1]:


from googletrans import Translator

txt = input("英文を入力してください :")
''' 英語・日本語 翻訳'''
tr = Translator()
ja1 = tr.translate(txt, src="en", dest="ja")
print("\n翻訳結果:",end='')
print(txt,end='')
print(" ==> ",end='')
print(ja1.text)


# In[2]:


from google_speech import Speech
from IPython.display import display, HTML

''' 英文を読み上げます MP3ファイルで録音します '''
speech = Speech(txt, "en")
speech.play()
filn = "speech.mp3"
speech.save(filn)


# In[3]:


display(HTML("<audio controls src=\"speech.mp3\" type=\"audio/mp3\">英語発音</audio></br>"))
-----jupyter end -----


■scikit-learn インストール

  scikit-learn WEB ページに従って。

  https://scikit-learn.org ==>> Getting Started ==>> installation instructions ==>> 
      [Third party distributions of scikit-learn] . [Debian/Ubuntu]

  $ sudo apt install -y python3-sklearn python3-sklearn-lib

    https://stackoverflow.com/questions/35064304/runtimeerror-make-sure-the-graphviz-executables-are-on-your-systems-path-aft 
   「RuntimeError: Make sure the Graphviz executables are on your system's path" after installing Graphviz 2.38」
     より
    $ sudo apt install -y graphviz
       
    scikit-learnデモで使うものの追加
    $ pip3 install graphviz
    $ pip3 install pooch
    $ pip3 install plotly
    $ pip3 install annoy
    $ pip3 install nmslib
    $ pip3 install pooch
    $ pip3 install mlxtend
    $ sudo apt install python3-skimage

    グラフのタイトルに日本語を使う場合に、
    $ pip3 install japanize-matplotlib

    サンプルデモのページにあるように、examplesを始める前に必ずやること。
  $ pip3 install --upgrade scikit-learn

▶ sci kit learn 1.2.1 Examples

  https://scikit-learn.org/stable/auto_examples/index.html

  下にあるデータをダウンロードする。
    適当なディレクトリに解凍する。

●●●●● DOCKERインストール ●●●●● 
Dockerコンテナにインストールする

1. Dockerfile

---
# arm64/bullseye-skl/Dockerfile
FROM arm64v8/debian
MAINTAINER “K.Shimoura"
ENV container docker
ENV DEBIAN_FRONTEND noninteractive
#           SIGNAL=37
STOPSIGNAL SIGRTMIN+3
# root パスワード設定
RUN printf "rootdocker\nrootdocker\n"| passwd > /dev/null 2>&1
RUN apt update
# ロケール設定
RUN apt install -y locales locales-all
ENV LC_ALL ja_JP.UTF-8
ENV LANG ja_JP.UTF-8
ENV LANGUAGE ja_JP.UTF-8
ENV TZ Asia/Tokyo
RUN echo 'export LC_ALL="ja_JP.UTF-8"' >> /etc/profile
RUN echo 'export LANG="ja_JP.UTF-8"' >> /etc/profile
RUN echo 'export LANGUAGE="ja_JP:jp"' >> /etc/profile
RUN echo 'export TZ="Asia/Tokyo"' >> /etc/profile
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
# 1 ユーザ登録
# ユーザ作成
RUN echo "pi:pidocker:1000:1000:,,,:/home/pi:/bin/bash"|newusers
# ユーザ 設定
RUN cp -r /etc/skel/.[a-z]* /home/pi
RUN chown -R pi:pi /home/pi

# アプリケーションインストール
RUN apt install -y nano python3 python3-pip git
# jupyter-notebook インストール
RUN apt install -y jupyter-notebook
# scikit-learn インストール
RUN apt install -y python3-sklearn python3-sklearn-lib graphviz
RUN apt install -y python3-skimage
# java インストール
RUN apt install -y openjdk-17-jdk
# sound インストール
RUN apt install -y alsa-utils
RUN printf 'defaults.pcm.card 2\ndefaults.ctl.card 2\n' > /etc/asound.conf
RUN apt install -y sox libsox-fmt-all
# ユーザpiで実行
WORKDIR /home/pi
USER pi
# jupyter notebook 環境設定
RUN jupyter notebook --generate-config
RUN sed -i -e "s/# c.NotebookApp.open_browser.*$/c.NotebookApp.open_browser = False/" /home/pi/.jupyter/jupyter_notebook_config.py
RUN sed -i -e "s/# c.NotebookApp.ip.*$/c.NotebookApp.ip = '*'/"  /home/pi/.jupyter/jupyter_notebook_config.py
# jupyter notebook 環境設定 パスワード設定
#RUN pss=`shuf -i 1-239 -n 1`; echo "jupyter$pss" > /home/pi/.jupyter/pss.txt; \
#    echo "jupyter$pss"|python3 -c 'from notebook.auth import passwd;print("{\n  \"NotebookApp\": {\n    \"password\": \"",end=""); print(passwd(input()),end=""); print("\"\n  }\n}")' > /home/pi/.jupyter/jupyter_notebook_config.json; \
#    echo "";echo "jupyter notebookパスワード: jupyter$pss"; echo ""
RUN pss='skldocker'; echo "$pss" > /home/pi/.jupyter/pss.txt; \
    echo "$pss"|python3 -c 'from notebook.auth import passwd;print("{\n  \"NotebookApp\": {\n    \"password\": \"",end=""); print(passwd(input()),end=""); print("\"\n  }\n}")' > /home/pi/.jupyter/jupyter_notebook_config.json; \
    echo "";echo "jupyter notebookパスワード: $pss"; echo ""
RUN chmod 600 /home/pi/.jupyter/jupyter_notebook_config.json
RUN chmod 400 /home/pi/.jupyter/pss.txt

# scikit-learn python module インストール
RUN pip3 install numpy scipy matplotlib ipython pandas pillow graphviz mglearn
RUN pip3 install pooch plotly annoy nmslib pooch nltk spacy
RUN pip3 install japanize-matplotlib
RUN python3 -m spacy download en
RUN pip3 install --upgrade scikit-learn
RUN pip3 install mlxtend
RUN python3 -c "import nltk;nltk.download('all')"
RUN pip3 install googletrans==4.0.0-rc1
RUN pip3 install google_speech
RUN echo 'rootdocker'| su - root -c "adduser pi audio"
---
 jupyter-notebook パスワードは適当なものに修正すること。pss='skldocker' ==> pss='xxxx'。
 パスワードの確認は、コンテナ実行中に、
  docker ps
    docker exec {docker psでのコンテナID} cat /home/pi/.jupyter/pss.txt
  で表示できるように/home/pi/.jupter/pss.txtに書き込んでいる。
 jupyter-notebook 動作環境のうちで、IPアドレスは特に制限なし、ローカルブラウザは起動しないに設定している。
  (jupyter notebook --ip=* --no-browser と同じ)
 nltkがインストールされるのでnltkデータを全ダウンロードする。

2. build

 $ docker build -t arm64/bullseye-skl .

3. run

 $ docker run -ti --rm -v {scikit-learnデモ解凍ディレクトリ}:/home/pi/EXT -p 8888:8888 arm64/bllseye-skl bash -c "cd EXT;jupyter notebook;bash"

    bash -c の最後の bash はjupyter-notebookを終了してもコンテが実行終了しないように。
    HTTPポートは、-p 8888:8888 の -p {他のポートとかさならないポート番号}:8888 に修正すること。

    コンテナ実行前に
  https://scikit-learn.org/stable/auto_examples/index.html WEBページ下にあるjupyter-notebook用のzipファイルを
    {scikit-learnデモ解凍ディレクトリ}に解凍しておく。

4. scikit-learn,pythonを使うには他のPCのブラウザから

 他のPCのブラウザで、
  http://{IPアドレス}:8888
  で使う。

 使ったプログラムとデータは、コンテナ外の{scikit-learnデモ解凍ディレクトリ}に残る。

5. パッケージ、モジュールが足りない場合

  docker ps

    apt install する場合、
     docker exec -ti -u root コンテナID bash

    pip3 install する場合、
     docker exec -ti コンテナID bash

    カレントディレクトリが /home/pi/EXT になっているので注意する。
  パッケージ、モジュールを追加した場合、その他のメモリを修正した場合はコンテナ終了でなくなるので
  残したい場合は必ず docker commit すること。
  commitする前にjupyter-notebookは終わらせておいたほうがいいかもしれない。

参照:https://qiita.com/alchemist/items/ce7f6790bdc2c7cee674
   投稿日 2019年06月22日 更新日 2019年06月22日
   2019年版 リモートサーバでJupyter Notebookを実行する方法


######## 以下は参考資料 ##########################

モジュールが日々アップデートされているのでインストールし直した時、思わぬところでエラーが出る場合がある。

pandas.plotでは、タイトルに日本語があると文字ばけする場合、

1) OSにインストールされているフォントファミリーを確認

 $ fc-list -f "%{family}\n"
  ..
    ::
  IPA Pゴシック,IPAPGothic
  Takao Pゴシック,TakaoPGothic
  IPA P明朝,IPAPMincho
  IPAゴシック,IPAGothic
  Takao P明朝,TakaoPMincho
  Takao Pゴシック,TakaoPGothic
  Takao明朝,TakaoMincho
  Takao P明朝,TakaoPMincho
  Takaoゴシック,TakaoGothic
    ::
  ..

2) 日本語フォントが見つからない場合
 fonts-takaoか fonts-ipafontをインストールする。

3) matplotlibにフォントを選択する

  ---python code--
  import matplotlib
  #matplotlib.rc('font', family='TakaoPMincho')
  matplotlib.rc('font', family='IPAGothic')

  または
 import matplotlib.pyplot as plt
  plt.rcParams['font.family'] = 'IPAGothic"

 または、
 import matplotlib.pyplot as plt
 import japanize_matplotlib


4) それでも文字化け

 $ ls ~/.cache/matplotlib
    fontlist-v330.json 表示されたjsonファイル削除
  $ rm ~/.cache/matplotlib/fontlist-v330.json

 Jupyter notebook カーネル再起動

======================

▶ sci kit learn 1.2.0 Examples
  https://scikit-learn.org/stable/auto_examples/index.html

  下にあるデータをダウンロードする。
  動かないのは2,3個なのでscikit learn元にあるのが一番かな。

    $ sudo apt install python3-skimage
    $ pip3 install pooch
    $ pip3 install plotly
    $ pip3 install annoy
    $ pip3 install nmslib
    $ pip3 install pooch

▶オライリー
 「Pythonではじめる機械学習」 
...

  github からサンプルダウンロード

 $ git clone  https://github.com/amueller/introduction_to_ml_with_python.git

ダウンロードしたサンプルプログラムが実行できる。
そのままでは bostonデータ を使うことができない。
bostonデータ以外では、結果がずれているのがある。

①load_boston() でエラーとなる。load_boston() 自分用に作る。
  load_boston()は上記のように。 

def plot_learning_curve(est, X, y):
    training_set_size, train_scores, test_scores = learning_curve(
        est, X, y, train_sizes=np.linspace(.1, 1, 20), cv=KFold(20, shuffle=True, random_state=1))
    estimator_name = est.__class__.__name__
    line = plt.plot(training_set_size, train_scores.mean(axis=1), '--',
                    label="training " + estimator_name)
    plt.plot(training_set_size, test_scores.mean(axis=1), '-',
             label="test " + estimator_name, c=line[0].get_color())
    plt.xlabel('Training set size')
    plt.ylabel('Score (R^2)')
    plt.ylim(0, 1.1)

def load_boston_extended():
    boston = load_boston()
    X = boston.data

    X = MinMaxScaler().fit_transform(boston.data)
    X = PolynomialFeatures(degree=2, include_bias=False).fit_transform(X)
    return X, boston.target

def plot_ridge_n_samples():
    X, y = load_boston_extended()

    plot_learning_curve(Ridge(alpha=1), X, y)
    plot_learning_curve(LinearRegression(), X, y)
    plt.legend(loc=(0, 1.05), ncol=2, fontsize=11)
....
実行sklearnディレクトリに。
./load_boston.py

使う時、
---------source----
import load_boston

boston = load_boston.load_boston()
X, y = load_boston.load_boston_extended()
-------------------
あとは、import load_boston でエラーが出たらコメントにする。

②エラーになる。

$ nano preamble.py
---
from mglearn import plot_helpers <<==追加
import mglearn
from cycler import cycler

set_matplotlib_formats('pdf', 'png')
plt.rcParams['savefig.dpi'] = 300
plt.rcParams['image.cmap'] = "viridis"
plt.rcParams['image.interpolation'] = "none"
plt.rcParams['savefig.bbox'] = "tight"
plt.rcParams['lines.linewidth'] = 2
plt.rcParams['legend.numpoints'] = 1
plt.rc('axes', prop_cycle=(
    cycler('color', plot_helpers.cm_cycle.colors) +                      <<==修正
    cycler('linestyle', ['-', '-', "--", (0, (3, 3)), (0, (1.5, 1.5))])))
...修正

3章のサンプル実行で写真の色がでないのがあるのでこの修正では足りない。

③memoryでエラーになる。

$ nano ~/.local/lib/python3.9/site-packages/mglearn/plot_nmf.py
---
#memory = Memory(cachedir="cache")
memory = Memory("cachedir")
---修正
$ nano ~/.local/lib/python3.9/site-packages/mglearn/plot_pca.py
---
memory = Memory("cachedir")
--- 修正

④その他
$ nano ~/.local/lib/python3.9/site-packages/mglearn/datasets.py
---
#from sklearn.datasets import load_boston
;;
#from .make_blobs import make_blobs
from sklearn.datasets import make_blobs
::
def make_forge():
    # a carefully hand-designed dataset lol
    X, y = make_blobs(centers=2, random_state=4, n_samples=30)
    y[np.array([7, 27])] = 0
    mask = np.ones(len(X), dtype=bool) <<==np.bool修正
    mask[np.array([0, 1, 5, 26])] = 0
    X, y = X[mask], y[mask]
    return X, y

---修正
同様に

$ nano  ~/.local/lib/python3.9/site-packages/mglearn/tools.py
---
def make_handcrafted_dataset():
    # a carefully hand-designed dataset lol
    X, y = make_blobs(centers=2, random_state=4, n_samples=30)
    y[np.array([7, 27])] = 0
    mask = np.ones(len(X), dtype=bool)  <<===
    mask[np.array([0, 1, 5, 26])] = 0
    X, y = X[mask], y[mask]
    return X, y
---修正

$ nano ~/.local/lib/python3.9/site-packages/mlxtend/evaluate/holdout.py
---
    def split(self, X, y, groups=None):
---も同様に修正する。

編集:03-unsupervised-learning.ipynb

IN[24] mask = np.zeros(people.target.shape, dtype=bool)
..
(★3Dグラフがかけない。)
(★顔写真が黒くなる。)

編集:04-unsupervised-learning.ipynb

IN[14]  print(ohe.get_feature_names_out())
IN[35]  print("Polynomial feature names:\n{}".format(poly.get_feature_names_out()))
IN[38]  print("Polynomial feature names:\n{}".format(poly.get_feature_names_out()))
IN[71]  features_poly = poly_transformer.get_feature_names_out(features)

..

★★:05-unsupervised-learning.ipynb

IN[24]  mglearn.plots.plot_cross_val_selection()
でエラーになる。(??)

★★:06-unsupervised-learning.ipynb

OUT[27]  結果数値が一致しない。

編集:07-unsupervised-learning.ipynb

IN[16]  feature_names = vect.get_feature_names_out()
IN[21]  feature_names = vect.get_feature_names_out()

他の.get_feature_namesも、.get_feature_names_outに修正する。
..

★★:07-unsupervised-learning.ipynb

IN[35]  pipe = make_pipeline(TfidfVectorizer(min_df=5), LogisticRegression())
        ::
        :: の欄で中断する。


▶秀和システム
 scikit-learn データ分析 実装ハンドブック
...
モジュールgoogle以外はない時pip3 installする。

load_bostonでエラーになるので、「PYTHONではじめる機械学習」で使ったファイルを、
実行ディレクトリに、data, descrを作成し、ファイルをコピー。
./data/boston_house_prices.csv
./descr/boston_house_prices.rst
./load_boston.py

使う時の直前で、
ーーーーーーーー
import os
import sys
import subprocess
s = subprocess.check_output("pwd")

sys.path.append(os.path.join(s.decode('utf-8').replace("\n", ""), '..'))

#print(s.decode('utf-8').replace("\n", ""))
import pprint
pprint.pprint(sys.path)
ーーーーーーーーーを実行する。
使うところで、
---------source----
import load_boston
boston = load_boston.load_boston()
にする。

section3_4_1.ipynb  確率的勾配降下法の回帰モデルを作成 でエラー。
section3_7_1.ipynb  決定木回帰のモデルを作成 でエラー。
section3_7_2.ipynb  ランダムフォレスト回帰のモデルを作成 でエラー。
section4_4_1.ipynb  最初のグラフがでない。
                      訓練データのプロットの 前に %matplotlib inline、あとにplt.show()。 
section4_4_2.ipynb
                      訓練データのプロットの 前に %matplotlib inline、あとにplt.show()。 
section4_5_1.ipynb    google.colab がないのでエラー。

8章はプログラムがない。

▶seaborn 徹底入門!Pythonを使って手軽で綺麗なデータ可視化8連発
https://www.codexa.net/seaborn-python/
(きれいなグラフが書ける)

$pip3 install seaborn
--
#sns.distplotでヒストグラムを描く
sns.displot(df['age'], kde=True)
#確率密度関数を除き、ヒストグラムのみを描く
sns.histplot(df['age'])
--

★注意
~/.local/lib/python3.9/site-packages/mglearn/ ディレクトリはpip3 install mglearnを実行した場合
なしのときは、introduction_to_ml_with_python/mglearnにある。
エラー表示のファイルパスをよくみること。
---------------------------------
markdown
  行先頭改行1個と次の行4空白(tabキー)+テキスト、それ以降のHTML文字コードはエスケープ文字にしてくれる
 その後は4空白+テキストもHTML文字コードはエスケープ文字にしてくれる
 zip, pdfファイルを貼るときは,行先頭改行1個と次の行4空白でなければ、「<a href='./test.pdf'>test</a>」HTML Aタグコーディングすれば良い。
2024-11-19 「Raspberry pi OS」
□□□□□□□□□□□
2024-11-19 現在
UPDATE 2024-11-13 OS イメージ
/etc/rc.localがなくなっている。rc-localサービスもSTOPしている。

参考:https://www.cyberciti.biz/faq/how-to-enable-rc-local-shell-script-on-systemd-while-booting-linux-system/
   How to enable rc.local shell script on systemd while booting Linux system

必要な場合は、
---- /etc/rc.local ----
#!/bin/sh -e
実行コマンドライン
exit 0
----
作成して、
$ sudo chmod +x /etc/rc.local
$ sudo systemctl restart rc-local

□□□□□□□□□□□
2024-10-29 現在
Raspberry pi Imagerがアップデートされている。
以前のバージョンを使ったあとは使いにくくなっている。rasbian full インストールイメージが選択できない。

2024-11-05 現在
●2024-10-22 DSKTOPイメージ
ファイルマネージャでファイルを移動、コピーしようとしてファイルのアイコンがカーソルに表示され、動作が未完だとカーソルにアイコンがついたままになる。

Rasbian OS Imagerから環境設定(パスワード、ロケール等)するとMozcがインストールされない。
ロケール設定のようにならない。
Rasbian OS Imagerからイメージコピーだけで、起動時にロケール設定が簡単。
chromium-l10nがインストールされない。
Waylandのchromiumはまだオプションなしでは日本語入力ができない。

参照:https://qiita.com/aratetsu_sp2/items/6bd89e5959ba54ede391
   Bookworm (Raspberry Pi OS)のChromiumで日本語入力できない現象について
Waylandのままで、
 案4 chromium-viewer --gtk-version=4 
を使う。

その前にmozcを apt remove で fcitx とつくものを全部削除。

 参照:https://gihyo.jp/admin/serial/01/ubuntu-recipe/0689
    Ubuntu 21.10でFcitx 5を使用する
 より、
  $ sudo apt install fcitx5-mozc kde-config-fcitx5
  $ im-config -n fcitx5
  $ sudo reboot
 fctix5-mozcにする。

Wayland かどうかを調べるには、
$ echo $XDG_SESSION_TYPE
でwaylandとなっている。

☆2024-07-04 bookworm Desktop イメージ
fcitx-mozcが自動インストールされた。
メニューからのOSセットアップでリモートデスクトップのセレクタボタンが追加になった。
apt updateすれば追加されている。(使う機会は今はない)
chromium-browserは日本語入力はまだできない。chromiumにすればよい。

□□□□□□□□□□□
☆2024-03-15 bookworm Desktop イメージ
$ sudo apt remove -y --purge chromium-browser
$ sudo apt remove -y --purge chromium-codecs-ffmpeg-extra
$ sudo apt install -y chromium
$ sudo apt install -y chromium-l10n
バージョアップされた。arm32 chromium バージョン: 125.0.6422.112
一時、chromium-l10nがインストールできなかったができるようになった。
Wayland で日本語入力ができるようになる。

fcitx-mozcが自動インストールされない。

☆2024-03-12 bookworm Desktop イメージ
chromium バージョン: 123.0.6312.86 にするとWayland で日本語入力ができるようになる。
いいことだ。Raspberry pi設定でブラウザの選択ができなくなっている。
スクリーンショットはgrimがインストールされている。キーprint screenでスクリーンショットされる。
slurp もインストールするとマウスで範囲指定するとその範囲がスクリーンショットされる。
fcitx-mozcが自動インストールされない。

☆2023-12-05 bookworm Desktop イメージ
raspi-configでWaylandを無効にすると、タスクバーにあるシステムアップデートアイコンに表示されるメセージが英語になる。
Waylandでは、日本語表示。

☆2023-10-10 bookworm Desktop イメージ
アクセサリimager がUPDATEされている。
機種から選択すると64ビットOSが奥の方になった。
説明書を読む人が少ないのかな?

apt updateでワーニングが出ることがある。
参考:https://github.com/MichaIng/DietPi/issues/6463
   Bookworm | Mirror warnings #6463
対処方法がある。11-5現在では出ていない。

☆2023-10-10 arm32 bookworm Desktop イメージ
初回の起動OSセットアップで日本語キーボードにし、その後、raspi-configでWaylandを無効にすると、キーボードがUS配列になる。
いくら設定し直してもだめである。設定を確認しても日本語になっているのになぜ???
(通常はUS配列のキーボードを使っているのでわからなかった)
raspi-configでWaylandを有効にし直すと正常になる。

☆2023-10-10 arm64 bookworm Desktop イメージ
ブラウザが,Chromium,firefox 選択可能になっている。
Chromium バージョン: 116.0.5845.102
検索入力フィールドに日本語入力ができない。なぜ?

参照:https://qiita.com/aratetsu_sp2/items/6bd89e5959ba54ede391
   Bookworm (Raspberry Pi OS)のChromiumで日本語入力できない現象について

RaspberryPi 4Bで、
chromium-viewer --ozone-platform=x11ではブラウザは開かない。
chromium-browser --ozone-platform=x11 では入力できない。
raspi-configでWaylandを無効にし、reboot後は入力できる。
Wifi 2.4Ghzの接続がよくなったような気がする。

Rasberry pi 3Bは64ビットOSで入力できる。ディスプレイのブランク黒表示は初期設定がオン。

・・・
Desktop画面がチカとフラッシュする。ディスプレイとかの環境によるかも?
OS フルバージョンはoffice,Mathematica, KiCAD付き。

ディスプレイのブランク黒表示は設定がオフなのでRaspberry Piの設定でディスプレイの画面のブランクでオン設定する。
固定IPアドレスの設定方法が変わった。

「Bookworm 固定IPアドレス設定方法」
◆方法1
タスクバーのネットワークアイコンをクリック。下のAdvanced Options選択。
「接続を編集する」でデバイスを選択して”歯車”クリック。
IPV4設定タグより、「固定IPアドレス」、「ネットマスクビット数」、「ゲートウェイ」、「DNSサーバー」
を設定。

◆方法2
参照:
https://itslinuxfoss.com/set-up-static-ip-address-debian-12-linux/
How to Set Up a Static IP Address on Debian 12 Linux
(Method2より)

(1)ネットワークデバイス接続、UUID確認

$ nmcli con show
NAME        UUID                                  TYPE      DEVICE 
有線接続 1  xxxxxxxx-e9e7-3d7e-xxxx-xxxxxxxxxxxx  ethernet  eth0   
lo         xxxxxxxx-ae5c-4d17-xxxx-xxxxxxxxxxxx  loopback  lo

(2)固定IPアドレス設定

$ sudo nmcli con mod "有線接続 1" ipv4.addresses 192.168.1.xx/24 ipv4.gateway 192.168.1.1 ipv4.dns 192.168.1.1 ipv4.method manual

(4) NetworkManager再起動

$ sudo systemctl restart NetworkManager

□□□□□□□□□□□
☆2023-05-03 bullseye Desktop イメージ
最近使わないので気が付かなかったが、bullseyeでは omxplayerがインストールされていないのに気がついた。
legacy(buster)イメージに残っている。

☆2023-05-03 arm64 bullseye Desktop イメージ
ファイルマネージャの表示とか、その他のデスクトップ表示が少し早くなった。
☆2023-02-21 イメージ
Kernel 2回めアップデートで Desktopで設定 ディスプレイ・画面のブランクが動作するようになった。
KiCadがおすすめになった。
☆2022-09-22 arm64 bullseye Desktop イメージ
最初のOS初期設定で日本を選択後、LAN接続してOSアップデートの正常終了し、リブートすると
日本語入力メソッドがfcitx-mozcインストールされる。
初のOS初期設定で日本を選択後、LAN接続してOSアップデートをしないとmozcがインストールされない。
気が付かなかった。

bullseye 32,62ビットOSのChromiumブラウザがtextarea項目にテキストをペーストし、ボタンクリックするとjavascriptに制御がうつる前に
プログラムが異常終了することがある。textareaがあるHTMLだけではないのかもしれないが。
32ビットbusterではなんともないのだけど。

2023-02-11現在。 docker make の表示が変わった。

□□□□□□□□□□□
2022-09-22 arm32 buster legacy Desktop パッケージイメージ

chromium-l10n言語パッケージを追加する。
PI-TOP V2用の電源管理・スピーカ出力モジュールを使用する場合、apt pt-hub。
sudo apt install nftables インストール。
apt pt-hubインストールしたせいかもしれないが、ファイルマネージャが固まることがある。

□□□□□□□□□□□
☆2022-09-06 arm64 bullseye Desktop イメージ

Raspberry pi 7インチディスプレイの接続は、
.....................................
参照:https://osoyoo.com/ja/2019/09/20/instruction-for-raspberry-pi-5-dsi-touch-screen/#:~:text=LCD%E3%83%87%E3%82%A3%E3%82%B9%E3%83%97%E3%83%AC%E3%82%A4%E3%81%AE%E7%89%A9%E7%90%86%E8%A7%A3%E5%83%8F%E5%BA%A6%E3%81%AF800%C3%97480%E3%81%A7%E3%81%99%E3%80%82
  Raspberry Pi 5 “DSIタッチスクリーン取扱説明書(osoyoo)
を参考に修正する。

$ sudo nano /boot/config.txt
---
#dtoverlay=cv4-fkms-V3D   <<== dtoverlay=cv4-fkms-V3Dをすべてコメントにする

framebuffer_width=1200    <<== 画面大きさ
framebuffer_height=720    <<== 画面大きさ
lcd_rotate=2              <<== 回転
---
 lcd_rotate=2はdtoverlay=cv4-fkms-V3Dをコメントにしないと有効にならない。
 framebuffer_width, framebuffer_heightを指定すると800x480のドット数が変わる。

メールクライアントがないとき。

$ sudo apt install claws-mail

VNCクライアントがないとき。

$ sudo apt install realvnc-vnc-viewer

$ sudo apt install libreoffice
で中身がインストールされる。

iptablesが外れた。nftablesになった。systemctlで制御。
sudo apt install iptables でインストールして、iptables コマンドを実行するとnftablesに変換してくれる。

ファイルマネージャはよくなってるが、マウス右クリック コピー、マウス右クリック ペーストがちょっと仕様が変わった。

HDMIの画面の回転、サイズ変更はメインメニュー・Screen Configurationで行う。(xrandr)
.........................
コマンドラインで行うには、
回転: xrandr --output HDMI-1 --rotate right
サイズ変更(--scale): xrandr --output HDMI-1 --scale 0.7x0.7 (0.7は画素数が少なくなる)

◎コマンドを自分だけの自動実行にするには、

mkdir ~/.config/autostart
nano ~/.config/autostart/wrotate.desktop
---
[Desktop Entry]
Type=Application
Name=MyDeskTop 
Exec=/home/pi/rotate.sh
--- 作成
nano ~/rotate.sh
---
#!/bin/sh
sleep 2
xrandr --output HDMI-1 --rotate right
xrandr --output HDMI-1 --scale 0.7x0.7
---作成
chmod +x rotate.sh

◎コマンドを全USERの自動実行にするには、

sudo nano /etc/xdg/autostart/mydesktop.desktop
---
[Desktop Entry]
Type=Application
Name=MyDeskTopALL 
Exec=/home/pi/rotate.sh
--- 作成
実行スクリプトは上記と同じ。

メインメニュー・Main Menu Editor -> 設定 -> Desktop Session Settings(lxsession-edit)にチェックを入れる。
メインメニュー・Desktop Session Settings で[Desktop Entry]のNameで指定した名前にチェックが入ってるかを確認する。◎コマンドを自分だけの自動実行か、◎コマンドを全USERの自動実行するかのどちらかを選ぶ。
[wscreen4b.png]

[raspberry-4b.jpg]
2022-08-24 「SONY Xperia Ace III SO-53C MTP接続」
https://appex.blog.fc2.com/blog-entry-64.html
Linux mint 17でのXperia XPのMTP認識
より

スマホをUSB接続(手順は選択しない)

$ lsusb
 SO-53C USB IDをメモする
 > Bus 001 Device 004: ID 0fce:020e Sony Ericsson Mobile Communications AB SO-53C

$ sudo nano /lib/udev/rules.d/69-libmtp.rules
 SONY IDでサーチ
 似たデバイスの行をコピーする
 SO-53C USB IDに修正する
 > # SONY Xperia Ace III (SO-53C)
 > ATTR{idVendor}=="0fce", ATTR{idProduct}=="020e", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"

または、
「ATTR{idVendor}=="0fce", ATTR{idProduct}=="020e", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"」
を内容として、

$ sudo nano /etc/udev/rules.d/69-libmtp.rules
 で69-libmtp.rulesファイルを作成してもよい

USBケーブルを抜く

$ sudo reboot

スマホをUSB接続し、スマホ側でUSBファイル転送にする

rasberry pi側で、リムーバブルメディア接続のウィンドウが開くのでOKをクリック
このときエラーがでる(まだ対応は調査していない、無視する)
SO-53Cディレクトリを右クリックして”ボリュームマウントを解除する”を選択
もう一度、右クリックして”ボリュームマウントする”をクリックする
内部、SDカードが表示される

それでも 「the name :n.nnnn was not provided by any .service files」メッセージが出るときは、
( https://askubuntu.com/questions/1357359/gnome-software-sorry-something-went-wrong-the-name-n-nnnn-was-not-provided-b
 より)

$ sudo apt install --reinstall gnome-software
$ reboot
2021-12-31 「GITコマンド」
[git-cmd02.png]
GITWEBインストール

$ sudo apt install apache2
$ sudo apt install gitweb
$ sudo a2enmod cgi
$ sudo adduser git 
          パスワード:gitdocker 

$ sudo mkdir /home/git/repositories
$ sudo chown git:git /home/git/repositories
$ sudo usermod -a -G git www-data

$ sudo nano /etc/gitweb.conf
---
$projectroot = "/home/git/repositories";

$git_temp = "/tmp";

$home_link = $my_uri || "/";

$projects_list = $projectroot;

$home_link_str = "MY GIT";
$site_name = "MyGitServer WEB";
$feature{'snapshot'}{'default'} = ['zip'];
---修正

$ sudo service apache2 restart

$ ssh git@192.168.1.xx 'cd repositories;git init --bare --share project.git;echo "トラプロジェクト" > project.git/description'

$ git clone ssh://git@192.168.1.xx:/home/git/repositories/project.git
$ cd project
$ nano README.txt
$ git add .
$ git commit -m "init"
$ git push

 http://192.168.1.xx/gitweb  ブラウザでprojectが表示されることを確認

RAWテキスト表示の文字化け対策
$ sudo nano  /usr/lib/cgi-bin/gitweb.cgi
--
our $default_text_plain_charset  = 'utf-8'; <<== 修正
--
2021-09-24 「(A+B)**N の式展開」
ちょっと体操2。
(A+B)**N の数式を展開する。

nano cal_e1.py
----
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
c = [1]
d = [0] * 20

print("(A+B)**N の式展開")
print("N - in:",end="")
N = int(input().strip())
if N > 15:
  N = 15
if N < 1:
  N = 1
for k in range(N+1):
  d[0] = 1
  for i in range(k+1):
    if i < k:
      if i > 0:
        d[i] = c[i-1] + c[i]
    else:
      d[i] = 1

  c = d[:]

h = N // 2
print("(A+B)**%d = " % (N), end="")
for k in range(N+1):
  if k == 0:
    print("A**%d + " % N,end="")
  elif k == N:
    print("B**%d\n" % N)
  elif k < h:
    print("%dA**%dB**%d + " % (d[k],N-k, k),end="")
  elif k <= h and (N & 1) == 0:
    print("%dA**%dB**%d + " % (d[k],k, k),end="")
  else:
    print("%dA**%dB**%d + " % (d[k],N-k, N-(N-k)),end="")
-----
python3 cal_e1.py
.....
(A+B)**N の式展開
N - in:6
(A+B)**6 = A**6 + 6A**5B**1 + 15A**4B**2 + 20A**3B**3 + 15A**2B**4 + 6A**1B**5 + B**6
2021-08-23 「連分数」
ちょっと体操。
πとeの計算。

$ nano bun11.py
---
from decimal import *
getcontext().prec = 120

print("=== PI ===")
print("in:",end="")
N = int(input().strip())

tmp = Decimal(0)
for x in range(N, 0, -1):
  tmp = Decimal(x * x) / (Decimal( 2 * x + 1 )  + tmp)

pi1000 = '3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461284756482337867831652712019091456485669234603486104543266482133936072602491412737245870066063155881748815209209628292540917153643678925903600113305305488204665213841469519415116094330572703657595919530921861173819326117931051185480744623799627495673518857527248912279381830119491298336733624406566430860213949463952247371907021798609437027705392171762931767523846748184676694051320005681271452635608277857713427577896091736371787214684409012249534301465495853710507922796892589235420199561121290219608640344181598136297747713099605187072113499999983729780499510597317328160963185950244594553469083026425223082533446850352619311881710100031378387528865875332083814206171776691473035982534904287554687311595628638823537875937519577818577805321712268066130019278766111959092164201989'
print(pi1000[:121])
print(Decimal(4.0) /(Decimal(1.0) + tmp))

print("=== e ===")
print("in:",end="")
N = int(input().strip())

tmp = Decimal(N + 1)
for x in range(N, 0, -1):
  tmp = Decimal(x) + (Decimal(x) / tmp)

e1000 =  '2.718281828459045235360287471352662497757247093699959574966967627724076630353547594571382178525166427427466391932003059921817413596629043572900334295260595630738132328627943490763233829880753195251019011573834187930702154089149934884167509244761460668082264800168477411853742345442437107539077744992069551702761838606261331384583000752044933826560297606737113200709328709127443747047230696977209310141692836819025515108657463772111252389784425056953696770785449969967946864454905987931636889230098793127736178215424999229576351482208269895193668033182528869398496465105820939239829488793320362509443117301238197068416140397019837679320683282376464804295311802328782509819455815301756717361332069811250996181881593041690351598888519345807273866738589422879228499892086805825749279610484198444363463244968487560233624827041978623209002160990235304369941849146314093431738143640546253152096183690888707016768396424378140592714563549061303107208510383750510115747704171898610687396965521267154688957035035'
print(e1000[:121])
print(Decimal(2.0) + Decimal(1.0) / tmp)
----
$ python3 bun11.py
=== PI ===
in:155
3.14159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664
3.14159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664
=== e ===
in:77
2.71828182845904523536028747135266249775724709369995957496696762772407663035354759457138217852516642742746639193200305992
2.71828182845904523536028747135266249775724709369995957496696762772407663035354759457138217852516642742746639193200305992
.....................................

ブルーバックス 「アメリカ流 7歳からの微分積分」 ドナルドコーエン 新井紀子訳
”The Mathman”
http://mathman.biz/home.html

図:ブルーバックス 「アメリカ流 7歳からの微分積分」 ドナルドコーエン 新井紀子訳 より
[calc-pai-e.jpg]
2021-07-02「ジャクソン構造図」
USP MAGAZINE 2012 autumn号の「やわらかマッド~ はじめてのソフトウェア工学 第3回」を見て言語の構文解析に使えないかとヒラメキがあって興味を持った。
ジャクソン構造図はデータ構造中心でプログラムを作るものなので、言語の構文解析にも似ているかなとひらめいた。
これを使えばもっとまともな文章がひょっとしたらできるかも。

USP MAGAZINEにあったCSVファイルをやってみた。
処理中心な方向になってしまう。
[csv6.png]

参考:
(1) USP MAGAZINE Vol.5   - 2012.6月発行

 やわらかマッド~ はじめてのソフトウェア工学 第2回

(2) USP MAGAZINE 2012 autumn  - 2012.9月発行

 やわらかマッド~ はじめてのソフトウェア工学 第3回

(3) Michael A. Jackson『構造的プログラム設計の原理』鳥居 宏次(訳)、日本コンピュータ協会、1980年。

(4) Michael Jackson『システム開発 ーJSD法ー』大野侚郎,山崎 利治(監訳)、共立出版株式会社、1989年。

JSPエディタ:
 スウェーデン シェブデ大学
 https://www.his.se/en/about-us/staff/henrik.engstrom/jsp-editor/

 Windows users
  Download the following file: jsp3.2.exe 

  JAVA
  Download the following file: jsp3_2.jar

JAVA用をダウンロードする
使い方
$ sudo apt install openjdk-11-jdk

$ java -jar jsp3_2.jar

 メニューからcで生成するとソースプログラムができる
 これをPython3用に書き換える

エラー1は、 ”文字列" で終わりのダブルクォテーションがない時。
エラー2は、項目区切り文字カンマ、改行、EOFでない時。
エラー3は、文字に制御コードがあった時。

$ nano csv.py
-----
'''
int main()
{
   /* Operation EOF=0 */
   /* Operation レコード='' */
   /* Operation get1c() */
   while (!EOF){
      while (c!=改行 and !EOF){
         /* Operation item='' */
         while (c==' ')
            /* Operation Get1c() */
         if (c=='"'){
            /* Operation Get1c() */
            while (not EOF)
               if (c=='"'){
                  /* Operation Get1c() */
                  if (c=='"'){
                     /* Operation Get1c() */
                     /* Operation 文字”item追加 */
                  }
                  else 
                     /* Operation Break */
               }
               else {
                  /* Operation 文字編集 */
                  /* Operation Get1c() */
               }
            if (EOF)
               /* Operation exit(1) */
            else 
               /* ー */
         }
         else 
            while (c!=',' and c!=改行 and !EOF){
               if (c>' ')
                  /* Operation item文字追加 */
               else 
                  /* Operation exit(1) */
               /* Operation Get1c() */
            }
         {
         if (item=='')
            /* ’_’レコード追加 */
         else 
            /* Itemレコード追加 */
         if (c==','){
            /* Operation Get1c() */
            /* Operation 空白区切り追加 */
         }
         else if (c==改行 or EOF)
            /* Operation break */
         else 
            /* Operation exit(1) */
         if (EOF or c==改行)
            /* Operation '_'レコード追加 */
         else 
            /* ー */
         }
      }
      {
      /* Operation Printレコード */
      if (c==改行)
         /* Operation Get1c() */
      else 
         /* EOF */
      }
   }
}
'''
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import sys

EOF = 0

def getchar():
  global EOF
  c = sys.stdin.read(1)
  if len(c) == 0:
    EOF = 1
    c = ''
  return c

def main():
   global EOF
   EOF = 0
   record_s = ''
   c = getchar()
   while not EOF: 
      while c!='\x0a' and not EOF:
         item=''
         while c==' ':        # 空白削除
            c = getchar()
         if c=='"':           # "~~~~~~"
            c = getchar()
            while not EOF:
               if c=='"':     # " "" で ”1文字
                  c = getchar()
                  if c=='"':
                     c = getchar()
                     item += '"'
                  else:
                     break     # "~~~~~~" の ”終
               else:
                  item += c    # "xxxxxx" の 文字部分
                  c = getchar()
            if EOF:
               print("?Error:1> Nothing End of '\"'\n---")
               print(item)
               print("---")               
               sys.exit(1)
            else:
               pass
         else: 
            while c!=',' and c!='\x0a' and not EOF:
               if c>' ':
                  item += c    # xxxxxx の 文字部分
               else:           # 制御文字
                  print("?Error:3> Invalid Code\n---")
                  print(item)
                  print("---")               
                  sys.exit(1)   
               c = getchar()
         if item=='':               # 項目確定  
            record_s += '_'         # Null文字
         else: 
            record_s += item        # 項目セット
         if c==',':                 # 項目区切り文字 カンマ
            c = getchar()
            record_s += ' '         # 項目区切り空白セット
         elif c=='\x0a' or EOF:     # 項目区切り文字 改行 or EOF
            break
         else:                      # 項目区切り文字 カンマ、改行、EOF 以外
            print("?Error:2> Nothing Separator ','\n---")
            print(item)
            print("---")
            sys.exit(1)
         if c=='\x0a' or EOF:       # 項目区切り文字 カンマの後の文字チェック
            record_s += '_'
      print(record_s)               # Printレコード
      record_s = ''
      if c=='\x0a':            # 1行区切り文字 改行 
         c = getchar()
      else:                    # 1行区切り文字 EOF
         pass

if __name__ == "__main__":
   main()
---
$ nano Book1.csv
---
a,b,c
1,2,3
"""","""""",""""""""
"""a""","""b""","""c"""
"あ
い
う",い,う
,,
,,abc
,,[EOF]
---
$ python3 csv.py < Book1.csv
...
pi@r0529rtop:~/mnt/jsp-edit $ python3 csv6.py < Book1.csv
a b c
1 2 3
" "" """
"a" "b" "c"
あ
い
う い う
_ _ _
_ _ abc
_ _ _
2021-06-13「stanford coreNLP」
Stanford CoreNLPのインストール

参考:CoreNLP を使ってみる(1)
   https://lab.astamuse.co.jp/entry/corenlp1

1)環境
 Raspberry pi 4B 8GB
 Rasbian 2021-05-07 Desktopイメージ

2)JAVAインストール
$ sudo apt install openjdk-11-jdk

 Desktopイメージではすでにインストール済。

3)Stanford CoreNLPダウンロード
 https://stanfordnlp.github.io/CoreNLP/
 「Download CoreNLP 4.2.2]ボタンでZIPファイルダウンロード4

4)解凍
 解凍して
 $ cd stanford-corenlp-4.2.2

5)corenlp.sh修正

 echo java -mx2800m -cp \"$scriptdir/*\" edu.stanford.nlp.pipeline.StanfordCoreNLP $*
 java -mx2800m -cp "$scriptdir/*" edu.stanford.nlp.pipeline.StanfordCoreNLP $*
 --
  -mx5g を -mx2800m に変更。環境によってはメモリの大きさが違うのでなるべく大きいあたいにすること。

6)センテンスパース結果の表示
  パース結果がほしいので -annotators tokenize,ssplit,parse を指定。

 $ ./corenlp.sh  -annotators tokenize,ssplit,parse
 ...
 NLP> Stanford University is located in California. It is a great university, founded in 1891.

 Sentence #1 (7 tokens):
 Stanford University is located in California.

 Tokens:
 [Text=Stanford CharacterOffsetBegin=0 CharacterOffsetEnd=8 PartOfSpeech=NNP]
 [Text=University CharacterOffsetBegin=9 CharacterOffsetEnd=19 PartOfSpeech=NNP]
 [Text=is CharacterOffsetBegin=20 CharacterOffsetEnd=22 PartOfSpeech=VBZ]
 [Text=located CharacterOffsetBegin=23 CharacterOffsetEnd=30 PartOfSpeech=VBN]
 [Text=in CharacterOffsetBegin=31 CharacterOffsetEnd=33 PartOfSpeech=IN]
 [Text=California CharacterOffsetBegin=34 CharacterOffsetEnd=44 PartOfSpeech=NNP]
 [Text=. CharacterOffsetBegin=44 CharacterOffsetEnd=45 PartOfSpeech=.]

 Constituency parse: 
 (ROOT
  (S
    (NP (NNP Stanford) (NNP University))
    (VP (VBZ is)
      (VP (VBN located)
        (PP (IN in)
          (NP (NNP California)))))
    (. .)))


 Dependency Parse (enhanced plus plus dependencies):
 root(ROOT-0, located-4)
 compound(University-2, Stanford-1)
 nsubj:pass(located-4, University-2)
 aux:pass(located-4, is-3)
 case(California-6, in-5)
 obl:in(located-4, California-6)
 punct(located-4, .-7)

 Sentence #2 (10 tokens):
 It is a great university, founded in 1891.

 Tokens:
 [Text=It CharacterOffsetBegin=46 CharacterOffsetEnd=48 PartOfSpeech=PRP]
 [Text=is CharacterOffsetBegin=49 CharacterOffsetEnd=51 PartOfSpeech=VBZ]
 [Text=a CharacterOffsetBegin=52 CharacterOffsetEnd=53 PartOfSpeech=DT]
 [Text=great CharacterOffsetBegin=54 CharacterOffsetEnd=59 PartOfSpeech=JJ]
 [Text=university CharacterOffsetBegin=60 CharacterOffsetEnd=70 PartOfSpeech=NN]
 [Text=, CharacterOffsetBegin=70 CharacterOffsetEnd=71 PartOfSpeech=,]
 [Text=founded CharacterOffsetBegin=72 CharacterOffsetEnd=79 PartOfSpeech=VBN]
 [Text=in CharacterOffsetBegin=80 CharacterOffsetEnd=82 PartOfSpeech=IN]
 [Text=1891 CharacterOffsetBegin=83 CharacterOffsetEnd=87 PartOfSpeech=CD]
 [Text=. CharacterOffsetBegin=87 CharacterOffsetEnd=88 PartOfSpeech=.]

 Constituency parse: 
 (ROOT
  (S
    (NP (PRP It))
    (VP (VBZ is)
      (NP
        (NP (DT a) (JJ great) (NN university))
        (, ,)
        (VP (VBN founded)
          (PP (IN in)
            (NP (CD 1891))))))
    (. .)))


 Dependency Parse (enhanced plus plus dependencies):
 root(ROOT-0, university-5)
 nsubj(university-5, It-1)
 cop(university-5, is-2)
 det(university-5, a-3)
 amod(university-5, great-4)
 punct(university-5, ,-6)
 acl(university-5, founded-7)
 case(1891-9, in-8)
 obl:in(founded-7, 1891-9)
 punct(university-5, .-10)
 ...

7)パース結果を図にする
 http://github.com/int2str/jssyntaxtree
 よりダウンロード。解凍。解凍ディレクトリで
 これはJAVASCRIPTで書かれた木構造を描画するもの。
 そのままでは構造体の区切り文字が[]なのでこれを()に変更する。
 出力された丸括弧で表示させたいので。

 $ nano 
  ----
  function isControlCharacter(ch) {
    const control_chars = ['[', ']','(', ')', '_', '"']; <<==()追加
    return control_chars.includes(ch);
  }
  ;;
 function parseControlCharacters(input) {
   if (input.charAt(0) == '_') return [new Token(TokenType.SUBSCRIPT_PREFIX), 1];
   if (input.charAt(0) == '[') return [new Token(TokenType.BRACKET_OPEN), 1];
   if (input.charAt(0) == ']') return [new Token(TokenType.BRACKET_CLOSE), 1];
   if (input.charAt(0) == '(') return [new Token(TokenType.BRACKET_OPEN), 1]; <<==追加
   if (input.charAt(0) == ')') return [new Token(TokenType.BRACKET_CLOSE), 1]; <<==追加
  return [null, 0];
 }
 ---- 修正

 解凍ディレクトリでpythonサーバを起動。
 $ python3 -m http.server 8000

  WEBブラウザで
 http://localhost:800
  で開く。
 上のテキストフィールドに
 「(ROOT
  (S
    (NP (NNP Stanford) (NNP University))
    (VP (VBZ is)
      (VP (VBN located)
        (PP (IN in)
          (NP (NNP California)))))
    (. .))) 」
 コピー&ペーストする。
 図を木リックすると画像がダウンロードされる。
[npl-tree.png]
2021-04-30 「TinyBasic Plus for PICO」
RP2040の周辺デバイスレジスタを直接読み書きしたくてBASICを移植してみた。
BASICソースプログラムは最近の流行からはそれている。
FATFSはプログラムをSAVE,LOADするのに必要なので追加した。長いファイル名、日本語ファイル名可。
EDITORは小さくてTTYエスケープシーケンスを使うものを探して移植。

Download Files

(1) http://elm-chan.org/fsw/ff/00index_e.html
   FatFs - Generic FAT Filesystem Module

   FatFs sample projects for various platforms (December 5, 2020)
   http://elm-chan.org/fsw/ff/ffsample.zip
   FM3を参考にする。

(2) https://github.com/BleuLlama/TinyBasicPlus
   TinyBasic Plus

   https://github.com/BleuLlama/TinyBasicPlus/archive/refs/heads/master.zip

(3) https://github.com/GrenderG/tte
    tte (tiny text editor)

    https://github.com/GrenderG/tte/archive/refs/heads/master.zip

(4) https://www.raspberrypi.org/documentation/rp2040/getting-started/
   Raspberry pi PICO
  
   https://datasheets.raspberrypi.org/pico/getting-started-with-pico.pdf
   Getting started with Raspberry Pi Pico

(5) getting-started-with-pico.pdfの説明によりインストールする。
  できた "~/pico"ディレクトリにTBASIC PLUSのzipファイルを解凍する。
  Cmakeか、VSCODEでコンパイルする。

   ▶VSCODE設定

   $ code --install-extension marus25.cortex-debug
   $ code --install-extension ms-vscode.cmake-tools
   $ code --install-extension ms-vscode.cpptools

   PICO_SDK_PATH は設定されている。

  .vscode/launch.jsonの修正
    □pico-examplesをコンパイルとデバッグする場合
   $ cd pico/pico-examples
     $ mkdir .vscode
     $ cp ide/vscode/launch-raspberrypi-swd.json .vscode/launch.json
     $ cp ide/vscode/settings.json .vscode

     ■他のプログラムの場合
     $ cd pico/tbasic_fatfs
          自分で作成したプロジェクトのディレクトリ
   $ cp ../pico-examples/ide/vscode/launch-raspberrypi-swd.json .vscode/launch.json
     $ cp ../pico-examples/ide/vscode/settings.json .vscode

     ◎共通 コピーしたlaunch.json修正
    $ nano .vscode/launch.json
   ---
    {
      "version": "0.2.0",
      "configurations": [
        {
            "name": "Pico Debug",
            "cwd": "${workspaceRoot}",
            "executable": "${command:cmake.launchTargetPath}",
            "request": "launch",
            "type": "cortex-debug",
            "servertype": "openocd",
            // This may need to be arm-none-eabi-gdb depending on your system
            "gdbPath" : "gdb-multiarch",
            "device": "RP2040",
            "configFiles": [
                "interface/picoprobe.cfg",  <<===raspberrypi-swd.cfg をpicoprobe.cfgに変更
                "target/rp2040.cfg"              (picoprobeを使う場合)
            ],
            "svdFile": "${env:PICO_SDK_PATH}/src/rp2040/hardware_regs/rp2040.svd",
            "runToMain": true,
            // Work around for stopping at main on restart
            "postRestartCommands": [
                "break main",
                "continue"
            ]
        }
      ]
    }
  ----
ソースプログラムダウンロード tbasic-fatfs.zip(759Kb)
......
BASIC言語
- BYE		- *exits Basic, soft reboot on Arduino*
- END 		- *stops execution from the program, also "STOP"*
- MEM		- *displays memory usage statistics*
- NEW		- *clears the current program*
- RUN		- *executes the current program*
- FILES		- 	*lists the files on the SD card*
- LOAD "filename.bas"	- *new and loads a file from the SD card*
- ALOAD "filename.bas"  - *overwrite and loads a file from the SD card and auto restart
- SAVE "filename.bas"	- *saves the current program to the SD card, overwriting*
- INPUT variable	- *let the user input an expression (number or variable name*
- PEEK( address )	- *get a value in memory* (unimplemented)
- POKE address		- *set a value in memory* (unimplemented)
- PRINT expression	- *print out the expression, also "?"*
- REM stuff		- *remark/comment, also "'"*
- IF expression statement - *perform statement if expression is true*
- FOR variable = start TO end	- *start for block*
- FOR variable = start TO end STEP value - *start for block with step*
- NEXT - *end of for block*
- GOTO linenumber - *continue execution at this line number*
                     GOTO 100, GOTO A + 10
- GOSUB linenumber - *call a subroutine at this line number*
                      GOSUB 100, GOSUB A + 10
- RETURN	- *return from a subroutine*
- SLEEP msec    - *wait 99 msec
- SETRC "yyyy/mm/dd hh:mm:ss"  - *Set to RTC
- !xxxx         - *command for Fatfs

(o)Expressions, Math
- A=V, LET A=V	- *assign value to a variable*
- +, -, %, &, *, / - *Math*
- <,<=,=,<>,!=,>=,> - *Comparisons*
- ABS( expression )  - *returns the absolute value of the expression*
- RSEED( v ) - *sets the random seed to v*
- RND( m ) - *returns a random number from 0 to m*

(o)Function
- RDATE()      - *Read Date from RTC
- RTIME()      - *Read Time from RTC

Tiny BASIC Plus追加機能
・演算子 % :MOD  5 % 6 * 8 = 5 :*優先 MBASIC80と同様 5 % (6*8) 、C言語とは違う (5 % 6) * 8
・演算子 & :AND   10 & 3 = 2    : *,/ 優先
・16進数表現 $hhhh : 定数
        $PEEK(a) : 関数戻り値の16進数表示
        $A    : 変数の16進数表示
・関数追加   RDATE() : RTC日付取得 戻り値 (y*256*16 + m*256 + day)
            RTIME() : RTC時刻取得 戻り値 (hh*256*256 + mm*256 + ss) 
・ステートメント追加
        SLEEP msec : ミリ秒で指定 
        SETRTC "yyyy/mm/dd hh:mm:ss" : RTCに年月日時刻を設定する。
                          年/月/日 時:分:秒の文字列で指定
        ADDA A, 1  : 変数をアドレス値(unsigned long)で加算する。減算はマイナス値を加算する。
        ALOAD "プログラムファイル名" : 現在のプログラムに追加または、上書きロードされる。
                             ロード後はメモリされたプログラムの行番号が一番小さい行から実行される。
            FILES ["ディレクトリ[/ディレクトリ]”]: SDカード内のファイル一覧
・文字列のエスケープシーケンス追加
        \\ = \文字 、\' = '文字 , \" = "文字
        \888 = 8進数で文字コード表現
・変数を32ビットで扱う。
・BASICステートメント1行を400文字に制限。
・PEEK,POKEを8ビットか、32ビットで扱うか指定可能。
        PEEK(A)  : 8ビット扱い
        PEEK(A#) : 32ビット扱い、このときアドレスは4の倍数のこと。
        POKE A, 10  : 8ビット扱い
        POKE A, 10# : 32ビット扱い、このときアドレスは4の倍数のこと。
・行番号    1 ~ 65533
・FATFSファイル管理コマンド実行
            BASICコマンド入力で先頭に"!"を入力する。
            !mount    <-- SDカードを抜き差しした後で必ず実行。
            !type "ファイル名Path"  <-- ファイル内テキスト表示。
            !mkdir "ディレクトリ名"  <-- ディレクトリ作成
            !rmdir "ディレクトリ名"  <-- ディレクトリ削除
            !rm "ファイル名"        <-- ファイル削除
            !cp "コピー元ファイル名" "コピー先ファイル名"  <-- ファイルコピー
            !edit ["ファイル名"]    <-- テキストファイル編集

         Keybinding    Action
         Ctrl-Q        Exit
         Ctrl-S        Save
         Ctrl-F        Search. Esc, enter and arrows to interact once searching
         Ctrl-E        Flip line upwards
         Ctrl-D        Flip line downwards
         Ctrl-C        Copy line
         Ctrl-X        Cut line
         Ctrl-V        Paste line
         Ctrl-Z        Undo
         Ctrl-Y        Redo
         Ctrl-A        Help
         ... 注意 ...
         端末ターミナルウィンドウは80桁24行固定。
         これより小さい場合はカーソル制御が正しくできなくなるので編集ができなくなる。
              矢印キー等の複数コードが生成されるキーの長押しはキーコードの取りこぼしが起きるので注意すること。
              UTF-8日本語は可変長複数コードとなるので編集する場合はただの1バイトコードとして扱うので文字化けが
              起きることがあるので注意する。また、行内の日本語以降カーソル位置がバイト位置なので文字削除挿入は
         注意すること。80桁目にあるものと、横スクロールした場合は1桁目にある日本語は文字化けする。
              1行は500バイトまで。
         編集できるサイズはおおよそ空きメモリ未満。
[tte-01.png]
  (注意1)
  BASIC文入力中、行が折り返した場合、バックスペースでは前の行の後ろ側には回り込まない。
  端末の横幅を調整しながら前の行に回り込まないようにする。
  RTCは何もしないと"2021/4/1 00:00:00"から動作している。ファイルのタイムスタンプにも使用。
  メモリがないところ等にアクセスするとHARDFAULTとなるのでPEEK,POKEは注意すること。
  アドレスチェックは32ビットアクセスの4バイト倍数以外はしていなのでメモリアドレスに書き込みした場合は
  動作はどうなるかは不明。RP2040データシートをよく読むこと。
  (注意2)
   GPIO 25はBASIC,EDITORで使用しているのでBASICでは使用しないこと。
  GPIO 25 LED不規則点滅:FatFS,BASIC、EDITOR動作中。
  GPIO 25 LED等間隔点滅:FatFS,BASIC、EDITOR動作中にHARDFAULTが発生。リセット、電源入れ直す。
  GPIO 25 LED消灯:BASIC動作中にBYEコマンド入力した。リセット、電源入れ直す。

FATFS追加
 プログラムセーブ、ロード用
 FAT32 SDカード対応
 UTF-8ファイル名対応
 ファイル名パスは,130文字まで。
 cd, pwd カレントディレクトリという操作はない。
 mkdir xxx, mkdir xx/xxx はあり。
 files "xxx", files "xxx/xxxx" はあり。

参考:メモリ容量
[build] Memory region         Used Size  Region Size  %age Used
[build]            FLASH:      189380 B         2 MB      9.03%
[build]              RAM:       80184 B       256 KB     30.59%
[build]        SCRATCH_X:          0 GB         4 KB      0.00%
[build]        SCRATCH_Y:          0 GB         4 KB      0.00%


端末ターミナルソフトはminicom だと日本語が文字化けする。
cuかckermitがよい。


├── CMakeLists.txt  :Cmake 情報ファイル
|                     
├── README.txt       :説明
├── TinyBasicPlus <dir>  :TINY BASIC PLUSソース
│   ├── FILE-LIST
│   ├── README.md
│   ├── TinyBasicPlus.ino
│   ├── TinyBasicPlus_main.c
│   ├── desktop.h
│   └── main.cpp
├── build <dir>      :プログラムビルドディレクトリ
│   ├── CMakeCache.txt
│   ├── CMakeFiles <dir>
│   ├── Makefile     : Makefile 
│   ├── cmake_install.cmake
│   ├── compile_commands.json
│   ├── elf2uf2 <dir>
│   ├── generated <dir>
│   ├── pico-sdk <dir>
│   ├── tbasic_fatfs.bin
│   ├── tbasic_fatfs.dis
│   ├── tbasic_fatfs.elf
│   ├── tbasic_fatfs.elf.map :リンクマップ
│   ├── tbasic_fatfs.hex
│   └── tbasic_fatfs.uf2     :BOOTSELスイッチを押して書き込みするファイル
├── fatfs <dir>              :FATFS, Raspberry pi PICO基板の依存する関数プログラムファイル
│   ├── Ev_Board.c
│   ├── Ev_Board_conf.h
│   ├── fatfs <dir>
│   │   ├── diskio.h
│   │   ├── ff.c
│   │   ├── ff.h
│   │   ├── ffsystem.c
│   │   └── ffunicode.c
│   ├── ffconf.h
│   └── mmc_mfs.c
├── pico_sdk_import.cmake
├── tbasic_fatfs.c            :Tiny Basic Plus mainプログラム
└── tte <dir>                 :EDITORプログラム
    ├── LICENSE
    ├── README.md
    └── tte.c

ファイル:CMakeLists.txt
...
# Generated Cmake Pico project file

cmake_minimum_required(VERSION 3.13)

set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)

# initalize pico_sdk from installed location
# (note this can come from environment, CMake cache etc)
set(PICO_SDK_PATH "/home/pi/pico/pico-sdk")

# Pull in Raspberry Pi Pico SDK (must be before project)
include(pico_sdk_import.cmake)

project(tbasic_fatfs C CXX ASM)

# Initialise the Raspberry Pi Pico SDK
pico_sdk_init()

# Add executable. Default name is the project name, version 0.1

add_executable(tbasic_fatfs 
  fatfs/Ev_Board.c
  fatfs/fatfs/ff.c
  fatfs/fatfs/ffsystem.c
  fatfs/mmc_mfs.c
  fatfs/fatfs/ffunicode.c
  tbasic_fatfs.c
  TinyBasicPlus/TinyBasicPlus_main.c
  tte/tte.c )

pico_set_program_name(tbasic_fatfs "tbasic_fatfs")
pico_set_program_version(tbasic_fatfs "0.1")

pico_enable_stdio_uart(tbasic_fatfs 0)  <<--USB ACM UARTを使うとき
pico_enable_stdio_usb(tbasic_fatfs 1)   <<--
#pico_enable_stdio_uart(tbasic_fatfs 1) <<==GPIO1,2 UARTを使うとき
#pico_enable_stdio_usb(tbasic_fatfs 0)  <<==

# Add the standard library to the build
target_link_libraries(tbasic_fatfs pico_stdlib)

# Add any user requested libraries
target_link_libraries(tbasic_fatfs
        hardware_spi
        hardware_pwm
        hardware_rtc
        )

pico_add_extra_outputs(tbasic_fatfs)
include_directories(./ ./fatfs ./fatfs/fatfs)
#add_definitions(-DRASPI_PICO -DDDEBUG ) <<==SDカードCDピンがカード挿入時HI Activeのとき
                            DDEBUGマクロが要らない時は -DDDEBUG削除。
add_definitions(-DRASPI_PICO -DAKDK_SOCKET) <<--SDカードCDピンがカード挿入時LOW Activeのとき
SET(CMAKE_EXE_LINKER_FLAGS  "${CMAKE_EXE_LINKER_FLAGS} -Wl,--print-memory-usage")
...

◎配線
picoprobeとDEBUG対象PICOボード配線

  picoprobe GND -> Pico B GND
  picoprobe GP2 -> Pico B SWCLK
  picoprobe GP3 -> Pico B SWDIO
  picoprobe GP4/UART1 TX -> Pico B GP1/UART0 RX
   picoprobe GP5/UART1 RX -> Pico B GP0/UART0 TX
   picoprobe VSYS -> Pico B VSYS

    (getting-started-with-pico.pdf Appendix A: Using Picoprobe の  Picoprobe Wiring 参照)

   sparkfun.con micro-SD-card board            
   
   Pico B GPIO 16 (pin 21) MISO/spi0_rx-> DO on SD-card board
   Pico B GPIO 17 (pin 22) Chip select -> CS on SD-card board
   Pico B GPIO 18 (pin 24) SCK/spi0_sclk -> SCK on SD-card board
   Pico B GPIO 19 (pin 25) MOSI/spi0_tx -> DI on SD-card board
   Pico B GPIO 22 (pin 29) GPIO -> CD on SD-card board
   Pico B 3.3v (pin 36) -> VCC on SD-card board
   Pico B GND (pin 38)  -> GND on SD-card board

SDカードCDがどちらがActiveかをチェックするプログラム
GPIO 22を見ている。
SDカードを抜き差しして確認する。
-----
10 A = PEEK($D0000004#)
20 IF (A & $400000) != 0 GOTO 50
30 PRINT "SD CS検出LOW"
40 GOTO 60
50 PRINT "SD CS検出HI"
60 SLEEP 500
61 FILES
70 GOTO 10
-----

>mem
Program Start: h'20003570
Start Free Memory: h'20003570 - End Free Memory: h'2001344F
65248 bytes free.

  pokeステートメントはmemで表示される空きメモリアドレスの間に指定する。
 peek, pokeで指定するアドレスは空きメモリアドレス以外でも可能であるが、CPU Hardfault エラーになるか、
 全体が動作不可能、不安定等になる場合がある。Hardfaultについては基板上のLEDが等間隔で点滅する。
 このときはCPUをリセットすること。

>load "memdump.bas"
OK
>list
100 A = $20007CF0
110 B = $20007D30
120 POKE A, $EE
130 ADDA A, 1
140 IF A != B GOTO 120
200 GOSUB 8000
210 POKE $20007D04, 12345678#
220 POKE $20007D02, 12345678
230 POKE $20007D14, $12345678#
240 POKE $20007D12, $12345678
300 GOSUB 8000
310 END
8000 A = $20007CF0
8001 B = $20007D30
8002 PRINT "___ADDRESS_:_DATA___________________________________"
8004 PRINT ########.$A," : ";
8010 PRINT ##.$PEEK(A)," ";
8012 ADDA A, 1
8014 IF A = B GOTO 8050
8020 IF ( A % 8 ) != 0 GOTO 8040
8022 PRINT " "
8024 PRINT ########.$A," : ";
8040 GOTO 8010
8050 PRINT ""
8060 RETURN
OK
>run
___ADDRESS_:_DATA___________________________________
h'20007CF0 : h'EE h'EE h'EE h'EE h'EE h'EE h'EE h'EE  
h'20007CF8 : h'EE h'EE h'EE h'EE h'EE h'EE h'EE h'EE  
h'20007D00 : h'EE h'EE h'EE h'EE h'EE h'EE h'EE h'EE  
h'20007D08 : h'EE h'EE h'EE h'EE h'EE h'EE h'EE h'EE  
h'20007D10 : h'EE h'EE h'EE h'EE h'EE h'EE h'EE h'EE  
h'20007D18 : h'EE h'EE h'EE h'EE h'EE h'EE h'EE h'EE  
h'20007D20 : h'EE h'EE h'EE h'EE h'EE h'EE h'EE h'EE  
h'20007D28 : h'EE h'EE h'EE h'EE h'EE h'EE h'EE h'EE 
___ADDRESS_:_DATA___________________________________
h'20007CF0 : h'EE h'EE h'EE h'EE h'EE h'EE h'EE h'EE  
h'20007CF8 : h'EE h'EE h'EE h'EE h'EE h'EE h'EE h'EE  
h'20007D00 : h'EE h'EE h'4E h'EE h'4E h'61 h'BC h'00  
h'20007D08 : h'EE h'EE h'EE h'EE h'EE h'EE h'EE h'EE  
h'20007D10 : h'EE h'EE h'78 h'EE h'78 h'56 h'34 h'12  
h'20007D18 : h'EE h'EE h'EE h'EE h'EE h'EE h'EE h'EE  
h'20007D20 : h'EE h'EE h'EE h'EE h'EE h'EE h'EE h'EE  
h'20007D28 : h'EE h'EE h'EE h'EE h'EE h'EE h'EE h'EE 
OK
>load "vect-dump.bas"
OK
>list
10 PRINT "Vector Table Offset:",$PEEK($E000ED08#)
20 A = PEEK($E000ED08#)
30 FOR I = -16 TO 31
40 IF I < 0 PRINT ##.I;
41 IF I >= 0 PRINT ###.I;
42 PRINT " [ ",########.$A," ] = ",########.$PEEK(A#)
50 ADDA A, 4
60 NEXT I
OK
>run
Vector Table Offset:h'20000000
-16 [ h'20000000 ] = h'20042000
-15 [ h'20000004 ] = h'100001F7
-14 [ h'20000008 ] = h'100001C3
-13 [ h'2000000C ] = h'100004E1
-12 [ h'20000010 ] = h'100001C1
-11 [ h'20000014 ] = h'100001C1
-10 [ h'20000018 ] = h'100001C1
-09 [ h'2000001C ] = h'100001C1
-08 [ h'20000020 ] = h'100001C1
-07 [ h'20000024 ] = h'100001C1
-06 [ h'20000028 ] = h'100001C1
-05 [ h'2000002C ] = h'100001C7
-04 [ h'20000030 ] = h'100001C1
-03 [ h'20000034 ] = h'100001C1
-02 [ h'20000038 ] = h'100001C9
-01 [ h'2000003C ] = h'100001CB
000 [ h'20000040 ] = h'100001CD
001 [ h'20000044 ] = h'100001CD
002 [ h'20000048 ] = h'100001CD
003 [ h'2000004C ] = h'1000D6E9
004 [ h'20000050 ] = h'100003F9
005 [ h'20000054 ] = h'10011E4D
006 [ h'20000058 ] = h'100001CD
007 [ h'2000005C ] = h'100001CD
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
029 [ h'200000B4 ] = h'100001CD
030 [ h'200000B8 ] = h'100001CD
031 [ h'200000BC ] = h'10011C49
OK
>load "pwmreg-lst.bas"
OK
>list
10 PRINT "=== PWM Registers List ==="
20 A =$40050000
30 FOR I = 0 TO 44
40 IF (I / 5) != 8 GOTO 80
50 IF (I % 5) != 0 GOTO 90
60 PRINT " ......"
70 GOTO 90
80 IF (I % 5) = 0 PRINT " ... PWM ",I/5," ..."
90 IF I < 0 PRINT ##.I;
100 IF I >= 0 PRINT ###.I;
110 PRINT " [ ",########.$A," ] = ",########.$PEEK(A#)
120 ADDA A, 4
130 NEXT I
OK
>run
=== PWM Registers List ===
 ... PWM 0 ...
000 [ h'40050000 ] = h'00000000
001 [ h'40050004 ] = h'00000010
002 [ h'40050008 ] = h'00000000
003 [ h'4005000C ] = h'00000000
004 [ h'40050010 ] = h'0000FFFF
 ... PWM 1 ...
005 [ h'40050014 ] = h'00000000
006 [ h'40050018 ] = h'00000010
007 [ h'4005001C ] = h'00000000
008 [ h'40050020 ] = h'00000000
009 [ h'40050024 ] = h'0000FFFF
 ... PWM 2 ...
010 [ h'40050028 ] = h'00000000
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
017 [ h'40050044 ] = h'00000000
018 [ h'40050048 ] = h'00000000
019 [ h'4005004C ] = h'0000FFFF
 ... PWM 4 ...
020 [ h'40050050 ] = h'00000001
021 [ h'40050054 ] = h'00000640
022 [ h'40050058 ] = h'000002E6
023 [ h'4005005C ] = h'000C0000
024 [ h'40050060 ] = h'000004E1
 ... PWM 5 ...
025 [ h'40050064 ] = h'00000000
026 [ h'40050068 ] = h'00000010
027 [ h'4005006C ] = h'00000000
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
033 [ h'40050084 ] = h'00000000
034 [ h'40050088 ] = h'0000FFFF
 ... PWM 7 ...
035 [ h'4005008C ] = h'00000000
036 [ h'40050090 ] = h'00000010
037 [ h'40050094 ] = h'00000000
038 [ h'40050098 ] = h'00000000
039 [ h'4005009C ] = h'0000FFFF
 ......
040 [ h'400500A0 ] = h'00000010
041 [ h'400500A4 ] = h'00000000
042 [ h'400500A8 ] = h'00000010
043 [ h'400500AC ] = h'00000000
044 [ h'400500B0 ] = h'00000000
OK
                            
>load "hex-t01.bas"
OK
>list
10 PRINT $$1234
20 PRINT ####.$$1234
30 PRINT ###.$$CD
40 PRINT ###.$$ABCD
50 A = $4567
60 PRINT ###.$A
70 PRINT ######.$A
OK
>run
h'1234
h'1234
h'0CD
h'ABCD
h'4567
h'004567
OK
>load "num-t01.bas"
OK
>list
10 PRINT 1234
20 PRINT ######.1234
30 PRINT ###.34
40 PRINT ###.1234
50 PRINT ##12, "=NG"
OK
>run
1234
001234
034
1234
What? 50 PRINT ##^2, "=NG"

>load "esc-t01.bas"
OK
>list
10 PRINT "\033[A\033[ATEST 001"
20 PRINT "\377[A", "OK"
30 PRINT "\\015[A","OK"
40 PRINT "\"015[A","OK"
50 PRINT "data\"abc","OK"
60 PRINT "data\'abc"," OK"
70 PRINT "data'abc"," OK"
80 PRINT 'data\'abc'," OK"
90 PRINT 'data\"abc'," OK"
100 PRINT 'data"abc'," OK"
110 PRINT "\029[A","NG"
120 PRINT "\097[A","NG"
130 PRINT "\477[A","NG"
TEST 001
\ufffd[AOK
\015[AOK
"015[AOK
data"abcOK
data'abc OK
data'abc OK
data'abc OK
data"abc OK
data"abc OK
What? 110 PRINT "^029[A","NG"

 ーーー
 TinyBasic,FatFs用にPWM4をタイマー用に使いGPIO-25の基板についているLEDを点滅させている。

>load "gpio-test.bas"
OK
>list
10 REM **** GPIO-02 LED ON/OFF 500 USEC INTERVAL
20 Z = 500
30 GOSUB 1000
40 GOSUB 3000
50 GOSUB 4000
60 GOSUB 2000
70 GOTO 50
1000 POKE $E000E010, 1#
1010 POKE $E000E014, Z#
1020 POKE $E000E018, 0#
1030 Z = PEEK($E000E010#)
1040 RETURN
2000 Z = PEEK($E000E010#)
2010 IF (Z & $010000) = 0 GOTO 2000
2020 RETURN
3000 POKE $40014014, 5#
3010 POKE $D0000020, 4#
3020 RETURN
4000 POKE $D000001C, 4#
4010 RETURN
OK
>run
break!
OK
 ーーー
 よくあるLED点滅。Systickタイマを使う。
  配線                      LED
 GPIO-02 --/\/\510Ω/\/\/---▶|---> GND
                       目視では点灯
 20 Z = 数字 :数字20000以上で点滅して見える。

>setrtc "2021/4/28 14:01:00"
>load "date.bas"
OK
>list
10 PRINT "\012\012\012"
20 REM SETRTC "2021/4/3 11:59:40"
30 A = RTIME()
40 B = RDATE()
50 PRINT "\015\012\012\033[4A",(B&$FFFF000)/(256*16),"年",##.(B&$F00)/256,"月",##.B%256,"日"
60 PRINT ##.(A&$FF0000)/(256*256),":",##.(A&$FF00)/256,":",##.A%256
70 PRINT "\012\012"
80 SLEEP 1000
90 PRINT "\033[4A"
100 GOTO 30
OK
>run


2021年04月28日
14:01:32



break!
OK
>!type "ald00.bas"
10 PRINT "10"
20 PRINT "20"
30 PRINT "30"
40 A = 1
50 ALOAD "ald01.bas"
300 print "SUB 300 : ", A
310 A = A + 1
320 IF A > 5 END
330 SLEEP 500
340 RETURN

>!type "ald01.bas"
10 GOSUB 300
20 PRINT "100"
30 PRINT "110"
40 ALOAD "ald02.bas"

>!type "ald02.bas"
10 GOSUB 300
20 PRINT "80"
30 PRINT "90"
40 ALOAD "ald01.bas"
>load "ald00.bas"
OK
>run
10
20
30

SUB 300 : 1
100
110

SUB 300 : 2
80
90

SUB 300 : 3
100
110

SUB 300 : 4
80
90

SUB 300 : 5
OK
>load "goto.bas"
OK
>list
10 FOR I = 0 TO 14
20 GOTO (I%5)*10+30
30 PRINT "*";
40 PRINT "*";
50 PRINT "*";
60 PRINT "*";
70 PRINT "*"
200 NEXT I
OK
>run
*****
****
***
**
*
*****
****
***
**
*
*****
****
***
**
*
OK
2021-03-30  「CP/M  エミュレータ」
raspberry pi PICOにTiny BASICを入れようと思ったのが原因で横道にそれてしまった。

参照:
YAZE-AG - Yet Another Z80 Emulator by AG (V 2.40.5 / V 2.30.3)

http://www.mathematik.uni-ulm.de/users/ag/yaze-ag/

(1)インストール
$ wget http://www.mathematik.uni-ulm.de/users/ag/yaze-ag/devel/yaze-ag-2.40.5_with_keytrans.tar.gz
$ tar zxvlpf yaze-ag-2.40.5_with_keytrans.tar.gz
$ cd yaze-ag-2.40.5_with_keytrans
$ cp  Makefile_Raspberry_Pi_3_Model_B_ARMv7_32Bit  Makefile
$ make -j 4
$ sudo make install
$ cd ~
$ rm -r yaze-ag-2.40.5_with_keytrans
$ rm -f yaze-ag-2.40.5_with_keytrans.tar.gz
$ man yaze
$ yaze cpm  (CP/Mが動く)
  ~/cpm ディレクトリが出来る。

ドライブがWrite可能かどうかの一覧
各ドライブにソフトが入っている。

A: r/w  BOOT_UTILS      BOOT disk with CCP.COM and some utilies
B: r/w  CPM3_SYSdsk     Disk with all CP/M 3.1 system utilities
                          A section "YAZE-AG" is added in the help file.
C: r/o  ./disksort/     Connected to the (unix-)directory ./disksort/ (SOURCE)
D: r/w  DISKSORT.dsk    Submit examples of the DISKSORT project
F: r/w  ZINC            System Utilies of the ZINC project from John Elliott
G: r/w  TEST-UTILS-1.10 Test Utilities of the old version yaze-1.10
H: r/w  HI-C-Z280-Compiler   A Copy of the C Compiler from HI Tech Soft
I: r/w  UNIXLIKE        UNIX like utilities
J: r/w  MMU-Utils       Testfiles for the Memory Management Unit (MMU).
K: r/w  Kermit_SZRZ.ydsk Kermit and SZ/RZ (Zmodem)
L: r/w  spl.ydsk        SPL development environment to compile .SPL files
M: r/w  Turbo-Modula-2  Modula 2 Compiler of Borland
N: r/w  testdsk.ydsk    testdisk
P: r/w  BIOS3           Sources of the BIOS3 for YAZE-AG (look 0-README.1ST)

ファイルコピー
 D> pip コピー先ファイル名=コピー元ファイル名
 D> pip con:=ファイル名  (画面表示)
 D> pip aux:=ファイル名  (シリアルへ)
アセンブラ
 D> mac ファイル名[.asm]
 D> hexcom ファイル名[.hex] (HEXからCOMファイルへ変換)
UNIXコマンド
 A> df           (マウント全ドライブの容量表示)
 A> i:ls *.* -f

kermitでシリアル経由で接続する
 $ cd ~/cpm
 $ nano .yazerc
  ----
  attach aux /dev/ttyUSB1
  ---- 環境によるターミナルに合わせること(UNIX端末ポートをCP/M COMポートに割り当てる)
 $ stty -F /dev/ttyUSB1 -crtscts raw 115200 (ttyをRAWモード、ハンドシェークなし、BPSを設定する)
 $ yaze cpm

 x> k:
 k> kermit
 (/home/pi/cpm) C-Kermit> remote dir  (リモート側KERMITでls結果が表示)
 (/home/pi/cpm) C-Kermit> send ファイルパス (ファイル送信)
 (/home/pi/cpm) C-Kermit> get リモートファイルパス (ファイル受信)

linux側KERMITをサーバにする
--- ~/.kermrc ------
set line /dev/ttyUSB0
set carrier-watch off
set speed 115200
set parity none
set flow-control none
set escape-character ^]
server
-----------------

 $ nano kerm_server.sh
--------------------
#!/bin/sh
DEV=/dev/ttyUSB0
stty -F $DEV -crtscts raw 115200
kermit
----------作成
 $ chmod +x kerm-server.sh
 $ ./kerm-server.sh
  kermitがサーバモードで動作

rz, szコマンドを使う時

LINUX側
----send---
#!/bin/sh
DEV=/dev/ttyUSB0
stty -F $DEV -crtscts raw 115200
sz $1 > $DEV  < $DEV
----
-----recieve---
#!/bin/sh
DEV=/dev/ttyUSB0
stty -F $DEV -crtscts raw 115200
rz $1 > $DEV  < $DEV
-----

CP/Mの終了
 A> sys[enter]
CP/Mエミュレータの終了
 $> quit[enter]
CP/Mエミュレータのヘルプ
 $> help           (コマンド一覧)
 $> help コマンド  (コマンドオプションの説明)

ドライブの追加
 $ cdm
 $> create XXXXX.ydsk 256KB   (容量を指定、なしは1MB)
 $> quit
 $ cdm XXXXX.ydsk
 A0> ls -l          (ファイル一覧)
 A0> cp u:UNIXファイル名 CP/Mファイル名 (バイナリ転送、t:xxxはテキスト転送)
 A0> cp CP/Mファイル名 u:UNIXファイル名
 A0> quit

 $ nano ~/cpm/.yazerc
 ------
 mount o XXXXX.ydsk
 ----追加
 容量が大きいと"insufficient space to mount XXXXX.ydsk"メッセージがコマンド入力直後に表示される。
 ~/cpm/.yazercファイルの"go"コマンドをコメントにしてチェックすると良い。
 デフォルトでは"E","O"ドライブが空き。いらないのを外せば容量が大きくできる。
 最大16ドライブまでマウント出来る。
2021-06-04  「Raspberry pi PICO」
どんなものかと1個買ってみました。
ほぼ裸でです。
書き込みは、mbedかMicro:bitみたいな感覚です。
Micro:bitはUSBシリアル・フラッシュ書き込みは別CPUなのが、PICOはファームウェアでCPUひとつでやっている。

[ras-pi-pico.jpg]
[tiny2040.jpg]

参照:getting-started-with-pico.pdf  (2021-03-05)
   raspberry-pi-pico-python-sdk.pdf (2021-03-05)
   hardware_design_with_rp2040.pdf  (2021-03-05)
   pico_c_sdk.pdf  (2021-03-05)

(1)開発環境
 Raspberry pi 4B+ 4GB

(2)OSインストール

  Raspberry pi 2021-01-11 Desktopイメージインストール  
  sudo apt install fcitx-mozc
  sudo nano /boot/config.txt
  ---
  hdmi_force_hotplug=1
  ---追加,コメントを外す

  VNCを有効
 画面の大きさ変更は、VNC接続後に"メニュー設定"ー>"Screen Configuration"で行う。

(3)picoツールインストール

  wget https://raw.githubusercontent.com/raspberrypi/pico-setup/master/pico_setup.sh
  chmod +x pico_setup.sh
  ./pico_setup.sh
  sudo reboot

  minicomは一緒にインストールされる

(4)VSCodeで開発はツールインストールでインストール済なのでメニューから起動できる。
   オープンフォルダで "~/pico/pico-examples" を開くとコンパイルできる。

(5)配線

   Raspberry pi GPIO14 --- PICO pin2(GP1)
   Raspberry pi GPIO15 --- PICO pin1(GP0)
   Raspberry pi GND    --- PICO pin3(GND) に接続。

   Raspberry pi GPIO24 --- PICO SWDIO
   Raspberry pi GPIO25 --- PICO SWCLK
   Raspberry pi GND    --- PICO SWDGND に接続。

   Raspberry pi 5V     --- ショットキダイオードー▶ー --- PICO VSYS

プログラムをフラッシュに書き込んで、電源を外部からVSYS,またはUSBから給電する場合に周辺回路の電源を3v3ピン
からとるようなことをした場合にリセットがうまく行かない場合がある。
その時はRUNピンをGNDにする。または、RUN pin(37)とGND間に10μF電解コンデンサを入れて RUN pin(37)と3v3(36)に
ダイオードを入れる。向きは3v3(36)pin方向にコンデンサが放電するような向きに入れる。

       少電力ダイオード 
          ↓
 (36)3v3(OUT) --|◀--+---RUN pin(37)
                     |
                    ---- +
                    ////  10uF (電解コンデンサ)
                    ---- -
                     |
                     ▽ GND

(6)VisualStudio-Code と OPENOCDでデバッグ
  これでデバッグできるのだが、OSをアップデートしたか何かでできなくなってしまった。
  フラッシュイレースができないとなる。
  そこでpicoprobeでやることにした。Raspberry Pi PICOを1枚picoprobeにする。
  開発環境ボードとはUSBケーブルで接続する。
  picoprobeはツールインストールで作成されているのでそのuf2ファアイルをUSB経由で書き込む。

(7)USB picoprobeのパーミッションの変更
  sudo nano /etc/udev/rules.d/98-p-probe.rules
   ---
   ATTRS{idVendor}=="2e8a", ATTRS{idProduct}=="0004", MODE="0666"
   ---作成
  USBベンダーとプロダクトはlsusbコマンドで表示されるもの。
  ”Bus 001 Device 003: ID 2e8a:0004”  
  作成したら、リブートして有効にすること。
   有効にしないとコンパイルはできるがデバッグができない。

(8)picoprobeとDEBUG対象PICOボード配線

   picoprobe GND -> Pico B GND
   picoprobe GP2 -> Pico B SWCLK
   picoprobe GP3 -> Pico B SWDIO
   picoprobe GP4/UART1 TX -> Pico B GP1/UART0 RX
   picoprobe GP5/UART1 RX -> Pico B GP0/UART0 TX
     picoprobe VSYS -> Pico B VSYS

    (getting-started-with-pico.pdf  (2021-03-05) 
      Appendix A: Using Picoprobe の  Picoprobe Wiring 参照)

(9).vscode/launch.jsonの修正

  ---
    "gdbPath" : "gdb-multiarch",
    "device": "RP2040",
    "configFiles": [
        "interface/picoprobe.cfg",  <<=raspberrypi-swd.cfg をpicoprobe.cfgに変更
        "target/rp2040.cfg"
    ],
    "svdFile": "${env:PICO_SDK_PATH}/src/rp2040/hardware_regs/rp2040.svd",
    "runToMain": true,
  ---

(10)VScode でデバッグする。

   $ code

    VISUAL STUDIO Code画面になる
  1)openフォルダで先で設定したフォルダを開く
  2)ウィンドウ下のバーに「キットが選択されていません」となるのでそこをクリックし、
    GCC for arm-none-eabiを選ぶ
  3)ウィンドウ下のバーの「CMake:[Dbug]:準備完了」をクリック
  4)ウィンドウ上にDebug選択プルダウンメニューがでるので選択
  5)メニューRun -> Start Debugging[F5] 選択
  6)プロジェクト選択プルダウンメニューから新しく作ったプロジェクトを選択
  main()でブレークした状態となり、デバッグができる。
  生成されたmain()コードなのでこれを修正して使う。

(11)自分用のCプロジェクトの自動生成とVisualStudio-Codeでデバッグ

   $ cd ~/pico
   $ git clone https://github.com/raspberrypi/pico-project-generator.git
   $ cd ~/pico/pico-project-generator
   $ ./pico_project.py --gui

    [Project Name:] m_core1
    [Location:] /home/pi/pico
    [Library Options] なしでそのまま
    [Console Options] UARTにするかUSBシリアルにするか選択
    [Code Optins] なしでそのまま
    [Build Options] [x]Run Build [x]Create VSCode project Debugger=picoprobe
    [OK] クリック、その後「OK」クリック。
    [quit] クリック。

    ◎コマンドラインでプロジェクトを作る場合は作成したいフォルダに cd xxxx してから、
     /home/pi/pico/pico-project-generator/pico_project.py -uart --project vscode -d 1 プロジェクト名
      VS-code用(--project vscode)のpicoprobe(-d 1)の設定ファイルを作る。

     これでVscodeの環境とc言語 mainの雛形プログラムが作成される。

    UARTのデバッグはpicoprobeのUSBケーブル経由で行う。

  $ minicom -b 115200 -D /dev/ttyACM0

(12)せっかくのマルチコアチップなので体験してみる。
    設定は上記のようにおこなう。

   $ nano m_core1/m_core1.c
   -----
   #include <stdio.h>
   #include "pico/stdlib.h"
   #include "pico/multicore.h"

   // define LED
   #define LED_B 25

   static uint8_t led_b;

   bool repeating_timer_callback(struct repeating_timer *t) {
       gpio_put(LED_B, led_b);
       led_b ^= 1;
       return true;
   }
   // Program core1
   void core1_program(void)
   {
   struct repeating_timer timer;

       gpio_init(LED_B);
       gpio_set_dir(LED_B, GPIO_OUT);
       led_b = 1;
       add_repeating_timer_ms(500, repeating_timer_callback, NULL, &timer);
   
       while(1) {
           asm volatile("nop");
       }
   }

   int main() {
       // Start core1
       multicore_launch_core1(core1_program);

       sleep_ms(5000);
       while(1) {
           asm volatile("nop");
       }
       return 0;
   }
   -----修正

   $ nano m_core1/CMakeLists.txt
   ----
   target_link_libraries(testm1 pico_stdlib pico_multicore)
   ---- "pico_multicore"を追加する

   VISUAL STUDIO Code画面から上記のように修正してもよい。
   メニューRun -> Start Debugging[F5] 選択
  コンパイル後、実行して5秒後も同じ間隔でLEDが点滅する。

(13)RTCが結構正確に時を刻む。24時間以上で1秒位あるかどうかくらいです。
    まだ先の長い話ですが、C-SDKサンプルでそのまま使うと西暦2100年はうるう年で動作します。
    2100-02-28 23:59までにRTC: CTRL Register #8bit FORCE_NOTLEAPYEAR = 1 にしましょう。
    2100-03-01 以降には0に。
    4年毎のうるう年計算のみをする。

  曜日設定があるので曜日計算を調べてみた。
   昔の資料にある数式を使って現在の曜日計算すると正しくないものがある。
   ユリウス日から求めるのも手かも。ユリウス日の計算方法も数種類ある。

  Zellerの公式

  【参考】[改訂新版]C言語による標準アルゴリズム事典 奥村晴彦 技術評論社 2018

  Y 西暦4桁
  M 月
  D 日付

 ① M <= 2 のとき
    M + 12 = M  (1月を前年13月とする、 2月を前年14月とする)
    Y - 1 = Y

 ② Y + INT( Y / 4 ) - INT( Y / 100 ) + INT( Y / 400 )
                    + INT(( 13 * M + 8 ) / 5 ) + D = WDAY
     WDAY Mod 7 = w-day
     w-day 0: 日 1:月 2:火 3:水 4:木  5:金 6:土
     割り算計算は小数点以下切り捨て。

  【参考】教室に電卓を! (1) 一松信 海鳴社 1982

  Y 西暦4桁
  M 月
  D 日付

  有効範囲:1900.3.1~2100.2.28

 ① Y − 1900 = Y
   M <= 2 のとき
    M + 12 = M  (1月を前年13月とする、 2月を前年14月とする)
    Y - 1 = Y

 ② Y + INT( Y / 4 ) + INT(30.6 * ( M - 3) + 0.5 ) + D + 3 = WDAY
     WDAY Mod 7 = w-day
     w-day 0: 日 1:月 2:火 3:水 4:木  5:金 6:土
     割り算計算は小数点以下切り捨て。

(14)pico-playground I2Sオーディオ出力
   amazonで「HiLetgo PCM5102 ラズベリーパイpHATフォーマット用デジタルオーディオボードPCM5102
          I2S IIS用ステレオDAC D/AコンバータPLLボイスモジュール」
   を買って使ってみた。
   
   参照:https://shop.pimoroni.com/products/pimoroni-pico-vga-demo-base

   vscodeからそのままではコンパイルしても音はでない。pimoroniの説明にあるように
   $ cd ~/pico/pico-playground
   $ rm -rf build
   $ mkdir build
   $ cd build
   $ cmake -D"PICO_BOARD=vgaboard" ..
   $ cd apps
   $ make
    手でコンパイルすると、
    apps/usb_sound_card/usb_sound_card.uf2 ができるので、PICOに書き込む。

  配線:
   pico B GND  -> HiLetgo PCM5102 GND
   pico B GP28 -> HiLetgo PCM5102 LCK
   pico B GP27 -> HiLetgo PCM5102 BCK
   pico B GP26 -> HiLetgo PCM5102 DIN
     pico B VSYS -> HiLetgo PCM5102 VIN
     _ _ _ _ _    HiLetgo PCM5102 SCK -> GND 

     AUDIO JACK -> ヘッドホン

   これで音が出るようになる。USBケーブルで接続してSOUNDデバイスを確認する。
     stdioのUARTは変更されるので、配線を変更する。
   ( ~/pico/pico-sdk/src/boards/include/boards/vgaboard.hより)

   picoprobe GP4/UART1 TX -> Pico B GP21/UART1 RX
   picoprobe GP5/UART1 RX -> Pico B GP20/UART1 TX

   確認は、
   $ minicom -b 115200 -D /dev/ttyACM0

   VSCodeでcmakeするには、
   $ cd ~/pico/pico-playground
   $ mkdir .vscode
   $ cp ~/pico/pico-examples/ide/vscode/launch-raspberrypi-swd.json .vscode/launch.json
   $ cp ~/pico/pico-examples/ide/vscode/settings.json .vscode/settings.json

  $ nano ~/pico/pico-playground/.vscode/settings.json
   ---
    "cmake.buildBeforeRun": true,
    "C_Cpp.default.configurationProvider": "ms-vscode.cmake-tools",
    "cmake.configureArgs": [ "-DPICO_BOARD=vgaboard" ], <<<===追加
    "cmake.configureOnOpen": true
   --- 1行追加

   $ nano ~/pico/pico-playground/.vscode/launch.json
  ---
    "gdbPath" : "gdb-multiarch",
    "device": "RP2040",
    "configFiles": [
        "interface/picoprobe.cfg",  <<=raspberrypi-swd.cfg を環境にあわせてpicoprobe.cfgに変更
        "target/rp2040.cfg"
    ],
  ---
[raspi-picoclock.jpg]
2021-01-29  「BLE HID Keyboard」
BBC Micro:bit V2でnRF52833となったのでやってみた。
Micro:bit GOを取り寄せ。
技適マークあり。
[micro-bit-box.jpg]
箱の中の仕切り紙の電池カバーを組み立てる。
[micro-bit-batt.jpg]

まず、電池をつないでみる。
SPから音が出る。A → B ボタン押す。
Get startedの説明書のようにデモが始まる。
・・・・
nRF52 SDKでUARTを使う場合はBoardのヘッダーファイルの
----pca10100.h等------
#define RX_PIN_NUMBER  40    // Micro:bit-v2 USB Serial P1.08
#define TX_PIN_NUMBER  6     // Micro:bit-v2 USB Serial P0.06
を変更するとUSBケーブルをつなぎ、minicomコマンド"minicom -b 115200 -D /dev/ttyACM0"で通信可能になる。
GPIOについては、エッジコネクタP8(P0.10),P9(P0.09)がなぜか使えない。
https://makecode.microbit.org/で作ったSW入力が使えるので普通のGPIOにする手段があるのだろう。
WEB検索したが教えてくれるものが見つからない。
LSM303AGRはnRF52SDKコードで使える。
[micro-bit-temp.jpg]
 nRF52SDKの xamples/peripheral/twi_sensor/ を修正。
(1)Makefile: pcs10040/blank/armgccの 52832 ー> 52833
(2)sdk_config: pcs10040/blank/config
    #define NRFX_TWI0_ENABLED 1
    #define NRFX_TWI1_ENABLED 1    有機ELを使うので。
(3)main.c:
  TWIのインスタンス2個にする。
  TWI割り込み未使用に修正。
  16x16フォント、6x8フォント定義。
  外部TWI手順追加。
  LSM303AGR初期化
      LSM303AGR_ACC_CTRL_REG1 = 0x57 //Accel = 100Hz(Normal mode)
      LSM303AGR_ACC_TEMP_CFG_REG = 0xC0  //Enable Temperetue
      LSM303AGR_MAG_CFG_REG_A = 0x80     //Mag = 10Hz(high-resolution and continuous mode)
                                         // tempereture enable
      LSM303AGR_ACC_CTRL_REG4 = 0x80     //BDU on
      LSM303AGR_MAG_CFG_REG_C = 0x00     //Mag data-ready interrupt disenable
   LSM303AGR温度読み込み
     read_sensor_data(LSM303AGR_ACC_ADDR, LSM303AGR_ACC_OUT_TEMP_L, &ldata);
     read_sensor_data(LSM303AGR_ACC_ADDR, LSM303AGR_ACC_OUT_TEMP_H, &hdata);
    気温 = ((int8_t)hdata) + 25;
   SSD1306制御用の関数作成。
      コマンド単位でひとまとめで転送
    データはバイト単位でも転送可
  SSD1306温度表示作成。
以上が修正の概要。
・・・・
#endif
USB接続してmicro:bitのドライブのなかにあるHTMLを開くと説明書のページが表示される。
フラッシュメモリに書き込んで最初に戻したい場合は、
左メニュー”Out of box experience”より
 [Download the out of box .hex file]ボタンをクリックしてHeXファイルをダウンロードする。
 これをUSB MICROBITドライブにドラッグコピーすると最初の状態になる。
・・・・

コンパイル・書き込みをRaspberry PI/ Raspberry OS (Raspbian)でする。

SDK, Softdeviceダウンロード

https://www.nordicsemi.com/Products/Low-power-short-range-wireless/nRF52833
タグ Download クリック

下の「Download all files as .zip」クリック
(s113_nerf52_7.2.0.zip , nRF5_SDK_17.0.2_d674dde.zip チェックされていること)
DeviceDownload.zipがダウンロードされる

でBLEのプログラムをやってみた。
各ZIPファイルを解凍する。
コンパイラーインストール。
$ sudo apt install gcc-arm-none-eabi
  arm コンパイラインストール

./nRF5_SDK_17.0.2_d674dde/components/toolchain/gcc/Makefile.posix
    コンパイラ情報修正
----Makefile.posix-----
GNU_INSTALL_ROOT ?= /usr/bin/  <<==修正
GNU_VERSION ?= 7.3.1
GNU_PREFIX ?= arm-none-eabi
---修正
  GCCバージョンは /usr/bin/arm-none-eabi-gcc --version で調べる。

./nRF5_SDK_17.0.2_d674dde/examples/ble_peripheral/ble_app_hids_keyboard/pca10100/s113/armgcc
  ble keyboardサンプルコンパイル位置

SDKサンプルのgccディレクトリでMekeできる。

ファイル./nRF5_SDK_17.0.2_d674dde/components/boards/pca10100.h修正

-----patch.1------
--- pca10100-org.h	2020-09-11 14:43:54.000000000 +0900
+++ pca10100.h	2021-01-04 13:21:38.151062040 +0900
@@ -46,49 +46,64 @@
 
 #include "nrf_gpio.h"
 
-// LEDs definitions for PCA10056
-#define LEDS_NUMBER    4
+// LEDs definitions for Micro:bit V2
+#define LEDS_NUMBER    10
 
-#define LED_1          NRF_GPIO_PIN_MAP(0,13)
-#define LED_2          NRF_GPIO_PIN_MAP(0,14)
-#define LED_3          NRF_GPIO_PIN_MAP(0,15)
-#define LED_4          NRF_GPIO_PIN_MAP(0,16)
+#define LED_1          28 // col 1 GPIO P0.28
+#define LED_2          11 // col 2      P0.11
+#define LED_3          31 // col 3      P0.31
+#define LED_4          37 // col 4      P1.05
+#define LED_5          30 // col 5      P0.30
+#define LED_6          21 // row 1      P0.21
+#define LED_7          22 // row 2      P0.22
+#define LED_8          15 // row 3      P0.15
+#define LED_9          24 // row 4      P0.24
+#define LED_10         19 // row 5      P0.19
 #define LED_START      LED_1
-#define LED_STOP       LED_4
+#define LED_STOP       LED_10
 
 #define LEDS_ACTIVE_STATE 0
 
-#define LEDS_LIST { LED_1, LED_2, LED_3, LED_4 }
+#define LEDS_LIST { LED_1, LED_2, LED_3, LED_4, LED_5, LED_6, LED_7, LED_8, LED_9, LED_10 }
 
 #define LEDS_INV_MASK  LEDS_MASK
-
-#define BSP_LED_0      13
-#define BSP_LED_1      14
-#define BSP_LED_2      15
-#define BSP_LED_3      16
-
-#define BUTTONS_NUMBER 4
-
-#define BUTTON_1       11
-#define BUTTON_2       12
-#define BUTTON_3       24
-#define BUTTON_4       25
+// -----------------------LED_1..10 same number
+#define BSP_LED_0      LED_1
+#define BSP_LED_1      LED_2
+#define BSP_LED_2      LED_3
+#define BSP_LED_3      LED_4
+#define BSP_LED_4      LED_5
+#define BSP_LED_5      LED_6
+#define BSP_LED_6      LED_7
+#define BSP_LED_7      LED_8
+#define BSP_LED_8      LED_9
+#define BSP_LED_9      LED_10
+
+#define BUTTONS_NUMBER 2
+
+#define BUTTON_1       14    // BUTTON-A
+#define BUTTON_2       23    // BUTTON-B
+//#define BUTTON_3       24
+//#define BUTTON_4       25
 #define BUTTON_PULL    NRF_GPIO_PIN_PULLUP
 
 #define BUTTONS_ACTIVE_STATE 0
 
-#define BUTTONS_LIST { BUTTON_1, BUTTON_2, BUTTON_3, BUTTON_4 }
+#define BUTTONS_LIST { BUTTON_1, BUTTON_2 }
 
 #define BSP_BUTTON_0   BUTTON_1
 #define BSP_BUTTON_1   BUTTON_2
-#define BSP_BUTTON_2   BUTTON_3
-#define BSP_BUTTON_3   BUTTON_4
+//#define BSP_BUTTON_2   BUTTON_3
+//#define BSP_BUTTON_3   BUTTON_4
 
-#define RX_PIN_NUMBER  8
-#define TX_PIN_NUMBER  6
+//                            // Micro:bit-v2 P0, P1, P2 maybe? Let's try.
+//#define RX_PIN_NUMBER  13   // Micro:bit-v2 P15 OK
+//#define TX_PIN_NUMBER  1    // Micro:bit-v2 P14 OK
+#define RX_PIN_NUMBER  32   // Micro:bit-v2 P20
+#define TX_PIN_NUMBER  26   // Micro:bit-v2 P19
 #define CTS_PIN_NUMBER 7
 #define RTS_PIN_NUMBER 5
-#define HWFC           true
+#define HWFC           false
 
 // serialization APPLICATION board - temp. setup for running serialized MEMU tests
 #define SER_APP_RX_PIN              NRF_GPIO_PIN_MAP(1,13)    // UART RX pin number.
------------
$ patch pca10100.h < patch.1

ファイル./nRF5_SDK_17.0.2_d674dde/examples/ble_peripheral/ble_app_hids_keyboard/main.c修正
-----patch.2-------
--- main-org.c	2020-09-11 14:43:56.000000000 +0900
+++ main.c	2021-01-05 14:39:22.527826352 +0900
@@ -744,6 +744,7 @@
     sensorsim_init(&m_battery_sim_state, &m_battery_sim_cfg);
 }
 
+#if NRF_BLE_CONN_PARAMS_ENABLED==1
 
 /**@brief Function for handling a Connection Parameters error.
  *
@@ -776,7 +777,7 @@
     err_code = ble_conn_params_init(&cp_init);
     APP_ERROR_CHECK(err_code);
 }
-
+#endif
 
 /**@brief Function for starting timers.
  */
@@ -1523,6 +1524,14 @@
     err_code = bsp_init(BSP_INIT_LEDS | BSP_INIT_BUTTONS, bsp_event_handler);
     APP_ERROR_CHECK(err_code);
 
+    //+++++++++++++++++
+    bsp_board_led_off(5);
+    bsp_board_led_on(6);
+    bsp_board_led_on(7);
+    bsp_board_led_on(8);
+    bsp_board_led_on(9);
+    //+++++++++++++++++
+
     err_code = bsp_btn_ble_init(NULL, &startup_event);
     APP_ERROR_CHECK(err_code);
 
@@ -1583,7 +1592,9 @@
     advertising_init();
     services_init();
     sensor_simulator_init();
+#if NRF_BLE_CONN_PARAMS_ENABLED==1
     conn_params_init();
+#endif
     buffer_init();
     peer_manager_init();
 
------------------
$ patch main.c < patch.2

SDKの環境を設定する。
参照:https://www.u-blox.com/sites/default/files/RC-OscillatorConfiguration_AppNote_%28UBX-20009242%29.pdf
RC発信クロック設定方法 config

nRF5_SDK_.../examples/ble_peripheral/ble_app_hids_keyboard/pca10100/s113/config/sdk_config.h
-----
(1)以下のnrfx_clockブロック
// <e> NRFX_CLOCK_ENABLED - nrfx_clock - CLOCK peripheral driver
#define NRFX_CLOCK_CONFIG_LF_SRC 0


(2)nrf_drv_clockブロック
// <e> NRF_CLOCK_ENABLED - nrf_drv_clock - CLOCK peripheral driver - legacy layer
#define CLOCK_CONFIG_LF_SRC 0

(3)SoftDevice clock configurationブロック
// <h> Clock - SoftDevice clock configuration
#define NRF_SDH_CLOCK_LF_SRC 0
#define NRF_SDH_CLOCK_LF_RC_CTIV 16
#define NRF_SDH_CLOCK_LF_RC_TEMP_CTIV 2
#define NRF_SDH_CLOCK_LF_ACCURACY 1

(4)UARTピン
 #define HCI_UART_RX_PIN 32 // Micro:bit-v2 P20
 #define HCI_UART_TX_PIN 26 // Micro:bit-v2 P19
   pca10100.h で定義したもの
 #define HCI_UART_RTS_PIN 16
 #define HCI_UART_CTS_PIN 34
   これは空きピンを割り当てました
 #define NRF_LOG_BACKEND_UART_TX_PIN 26 // Micro:bit-v2 P19
   オリジナルがUART_TXピンと同じだったので

(5)#define NRF_BLE_CONN_PARAMS_ENABLED 0 はWindows10対策

------patch.3------
--- sdk_config-org.h	2020-09-11 14:43:56.000000000 +0900
+++ sdk_config.h	2021-01-05 15:14:16.142926150 +0900
@@ -131,7 +131,7 @@
 // <e> NRF_BLE_CONN_PARAMS_ENABLED - ble_conn_params - Initiating and executing a connection parameters negotiation procedure
 //==========================================================
 #ifndef NRF_BLE_CONN_PARAMS_ENABLED
-#define NRF_BLE_CONN_PARAMS_ENABLED 1
+#define NRF_BLE_CONN_PARAMS_ENABLED 0
 #endif
 // <o> NRF_BLE_CONN_PARAMS_MAX_SLAVE_LATENCY_DEVIATION - The largest acceptable deviation in slave latency. 
 // <i> The largest deviation (+ or -) from the requested slave latency that will not be renegotiated.
@@ -1771,7 +1771,7 @@
 // <196609=> External Full Swing 
 
 #ifndef NRFX_CLOCK_CONFIG_LF_SRC
-#define NRFX_CLOCK_CONFIG_LF_SRC 1
+#define NRFX_CLOCK_CONFIG_LF_SRC 0
 #endif
 
 // <o> NRFX_CLOCK_CONFIG_IRQ_PRIORITY  - Interrupt priority
@@ -4729,7 +4729,7 @@
 // <196609=> External Full Swing 
 
 #ifndef CLOCK_CONFIG_LF_SRC
-#define CLOCK_CONFIG_LF_SRC 1
+#define CLOCK_CONFIG_LF_SRC 0
 #endif
 
 // <q> CLOCK_CONFIG_LF_CAL_ENABLED  - Calibration enable for LF Clock Source
@@ -6731,22 +6731,22 @@
 
 // <o> HCI_UART_RX_PIN - UART RX pin 
 #ifndef HCI_UART_RX_PIN
-#define HCI_UART_RX_PIN 8
+#define HCI_UART_RX_PIN 32 // Micro:bit-v2 P20
 #endif
 
 // <o> HCI_UART_TX_PIN - UART TX pin 
 #ifndef HCI_UART_TX_PIN
-#define HCI_UART_TX_PIN 6
+#define HCI_UART_TX_PIN 26 // Micro:bit-v2 P19
 #endif
 
 // <o> HCI_UART_RTS_PIN - UART RTS pin 
 #ifndef HCI_UART_RTS_PIN
-#define HCI_UART_RTS_PIN 5
+#define HCI_UART_RTS_PIN 16
 #endif
 
 // <o> HCI_UART_CTS_PIN - UART CTS pin 
 #ifndef HCI_UART_CTS_PIN
-#define HCI_UART_CTS_PIN 7
+#define HCI_UART_CTS_PIN 34
 #endif
 
 // </e>
@@ -7581,7 +7581,7 @@
 #endif
 // <o> NRF_LOG_BACKEND_UART_TX_PIN - UART TX pin 
 #ifndef NRF_LOG_BACKEND_UART_TX_PIN
-#define NRF_LOG_BACKEND_UART_TX_PIN 6
+#define NRF_LOG_BACKEND_UART_TX_PIN 26 // Micro:bit-v2 P19
 #endif
 
 // <o> NRF_LOG_BACKEND_UART_BAUDRATE  - Default Baudrate
@@ -11789,12 +11789,12 @@
 // <2=> NRF_CLOCK_LF_SRC_SYNTH 
 
 #ifndef NRF_SDH_CLOCK_LF_SRC
-#define NRF_SDH_CLOCK_LF_SRC 1
+#define NRF_SDH_CLOCK_LF_SRC 0
 #endif
 
 // <o> NRF_SDH_CLOCK_LF_RC_CTIV - SoftDevice calibration timer interval. 
 #ifndef NRF_SDH_CLOCK_LF_RC_CTIV
-#define NRF_SDH_CLOCK_LF_RC_CTIV 0
+#define NRF_SDH_CLOCK_LF_RC_CTIV 16
 #endif
 
 // <o> NRF_SDH_CLOCK_LF_RC_TEMP_CTIV - SoftDevice calibration timer interval under constant temperature. 
@@ -11802,7 +11802,7 @@
 // <i>  if the temperature has not changed.
 
 #ifndef NRF_SDH_CLOCK_LF_RC_TEMP_CTIV
-#define NRF_SDH_CLOCK_LF_RC_TEMP_CTIV 0
+#define NRF_SDH_CLOCK_LF_RC_TEMP_CTIV 2
 #endif
 
 // <o> NRF_SDH_CLOCK_LF_ACCURACY  - External clock accuracy used in the LL to compute timing.
@@ -11821,7 +11821,7 @@
 // <11=> NRF_CLOCK_LF_ACCURACY_1_PPM 
 
 #ifndef NRF_SDH_CLOCK_LF_ACCURACY
-#define NRF_SDH_CLOCK_LF_ACCURACY 7
+#define NRF_SDH_CLOCK_LF_ACCURACY 1
 #endif
 
 // </h> 
-------------------
$ patch sdk_config.h < patch.3

$ make
$ nano cat_softdev.sh
-------------作成
#!/bin/sh
mkdir -p Micro.bit
srec_cat ../../../../../../components/softdevice/s113/hex/s113_nrf52_7.2.0_softdevice.hex -intel _build/nrf52833_xxaa.hex -intel -o _build/micro-bit.hex -intel --line-length=44
cp _build/nrf52833_xxaa.* Micro.bit
cp _build/micro-bit.hex Micro.bit
-------------
  srec_catコマンドは  apt install
  srec_catは1行で実行
 できたHEXファイルとソフトデバイスHEXと合成されたHEXファイルがいる。INTEL-HEXを結合する
$ sudo apt install srecord

$ chmod +x cat_softdev.sh
$ ./cat_softdev.sh

  Micro:bitはUSBケーブルで接続するとメモリードライブとなる。
  Micro.bitディレクトリにできたmicro-bit.hexをUSBメモリのMICROBITドライブにドラッグコピー。
 前もってUSBシリアルケーブル接続して minicom -b 115200 -D /dev/ttyUSB0 コマンド実行するとログが表示。
 プログラム起動時、5x5LEDの左上1個が点滅する。
 Add-deviceリストでペアリングする。5x5LEDの左上1個が点灯する。
 ただし、一度remove-deviceするとその後、リストに表示しなくなる。
 RESETボタンを押しながらか、電源をONする前にボタンB(SHIFTキー)を押しながら、
 RESETボタンを離すか、電源ONするとペアリングリストに表示される。

 ボタンAを押すと1文字入力される。"hello"が繰り返す。ボタンBはシフトキー。
・・・・・・・・・・・・・・・
LEDブリンクをやってみる。

ファイル: ./examples/peripheral/blinky/pca10100e/blank/armgcc/Makefile
---
nrf52820 を nrf52833 に修正する
----patch.1----------
--- Makefile-old	2020-09-11 10:09:32.000000000 +0900
+++ Makefile	2021-01-04 09:27:39.237863000 +0900
@@ -1,16 +1,16 @@
 PROJECT_NAME     := blinky_pca10100e
-TARGETS          := nrf52820_xxaa
+TARGETS          := nrf52833_xxaa
 OUTPUT_DIRECTORY := _build
 
 SDK_ROOT := ../../../../../..
 PROJ_DIR := ../../..
 
-$(OUTPUT_DIRECTORY)/nrf52820_xxaa.out: \
+$(OUTPUT_DIRECTORY)/nrf52833_xxaa.out: \
   LINKER_SCRIPT  := blinky_gcc_nrf52.ld
 
 # Source files common to all targets
 SRC_FILES += \
-  $(SDK_ROOT)/modules/nrfx/mdk/gcc_startup_nrf52820.S \
+  $(SDK_ROOT)/modules/nrfx/mdk/gcc_startup_nrf52833.S \
   $(SDK_ROOT)/components/libraries/log/src/nrf_log_frontend.c \
   $(SDK_ROOT)/components/libraries/log/src/nrf_log_str_formatter.c \
   $(SDK_ROOT)/components/boards/boards.c \
@@ -28,7 +28,7 @@
   $(SDK_ROOT)/components/libraries/strerror/nrf_strerror.c \
   $(SDK_ROOT)/modules/nrfx/soc/nrfx_atomic.c \
   $(PROJ_DIR)/main.c \
-  $(SDK_ROOT)/modules/nrfx/mdk/system_nrf52820.c \
+  $(SDK_ROOT)/modules/nrfx/mdk/system_nrf52833.c \
 
 # Include folders common to all targets
 INC_FOLDERS += \
@@ -70,7 +70,7 @@
 CFLAGS += -DCONFIG_GPIO_AS_PINRESET
 CFLAGS += -DDEVELOP_IN_NRF52833
 CFLAGS += -DFLOAT_ABI_SOFT
-CFLAGS += -DNRF52820_XXAA
+CFLAGS += -DNRF52833_XXAA
 CFLAGS += -DNRFX_COREDEP_DELAY_US_LOOP_CYCLES=3
 CFLAGS += -mcpu=cortex-m4
 CFLAGS += -mthumb -mabi=aapcs
@@ -92,7 +92,7 @@
 ASMFLAGS += -DCONFIG_GPIO_AS_PINRESET
 ASMFLAGS += -DDEVELOP_IN_NRF52833
 ASMFLAGS += -DFLOAT_ABI_SOFT
-ASMFLAGS += -DNRF52820_XXAA
+ASMFLAGS += -DNRF52833_XXAA
 ASMFLAGS += -DNRFX_COREDEP_DELAY_US_LOOP_CYCLES=3
 
 # Linker flags
@@ -104,10 +104,10 @@
 # use newlib in nano version
 LDFLAGS += --specs=nano.specs
 
-nrf52820_xxaa: CFLAGS += -D__HEAP_SIZE=4096
-nrf52820_xxaa: CFLAGS += -D__STACK_SIZE=4096
-nrf52820_xxaa: ASMFLAGS += -D__HEAP_SIZE=4096
-nrf52820_xxaa: ASMFLAGS += -D__STACK_SIZE=4096
+nrf52833_xxaa: CFLAGS += -D__HEAP_SIZE=4096
+nrf52833_xxaa: CFLAGS += -D__STACK_SIZE=4096
+nrf52833_xxaa: ASMFLAGS += -D__HEAP_SIZE=4096
+nrf52833_xxaa: ASMFLAGS += -D__STACK_SIZE=4096
 
 # Add standard libraries at the very end of the linker input, after all objects
 # that may need symbols provided by these libraries.
@@ -117,12 +117,12 @@
 .PHONY: default help
 
 # Default target - first one defined
-default: nrf52820_xxaa
+default: nrf52833_xxaa
 
 # Print all targets that can be built
 help:
 	@echo following targets are available:
-	@echo		nrf52820_xxaa
+	@echo		nrf52833_xxaa
 	@echo		sdk_config - starting external tool for editing sdk_config.h
 	@echo		flash      - flashing binary
 
@@ -137,8 +137,8 @@
 
 # Flash the program
 flash: default
-	@echo Flashing: $(OUTPUT_DIRECTORY)/nrf52820_xxaa.hex
-	nrfjprog -f nrf52 --program $(OUTPUT_DIRECTORY)/nrf52820_xxaa.hex --sectorerase
+	@echo Flashing: $(OUTPUT_DIRECTORY)/nrf52833_xxaa.hex
+	nrfjprog -f nrf52 --program $(OUTPUT_DIRECTORY)/nrf52833_xxaa.hex --sectorerase
 	nrfjprog -f nrf52 --reset
 
 erase:
---------------------
$ patch Makefile < patch.1

---修正

$ nano ./examples/peripheral/blinky/main.c
---
int main(void)
{
    /* Configure board. */
    bsp_board_init(BSP_INIT_LEDS);

    bsp_board_led_on(5);
    bsp_board_led_on(6);
    bsp_board_led_on(7);
    bsp_board_led_on(8);
    bsp_board_led_on(9);

    /* Toggle LEDs. */
    while (true)
    {
        for (int r = 5; r < LEDS_NUMBER; r++ )
        {
            bsp_board_led_off(r);

            for (int i = 0; i < 5; i++)
            {
                bsp_board_led_invert(i);
                nrf_delay_ms(500);

                bsp_board_led_invert(i);
                nrf_delay_ms(500);
            }
 
            bsp_board_led_on(r);
        }
    }
}
---main()を上記のように修正 

$ cd ./examples/peripheral/blinky/pca10100e/blank/armgcc
$ make
$ cd ./examples/peripheral/blinky/pca10100e/blank/armgcc/_build
Micro:bitをUSB接続する。
nrf52833_xxaa.hex をMicro:bit USBドライブにコピーする.
LED 5x5マトリックスのLED1個ずつ点灯、消灯を繰り返す。

・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・
[4key.jpg]
ワイヤレスキーボードを作ってみたくなり6年くらいほったらかしていたNRF51822 Blutooth基板を出してきて始めた。
同じNRF51822デバイスを使っているものは以外といっぱいある。
 スイッチサイエンス HRM1017 (emded, breakout基板)
 太陽誘電 Bluetooth
 Braveridge BVMCN5301   (segger J-link LITE付きがある)
 BBC Micro:bit
   
コンパイル・書き込みをRaspberry PI/ Raspberry OS (Raspbian)でする。
新しいSDKをやってみたけれども、なんともならず時間だけが費やされてしまった。

BLE開発入門 - はんだ付けからファームウェアの書き込みまで
https://qiita.com/k-yamada-github/items/27968882f7f38efda60a

を手がかりに
nrf5-SDK古いバージョン
https://developer.nordicsemi.com/nRF5_SDK/
nrf51_sdk_v6_1_0_b2ec2e6.zip

s110_nrf51822_7.3.0_softdevice
https://www.nordicsemi.com/Software-and-tools/Software/S110/Download#infotabs
s110_nrf51822_7.3.0.zip ダウンロードしたところ(s110 7.3にチェックする)

でBLEのプログラムをやってみた。
各ZIPファイルを解凍する。
コンパイラーインストール。
$ sudo apt install gcc-arm-none-eabi
  arm コンパイラインストール

$ nano nRF5_SDK_xx/nrf51822/Source/templates/gcc/Makefile.posix
---
GNU_INSTALL_ROOT := /usr
GNU_VERSION := 7.3.1
GNU_PREFIX := arm-none-eabi
---修正
  GCCバージョンは /usr/bin/arm-none-eabi-gcc --version で調べる。

SDKサンプルのgccディレクトリでMekeできる。
nRF5_SDK_xx/nrf51822/Source/templates/gcc/gcc_nrf51_xxx_xxx.ldがリンクアドレス設定ファイル。
Makefileの ”DEVICE_VARIANT”、"USE_SOFTDEVICE"で名前が決まる。

$ cd nRF5_SDK_xx/nrf51822/Board/nrf6310/s110/ble_app_hids_keyboard/

$ nano main.c

--
static void ble_stack_init(void)
{
    uint32_t err_code;

    // Initialize the SoftDevice handler module.
    // SOFTDEVICE_HANDLER_INIT(NRF_CLOCK_LFCLKSRC_XTAL_20_PPM, true);
    SOFTDEVICE_HANDLER_INIT(NRF_CLOCK_LFCLKSRC_RC_250_PPM_4000MS_CALIBRATION, true); <<==修正
--
 32KHz内蔵RC発信CLOCKにする。

$ cd gcc
$ make clean
$ make
  LED, BUTTONのポートを変更しなくてもはBLEペアリングテストはできる。

できたHEXファイルとソフトデバイスHEXと合成されたHEXファイルがいる。INTEL-HEXを結合する
$ sudo apt install srecord
$ srec_cat s110_nrf51822_7.3.0_softdevice.hex -intel ble_hids_keyboard110_s110_xxaa.hex -intel -o micro-bit.hex -intel --line-length=44
  コマンド1行で。

Micro:bit, embedはUSBケーブルで接続するとメモリードライブとなるのでドラッグ&ドロップすれば良い。

他の書き込みはBraveridge BVMCN5301に付いていたsegger J-link LITEで書き込み。
書き込みツールは以下の手順で、

https://devzone.nordicsemi.com/f/nordic-q-a/49600/segger-jlink-tools-on-raspberry-pi--
Segger JLink tools on Raspberry Pi -
にあったリンク↓
https://forum.segger.com/index.php/Thread/5693-SOLVED-J-Link-Remote-Server-on-Raspberry-Pi/?s=9291616dfd89fb558f236e94b8574ba7b817ad4f
にあったリンク↓

https://www.segger.com/downloads/jlink/JLink_Linux_arm.tgz
Acceptしてダウンロード

JLink_Linux_V680b_arm.tgz を解凍し、
cd  JLink_Linux_V680b_arm
README.txt にあるコマンドを実行
$ sudo cp 99-jlink.rules /etc/udev/rules.d/
$ sudo reboot
 リブートする

再起動したら  JLink_Linux_V680b_armディレクトリ下で
JLinkExeを実行してフラッシュに書き込む。

$ ./JLinkExe
SEGGER J-Link Commander V6.80b (Compiled Jun  5 2020 17:46:57)
DLL version V6.80b, compiled Jun  5 2020 17:46:38

Connecting to J-Link via USB...O.K.
Firmware: J-Link Lite-Cortex-M V8 compiled Sep 15 2016 12:05:01
Hardware version: V8.00
S/N: 000000000
License(s): GDB
VTref=2.995V


Type "connect" to establish a target connection, '?' for help
J-Link>connect
      =========
Please specify device / core. <Default>: xxx
Type '?' for selection dialog
Device>nrf51822
      =========
Please specify target interface:
  J) JTAG (Default)
  S) SWD
  T) cJTAG
TIF>s
   ===
Specify target interface speed [kHz]. <Default>: 4000 kHz
Speed> <Enter>
     ==========
Device "NRF51822_XXAA" selected.


Connecting to target via SWD
Found SW-DP with ID 0x0BB11477
Unknown DP version. Assuming DPv0
Scanning AP map to find all available APs
AP[1]: Stopped AP scan as end of AP map has been reached
AP[0]: AHB-AP (IDR: 0x04770021)
Iterating through AP map to find AHB-AP to use
AP[0]: Core found
AP[0]: AHB-AP ROM base: 0xF0000000
CPUID register: 0x410CC200. Implementer code: 0x41 (ARM)
Found Cortex-M0 r0p0, Little endian.
FPUnit: 4 code (BP) slots and 0 literal slots
CoreSight components:
ROMTbl[0] @ F0000000
ROMTbl[0][0]: E00FF000, CID: B105100D, PID: 000BB471 ROM Table
ROMTbl[1] @ E00FF000
ROMTbl[1][0]: E000E000, CID: B105E00D, PID: 000BB008 SCS
ROMTbl[1][1]: E0001000, CID: B105E00D, PID: 000BB00A DWT
ROMTbl[1][2]: E0002000, CID: B105E00D, PID: 000BB00B FPB
ROMTbl[0][1]: F0002000, CID: B105900D, PID: 000BB9A3 ???
Cortex-M0 identified.
J-Link>loadfile micro-bit.hex
      ==========================
Downloading file [_BOARD_5103_s110_xxaa.hex]...
Comparing flash   [100%] Done.
Erasing flash     [100%] Done.
Programming flash [100%] Done.
J-Link: Flash download: Bank 0 @ 0x00000000: 1 range affected (47104 bytes)
J-Link: Flash download: Total: 1.755s (Prepare: 0.055s, Compare: 0.020s, Erase: 0.939s, Program & Verify: 0.731s, Restore: 0.008s)
J-Link: Flash download: Program & Verify speed: 63 KB/s
O.K.
J-Link>exit
    ====
....
  リセット・ホルト・GO・イレースは参考文献参照。

参考:
FAQ・テクニカルガイド 「J-Link Commander」ツール - エンビテック
https://www.embitek.co.jp/technote/jlink/JLink_HowToUse_JLinkCommander.pdf
..........................................................................

NRF51-SDKのサンプルは、
--
http://blog.suga41.com/?eid=319
nRF51のサンプルソースは内部クロックに設定されている。(2016.03.10)
--
にあるように内蔵RC16MHzになっている。
.....
NRF_CLOCK->EVENTS_HFCLKSTARTED = 0;
NRF_CLOCK->TASKS_HFCLKSTART    = 1;
while ( NRF_CLOCK->EVENTS_HFCLKSTARTED == 0){
    // イベント待ち
    __NOP();
}
....
のようにすると、
NRF_CLOCK->HFCLKSTAT:00010000 が NRF_CLOCK->HFCLKSTAT:00010001 のように切り替わる。
また、キーSW用 KEY_PRESS_BUTTON_PIN_NOとBOND_DELETE_ALL_BUTTON_ID に割り当てたポートを抵抗でプルアップしないとCPUがSLEEP直後にWAKEUPする。
2020-07-13 「発音辞書検索」
[cmu_dict_use.png]
発音辞書検索を作ろうと思ったのは

Cマガジン 1991.4月号 発音の類似による文字のマッチングアルゴリズム:Metaphone

を発見してから。
同じような発音が似ている語を検索するための発音記号生成アルゴリズムは以下の様なものがある。

  American Soundex
   https://en.wikipedia.org/wiki/Soundex

  Metaphone
   https://en.wikipedia.org/wiki/Metaphone

  NYSIIS (New York State Identification and Intelligence System)
   https://en.wikipedia.org/wiki/New_York_State_Identification_and_Intelligence_System

  Match Rating Codex
   https://en.wikipedia.org/wiki/Match_rating_approach

母音字が注目されていないのがほとんどなので同じ生成記号でも結構引っかかる。

================
参考:
https://pypi.org/project/jellyfish/
jellyfish 0.8.2

sudo apt install python3-jellyfish
python3
---
>>> import jellyfish
>>> jellyfish.metaphone('snow')
'SNW'
>>> jellyfish.soundex('snow')
'S500'
>>> jellyfish.nysiis('snow')
'SNAO'
>>> jellyfish.match_rating_codex('snow')
'SNW'
>>> jellyfish.metaphone('virus')
'FRS'
>>> jellyfish.soundex('virus')
'V620'
>>> jellyfish.match_rating_codex('virus')
'VRS'
>>> jellyfish.nysiis('virus')
'VAR'

発音記号辞書

カーネギーメロン大学のCMU発音辞書を使う。
  http://www.speech.cs.cmu.edu/cgi-bin/cmudict
  The CMU Pronouncing Dictionary
ホムページにある
You can also download the dict from https://github.com/Alexir/CMUdict/blob/master/cmudict-0.7b.
からダウンロードしたcmudict-0.7bを加工して使う。
 35474行目 語の文字コードが崩れているので削除するか"D_J"に修正する。

  DZOKHAR  JH OW2 K AA1 R
  D_C  D IY1 S IY1
  Dxxx  D EY2 JH AA1 <<<=== 35474行目 語の文字コードが崩れているので削除するか"D_J"に修正する。
  E  IY1
  E'S  IY1 Z

発音記号はIPAが一般ですがフォントが特別になるのでアルファベット文字で表現できるARPABETという記号を使う。
 https://ja.wikipedia.org/wiki/ARPABET
 https://en.wikipedia.org/wiki/ARPABET
 ARPABET
インターネットを始めた組織が考えた記号。

この辞書からSqliteデータベースを作成する。これだと語と発音記号だけのものとなる。
--- install_cmu_dict.sh -----
#!/bin/sh
rm cmu_dict.db
cat <<EOF | tee sql.txt
CREATE TABLE alphatb
( word varchar(64) not null,
  arpabet varchar(256));
EOF
sed -e "/^;;.*$/d" -e "s/'/''/g" -e "s/\([^ ]*\)  \(.*\)$/insert into alphatb values \( lower\(\'\1\'\) ,\'\2\'\);/" cmudict-0.7b >> sql.txt
sqlite3 cmu_dict.db < sql.txt
-------------------------------

発音が同じようなものも検索したいのでPython3でSQL文生成前に発音の類似による文字のマッチングアルゴリズムで発音記号生成をしてしまう。
$ sudo apt install sqlite3
$ sudo apt install python3-jellyfish
$ nano cmu_sqlit3.sh
---- cmu_sqlit3.sh -----
#!/bin/sh
rm -f cmu_dict.db
cat <<EOF | tee sql.txt
CREATE TABLE alphatb
( id integer not null,
  word varchar(64) not null,
  arpabet varchar(256),
  metaphone varchar(128),
  soundex varchar(128),
  nysiis varchar(128),
  matchracodex varchar(128) );
EOF
python3 f01.py >> sql.txt
sqlite3 cmu_dict.db < sql.txt
-------
$ chmod +x cmu_sqlit3.sh
$ nano f01.py
------- f01.py -------
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import jellyfish
import re

try:
    file = open("cmudict-0.7b")  # cmu 辞書オープン
    lines = file.readlines()     # 辞書読み込み
    seqn = 0
    for line in lines:           # 1行毎処理
        dic1 = line.rstrip('\n') # 改行コード削除
        if dic1[0] == ';':       # コメント読み飛ばし
            continue
        dictd = re.split('  ', dic1)  # 単語と発音記号分離
        dictw = dictd[0]
        dictw = re.sub(r'^[^A-Z]+| *[ ( ][^ ( ]*[ ) ]',r'', dictw) # 単語先頭記号文字と最後の(数字)削除で発音比較アルゴリズム関数の引数作成
        meta = jellyfish.metaphone(dictw)              # metaphone()
        meta = meta.replace('\'','\'\'')               # 発音比較文字SINGLE-QUOTEを2つにエスケープ
        sndx = jellyfish.soundex(dictw)                # soundex()
        sndx = sndx.replace('\'','\'\'')               # 発音比較文字SINGLE-QUOTEを2つにエスケープ
        nyss = jellyfish.nysiis(dictw)                 # New York State Identification and Intelligence System()
        nyss = nyss.replace('\'','\'\'')               # 発音比較文字SINGLE-QUOTEを2つにエスケープ
        mrcd = jellyfish.match_rating_codex(dictw)     # match rating approach()
        mrcd = mrcd.replace('\'','\'\'')               # 発音比較文字SINGLE-QUOTEを2つにエスケープ
        dictx = dictd[0].replace('\'','\'\'')          # 単語 文字SINGLE-QUOTEを2つにエスケープ
        seqn += 1                                      # 単語連番
        print( 'insert into alphatb values (\''+str(seqn)+'\', lower(\''+ dictx + '\'), \'' + dictd[1] +'\', \''+ meta +'\', \''+ sndx +'\', \''+ nyss +'\', \''+  mrcd +'\');')
              # SQL insert文生成
except Exception as e:
    print(e)
finally:
    file.close()      # cmu 辞書クローズ
-------
$ ./cmu_sqlit3.sh
辞書データベースができる。133852語の発音記号。

検索プログラム

QT5インストール
$ sudo apt install python3-pyqt5 qtcreator qt5-qmake qt5-default

検索画面作成
メインメニューからqtcreator起動し、画面定義を作成する。
-------- cmu_dict_win.ui -------------------
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MainWindow</class>
 <widget class="QMainWindow" name="MainWindow">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>922</width>
    <height>488</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>MainWindow</string>
  </property>
  <widget class="QWidget" name="centralWidget">
   <widget class="QTableWidget" name="tableWidget">
    <property name="geometry">
     <rect>
      <x>20</x>
      <y>100</y>
      <width>881</width>
      <height>348</height>
     </rect>
    </property>
    <property name="font">
     <font>
      <family>Monospace</family>
     </font>
    </property>
    <property name="toolTip">
     <string notr="true"/>
    </property>
    <property name="statusTip">
     <string notr="true"/>
    </property>
    <property name="whatsThis">
     <string notr="true"/>
    </property>
    <property name="layoutDirection">
     <enum>Qt::LeftToRight</enum>
    </property>
    <property name="autoFillBackground">
     <bool>true</bool>
    </property>
    <property name="lineWidth">
     <number>999</number>
    </property>
    <property name="verticalScrollBarPolicy">
     <enum>Qt::ScrollBarAsNeeded</enum>
    </property>
    <property name="horizontalScrollBarPolicy">
     <enum>Qt::ScrollBarAlwaysOn</enum>
    </property>
    <property name="sizeAdjustPolicy">
     <enum>QAbstractScrollArea::AdjustIgnored</enum>
    </property>
    <property name="autoScroll">
     <bool>true</bool>
    </property>
    <property name="horizontalScrollMode">
     <enum>QAbstractItemView::ScrollPerItem</enum>
    </property>
    <property name="showGrid">
     <bool>true</bool>
    </property>
    <property name="gridStyle">
     <enum>Qt::DotLine</enum>
    </property>
    <property name="wordWrap">
     <bool>true</bool>
    </property>
    <property name="cornerButtonEnabled">
     <bool>true</bool>
    </property>
    <property name="rowCount">
     <number>10</number>
    </property>
    <property name="columnCount">
     <number>4</number>
    </property>
    <attribute name="horizontalHeaderVisible">
     <bool>true</bool>
    </attribute>
    <attribute name="horizontalHeaderMinimumSectionSize">
     <number>14</number>
    </attribute>
    <attribute name="verticalHeaderVisible">
     <bool>false</bool>
    </attribute>
    <row/>
    <row/>
    <row/>
    <row/>
    <row/>
    <row/>
    <row/>
    <row/>
    <row/>
    <row/>
    <column/>
    <column/>
    <column/>
    <column/>
    <item row="0" column="0">
     <property name="text">
      <string/>
     </property>
    </item>
    <item row="0" column="1">
     <property name="text">
      <string/>
     </property>
    </item>
   </widget>
   <widget class="QLineEdit" name="lineEWord">
    <property name="geometry">
     <rect>
      <x>20</x>
      <y>30</y>
      <width>591</width>
      <height>32</height>
     </rect>
    </property>
   </widget>
   <widget class="QLabel" name="label">
    <property name="geometry">
     <rect>
      <x>30</x>
      <y>0</y>
      <width>68</width>
      <height>22</height>
     </rect>
    </property>
    <property name="text">
     <string>単語</string>
    </property>
   </widget>
   <widget class="QLabel" name="label_2">
    <property name="geometry">
     <rect>
      <x>630</x>
      <y>0</y>
      <width>281</width>
      <height>22</height>
     </rect>
    </property>
    <property name="text">
     <string>検索方法(マッチ、先頭、後方、部分)</string>
    </property>
   </widget>
   <widget class="QPushButton" name="btnMatch">
    <property name="geometry">
     <rect>
      <x>630</x>
      <y>30</y>
      <width>61</width>
      <height>30</height>
     </rect>
    </property>
    <property name="text">
     <string>■■■</string>
    </property>
   </widget>
   <widget class="QPushButton" name="btnHead">
    <property name="geometry">
     <rect>
      <x>700</x>
      <y>30</y>
      <width>61</width>
      <height>30</height>
     </rect>
    </property>
    <property name="text">
     <string>■■?</string>
    </property>
   </widget>
   <widget class="QPushButton" name="btnTail">
    <property name="geometry">
     <rect>
      <x>770</x>
      <y>30</y>
      <width>61</width>
      <height>30</height>
     </rect>
    </property>
    <property name="text">
     <string>?■■</string>
    </property>
   </widget>
   <widget class="QPushButton" name="btnMiddle">
    <property name="geometry">
     <rect>
      <x>840</x>
      <y>30</y>
      <width>61</width>
      <height>30</height>
     </rect>
    </property>
    <property name="text">
     <string>?■?</string>
    </property>
   </widget>
   <widget class="QRadioButton" name="razBmeta">
    <property name="geometry">
     <rect>
      <x>400</x>
      <y>70</y>
      <width>119</width>
      <height>27</height>
     </rect>
    </property>
    <property name="text">
     <string>&amp;metaphone</string>
    </property>
    <attribute name="buttonGroup">
     <string notr="true">buttonGroup</string>
    </attribute>
   </widget>
   <widget class="QRadioButton" name="razBsndx">
    <property name="geometry">
     <rect>
      <x>520</x>
      <y>70</y>
      <width>101</width>
      <height>27</height>
     </rect>
    </property>
    <property name="text">
     <string>s&amp;oundex</string>
    </property>
    <attribute name="buttonGroup">
     <string notr="true">buttonGroup</string>
    </attribute>
   </widget>
   <widget class="QRadioButton" name="razBnyss">
    <property name="geometry">
     <rect>
      <x>620</x>
      <y>70</y>
      <width>81</width>
      <height>27</height>
     </rect>
    </property>
    <property name="text">
     <string>&amp;NYSIIS</string>
    </property>
    <attribute name="buttonGroup">
     <string notr="true">buttonGroup</string>
    </attribute>
   </widget>
   <widget class="QRadioButton" name="razBmrap">
    <property name="geometry">
     <rect>
      <x>710</x>
      <y>70</y>
      <width>191</width>
      <height>27</height>
     </rect>
    </property>
    <property name="text">
     <string>Mat&amp;ch rating approach </string>
    </property>
    <attribute name="buttonGroup">
     <string notr="true">buttonGroup</string>
    </attribute>
   </widget>
   <widget class="QLabel" name="label_3">
    <property name="geometry">
     <rect>
      <x>220</x>
      <y>70</y>
      <width>171</width>
      <height>22</height>
     </rect>
    </property>
    <property name="text">
     <string>発音比較アルゴリズム:</string>
    </property>
   </widget>
  </widget>
  <widget class="QToolBar" name="mainToolBar">
   <attribute name="toolBarArea">
    <enum>TopToolBarArea</enum>
   </attribute>
   <attribute name="toolBarBreak">
    <bool>false</bool>
   </attribute>
  </widget>
  <widget class="QStatusBar" name="statusBar"/>
 </widget>
 <layoutdefault spacing="6" margin="11"/>
 <resources/>
 <connections/>
 <buttongroups>
  <buttongroup name="buttonGroup"/>
 </buttongroups>
</ui>
--------

検索プログラム
$ nano py.py
----------- py.py -----
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from PyQt5 import uic
import PyQt5.QtCore as QtCore
from PyQt5.QtWidgets import QTableWidget, QRadioButton, QWidget, QSizePolicy, QHeaderView, QMainWindow, QMessageBox, QApplication, QTableWidgetItem
from PyQt5.QtGui import QIcon
from PyQt5 import QtGui, QtWidgets

from subprocess import run, PIPE, Popen
import signal
import time
import sys
import os
import sqlite3
import re

# データベースファイルのパス
dbpath = 'cmu_dict.db'

class GUICmudict(QMainWindow):
    def __init__(self):
        """UIファイルロード、イベントの関連付け、ウィンドウの設定"""

        super().__init__()
        self.currnt_dir = os.path.dirname(os.path.abspath(__file__))
        self.ui = uic.loadUi(self.currnt_dir + '/cmu_dict_win.ui')

        self.ui.setWindowIcon(QIcon(self.currnt_dir+'/Dict.png'))
        self.ui.setWindowTitle("英語発音辞書検索")
        self.ui.btnMatch.clicked.connect(self.sqlMatch)
        self.ui.btnHead.clicked.connect(self.sqlHead)
        self.ui.btnTail.clicked.connect(self.sqlTail)
        self.ui.btnMiddle.clicked.connect(self.sqlMiddle)

        self.ui.razBmeta.setChecked(True)

        self.ui.tableWidget.setAlternatingRowColors(False);  # 1 行おきに色を変える
        app.aboutToQuit.connect(self.closeEvent)  # From http://stackoverflow.com/questions/24532043/proper-way-to-handle-the-close-button-in-a-main-window-pyqt-red-x
        self.ui.tableWidget.setHorizontalHeaderLabels(["","■","","[ARPABET発音記号]"])
        self.ui.tableWidget.horizontalHeader().setStyleSheet("color:Blue;")

        self.ui.tableWidget.horizontalHeader().setDefaultAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
        self.ui.tableWidget.horizontalHeader().setSectionResizeMode(3, QHeaderView.Stretch)
        self.ui.tableWidget.resizeColumnsToContents();

    def normalWin(self):
        """通常表示"""
        self.ui.show()

    def FullScreen(self):
        """フルスクリーン表示"""
        self.ui.showFullScreen()

    def minimized_win(self):
        """ウィンドウをアイコンにする"""
        self.ui.showMinimized()

    def closeEvent(self):
        """システムメニュー[X]がクリックされた"""
        self.ui.close()
        sys.exit(0)

    def sqlMatch(self):
        self.ui.tableWidget.setHorizontalHeaderLabels(["","■","","[ARPABET発音記号]"])
        self.ui.tableWidget.setRowCount(0)
        txtword = self.ui.lineEWord.text()
        self.sqlExec(txtword, 0)

    def sqlHead(self):
        self.ui.tableWidget.setHorizontalHeaderLabels(["■","","","[ARPABET発音記号]"])
        self.ui.tableWidget.setRowCount(0)
        txtword = self.ui.lineEWord.text()
        self.sqlExec(txtword, 1)

    def sqlTail(self):
        self.ui.tableWidget.setHorizontalHeaderLabels(["","","■","[ARPABET発音記号]"])
        self.ui.tableWidget.setRowCount(0)
        txtword = self.ui.lineEWord.text()
        self.sqlExec(txtword, 2)
        #self.ui.tableWidget.setSizeAdjustPolicy(QTableWidget.QAbstractScrollArea.AdjustToContents)
        #self.ui.tableWidget.resizeColumnsToContents();

    def sqlMiddle(self):
        self.ui.tableWidget.setHorizontalHeaderLabels(["","■","","[ARPABET発音記号]"])
        self.ui.tableWidget.setRowCount(0)
        txtword = self.ui.lineEWord.text()
        self.sqlExec(txtword, 3)

    def printWord(self, row, str_word, sqlf):
        numRows = self.ui.tableWidget.rowCount()
        self.ui.tableWidget.insertRow(numRows)     
        #Add text to the row
        str_word = str_word.lower()
        if sqlf == 999:
            item = QTableWidgetItem(row[0])
            item.setBackground(QtGui.QColor(200, 255, 200))
            item.setTextAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
            self.ui.tableWidget.setItem(numRows, 1, item)
        if sqlf == 0:
            item = QTableWidgetItem(str_word)
            item.setBackground(QtGui.QColor(128, 240, 240))
            item.setTextAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
            self.ui.tableWidget.setItem(numRows, 1, item)
        if sqlf == 1:
            item = QTableWidgetItem(str_word)
            item.setTextAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
            item.setBackground(QtGui.QColor(128, 240, 240))
            self.ui.tableWidget.setItem(numRows, 0, item)
            item = QTableWidgetItem(row[0][len(str_word):])
            self.ui.tableWidget.setItem(numRows, 1, item)
        if sqlf == 2:
            item = QTableWidgetItem(row[0][:-len(str_word)])
            item.setTextAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
            self.ui.tableWidget.setItem(numRows, 1, item)
            item = QTableWidgetItem(str_word)
            item.setTextAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
            item.setBackground(QtGui.QColor(128, 240, 240))
            self.ui.tableWidget.setItem(numRows, 2, item)
        if sqlf == 3:
            m = re.search(str_word, row[0])
            item = QTableWidgetItem(row[0][:m.start()])
            item.setTextAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
            self.ui.tableWidget.setItem(numRows, 0, item)
            item = QTableWidgetItem(str_word)
            item.setTextAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
            item.setBackground(QtGui.QColor(128, 240, 240))
            self.ui.tableWidget.setItem(numRows, 1, item)
            item = QTableWidgetItem(row[0][m.end():])
            item.setTextAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
            self.ui.tableWidget.setItem(numRows, 2, item)
        item = QTableWidgetItem(row[1])
        item.setTextAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
        if sqlf == 999:
            item.setBackground(QtGui.QColor(240, 255, 240))
        else:
            item.setBackground(QtGui.QColor(240, 240, 255))
        self.ui.tableWidget.setItem(numRows, 3, item)

    def getBtnX(self):
        if self.ui.razBsndx.isChecked():
             return 1
        elif self.ui.razBnyss.isChecked():
             return 2
        elif self.ui.razBmrap.isChecked():
             return 3
        else:
             return 0

    def sqlExec(self, str_word, sqlf):
        # データベース接続とカーソル生成
        if len(str_word) == 0:
            numRows = self.ui.tableWidget.rowCount()
            self.ui.tableWidget.insertRow(numRows)     
            item = QTableWidgetItem("")
            item.setBackground(QtGui.QColor(255, 255, 255))
            self.ui.tableWidget.setItem(numRows, 0, item)
            item = QTableWidgetItem("Word入力なし")
            item.setBackground(QtGui.QColor(255, 255, 80))
            item.setTextAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
            self.ui.tableWidget.setItem(numRows, 1, item)
            item = QTableWidgetItem("")
            item.setBackground(QtGui.QColor(255, 255, 255))
            self.ui.tableWidget.setItem(numRows, 2, item)
            
        else:
            connection = sqlite3.connect(dbpath)
            # connection.isolation_level = None
            cursor = connection.cursor()
            p1_word = str_word
            if sqlf == 2:
               p1_word = '%' + str_word
            if sqlf == 1:
               p1_word = str_word + '%'
            if sqlf == 3:
               p1_word = '%' + str_word + '%'
        
            cursor.execute('SELECT word, arpabet, metaphone, soundex, nysiis, matchracodex, id FROM alphatb WHERE word like lower(?) ORDER BY word', (p1_word,))
            wsel = 0 
            for row in cursor.fetchall():
                self.printWord(row, str_word, sqlf)
                wsel += 1
            if sqlf == 0 and wsel == 1:
                btnx = self.getBtnX()

                selDBid = ['metaphone', 'soundex', 'nysiis', 'matchracodex'][btnx]
                selw = row[2+btnx]
                idw = row[6]
                numRows = self.ui.tableWidget.rowCount()
                self.ui.tableWidget.insertRow(numRows)     
                item = QTableWidgetItem("★発音類似語★")
                self.ui.tableWidget.setItem(numRows, 3, item)
                cursor.execute('SELECT word, arpabet, metaphone, soundex, nysiis, matchracodex, id FROM alphatb WHERE id!=? and '+selDBid+'=? ORDER BY word', (idw,selw,))
                for row in cursor.fetchall():
                    self.printWord(row, str_word, 999)

            connection.close()
            
        self.ui.tableWidget.resizeColumnsToContents();
        self.ui.tableWidget.horizontalHeader().setSectionResizeMode(3, QHeaderView.Stretch)
 

if __name__ == "__main__":
    app = QApplication(sys.argv)
    win = GUICmudict()
    #win.FullScreen()
    win.normalWin()
    sys.exit(app.exec_())
-----------------------
使い方

ディレクトリ構成
.
├── Dict.png     ...アイコンは名前はこれで、イメージは好みで用意すること。
├── cmu_dict.db
├── cmu_dict_win.ui
└── py.py

$ python3 py.py

単語を入力域に入力し、検索ボタンをクリック。
ボタン”■■■”
 語ひとつ一致結果と似たような発音の語一覧が表示される。
 アルゴリズムはいづれか一つ選択する。
ボタン”■■?”
 語の先頭部分一致一覧が表示される。
 似たような発音の語は出ない。
ボタン”?■■”
 語の後方部分一致一覧が表示される。
 似たような発音の語は出ない。
ボタン”?■?”
 語の中間部分一致一覧が表示される。
 似たような発音の語は出ない。
タイトルバー[X]
 プログラム終了。

-------- プログラムライセンス Copylight (c) k.Shimomura. The MIT License (MIT) --------- 

表紙