オレオレクラスによるシフト(ストリーム)演算子とコンマ(カンマ)演算子オーバーロードを利用したオレオレライブラリ

今までの流れ

  • ここ最近の最終目標は行列計算を使った組込制御
  • ところで「そのコンパイラならc++が使えるかも」と通達された
    • えっclassと標準ライブラリ使っていいのか!?やったー
    • 本当にc++が通った,今まで誰もやってないだけだった…
  • ただしc++98標準にのみ対応,もしくはc99標準にのみ対応
    • かつCPUが特殊で一般的なコンパイラLLVM等)が使えない
    • アライメントの扱いが特殊なせいかEigenが使えなかった
      • オブジェクト生成+リンクはおろかヘッダ導入すら無理
    • vectorはいける感があるらしい,それでなんとかしたい
  • Eigenなし-std=c++98縛りで,似たようなものを実装する

今回やったこと

c++入門ついでにオブジェクト指向コーディング

お題

  • Eigenmatrixを相手に<<を挟んで数字+カンマを含めた入力を扱うことができる
    • M << 1,2,3;
    • ストリームみたいだがストリームではない,たまたまiosクラスが<<>>を使ってるだけ,これはEigenに固有の実装らしい
  • これはとても便利なので,まずはその雛形を作る
    • 入力して出力できればOKです

以下,できたもの

#pragma once
#include <vector>
#include <Grabber.hpp>


namespace MyIO{

    class Grabber;
        //相互参照を設定する

    class Catcher{
        protected:
            std::vector<long double> arr;
                //データを保存する
        public:
            Catcher();
                //コンストラクタ
            ~Catcher();
                //デストラクタ
            Grabber operator<<(long double num);
            // データを"<<"で取る
            // Grabberを呼び出す
            void drainup();
                //溜めたデータを出す
        friend class Grabber;
            //Grabberとの連携を許可する
    };

};
#pragma once
#include <Catcher.hpp>


namespace MyIO{

    class Catcher;
        //相互参照を設定する

    class Grabber{
        protected:
            Catcher &catcherMem;
                //Catcherの参照を保存する
                //(データを返すのに使う)
        public:
            Grabber(Catcher &catcherRef):catcherMem(catcherRef){};
                //Catcherが呼び出せる初期化を定義する
                //Catcherの参照をメンバ変数に保存する
                //今回は明示的な初期化を行わないとダメ
            ~Grabber();
            Grabber& operator,(long double num);
                //データを","で取る
                //自身のポインタを返して再帰処理を行う
        friend class Catcher;
        //Catcherとの連携を許可する
    };

};
#include <iostream>
#include <Catcher.hpp>
#include <Grabber.hpp>


using namespace MyIO;

Catcher::Catcher(){
    std::cout << "Create Catcher" <<std::endl;
};

Catcher::~Catcher(){
    std::cout << "Delete Catcher" <<std::endl;
};

Grabber Catcher::operator<<(long double num){
    arr.assign(1,num);
        //長さ1で初期化して,その先頭にnumを代入する
    std::cout << "Create Grabber" <<std::endl;
    return (Grabber(*this));
        //自身の参照を渡してGrabberを起爆する
        //以降はGrabberが勝手に再起処理を行う
};

void Catcher::drainup(){
    for (size_t i = 0; i < arr.size(); i++){
            std::cout << arr[i] << " ";
    }
    std::cout << std::endl;
    arr.clear();
};
#include <iostream>
#include <Grabber.hpp>
#include <Catcher.hpp>


using namespace MyIO;

Grabber::~Grabber(){
    std::cout << "Delete Grabber" <<std::endl;
};

Grabber& Grabber::operator,(long double num){
    std::cout << "Altern Grabber" <<std::endl;
    catcherMem.arr.push_back(num);
        // 最後にnumを代入する
    return (*this);
        //自身の参照を渡してGrabberを起爆する
        //以降はGrabberが勝手に再起処理を行う
};
NAME  =   test.exe
SRMN    =   main.cpp
SRSB    =   myIO/Catcher.cpp myIO/Grabber.cpp
INCL    =   myIO
OBMN    =   test.exe
OBSB    =   $(SRSB:%.cpp=%.out)
GCCC    =   clang++
GCOP    =   -std=c++98

make    :   $(SRMN) $(SRSB)
    $(GCCC) $(GCOP) $(SRMN) $(SRSB) -I $(INCL) -o $(OBMN)
#include <Catcher.hpp>
#include <Grabber.hpp>


using namespace MyIO;

int main(){

    Catcher foo;

    foo << 1, 2, 3, 4, 5;
    foo.drainup();
    foo << 6, 7, 8, 9, 10;
    foo.drainup();
    long double bar = 1;
    foo << bar/1, bar/2, bar/3, bar/4, bar/5;
    foo.drainup();

};

実行結果

% make      
clang++ -std=c++98 main.cpp myIO/Catcher.cpp myIO/Grabber.cpp -I myIO -o test.exe
% ./test.exe
Create Catcher
Create Grabber
Altern Grabber
Altern Grabber
Altern Grabber
Altern Grabber
Delete Grabber
1 2 3 4 5 
Create Grabber
Altern Grabber
Altern Grabber
Altern Grabber
Altern Grabber
Delete Grabber
6 7 8 9 10 
Create Grabber
Altern Grabber
Altern Grabber
Altern Grabber
Altern Grabber
Delete Grabber
1 0.5 0.333333 0.25 0.2 
Delete Catcher

解説

アルゴリズム

要するに

M;
M << fa,fb,fc;

に対して

  1. 親クラス生成
  2. 算術演算(+-*/)の発生
    • いずれも<<,より優先度が高い
  3. <<演算,親クラス起爆+データ取る+親クラスの参照を持つ子クラス生成
  4. ,演算,子クラス起爆+データ取る(親クラス参照)+子クラス自己参照
  5. ,演算,子クラス起爆+データ取る(親クラス参照)+子クラス自己参照
  6. (以下;が来るまで演算の再帰処理が発生,;が来れば勝手に終了)

を実装すればよい

説明.png

つまり

があればOKと言える

実行結果について

CreateDeleteCatcherGrabberの生成と削除,AlternGrabberの再起 Catcerは1回の生成と削除 Grabberは入力の度に生成と削除,および引数の分だけ再起

名前空間

ヘッダでもソースでも,ファイルが異なっても名前空間は共用できた,便利

相互参照とprotectfriendの併用

クラス定義する前の相互参照の宣言と,protectに接続させるfriendの宣言は,両方とも必要だった privateを選ばなかったのはクラス継承で弄りたくなった時に痛い目をみそうな予感がしてしまったから

コンストラクタ・デストラク

ロギングによって追跡できるようにした,これに加えてコピーコンストラクタもあればコストが把握できる

myClass::myClass(){}; //デフォルトコンストラクタ
myClass::myClass(class arg){}; //引数ありコンストラクタ
myClass::~myClass(){}; //デフォルトデストラクタ,引数はない
myClass::myClass(const myClass &myObject){};  //コピーコンストラクタ,引数は自クラスのオブジェクトの参照

明示的初期化

いまいちよくわからないが(日本語で検索しても引っ掛からなかった)多分

  • デフォルトコンストラクタが定義されていない
  • 自明なデフォルト値がないメンバ変数を抱える

クラスでは一発目の定義の時点でメンバ変数を初期化する必要があるらしい

myClass::myClass(class arg):var(arg){}; //明示的初期化

今回はGrabberで引っかかりコンパイルエラーを吐かれたので修正した なお,引数を加工するメンバ関数をコンストラクタに渡すのはアリらしい

int myClass::fcn(class arg){return arg;}; //引数を加工できる関数を用意する
myClass::myClass(class arg):var(fcn(arg)){}; //それを使って初期化を工夫する

ライブラリ設定

コンパイル時の命令で-I $(PATH)すれば良い,そうすると<myHeader>記法が使えて便利

演算子オーバーロード

以下は一例

classReturn operator _operator_ (class1 arg1[,class2 arg2]){
    classReturn a = fcn(arg1[,arg2]);
    return a;
};

_operator_には使いたい演算子を設定する(ただし設定できないものもある)

演算子オーバーロードをクラス内のpublicメンバ関数で定義しており,かつ左辺の変数のクラスが定義しているクラスと一致する場合は,引数に設定するのは右辺の変数のみで済む(その際thisポインタが左辺の変数を指すため)(下記のような書き方もできなくはないらしい) 右辺の変数に定義しているクラスの変数を使いたいような場合は,(右辺の変数,左辺の変数)の順で引数を2つ定義した上で,アクセスしたいメンバ変数やメンバ関数publicにするか,protectedにした上で演算子オーバーロードfriendに設定する必要があるっぽいな? 要はfriendでまとめて定義した方が管理が楽かも しかし()だけはメンバ関数でやらないといけない あと参照受けするとコピーコスト少ないんじゃないか ちなみに三項演算子オーバーロードできないらしい

感想

マジでなんもわからん状態からここまで持ってこれたのでインターネットの集合知に感謝してる 必要に迫られ次第で年末年始関係なくコーディングが楽しくなってくるってはっきりわかんだね

参考

https://qiita.com/h_hiro_/items/a6484101d87847299885

実際はこちらを再構成したものになりますが,解読と解釈を入れて個人的に読みやすくしました @h_hiro_ さん,大変ありがとうございます,-std==c++98設定でもちゃんと動きました

https://qiita.com/tediousWerk/items/04e61864a20afb4ecee7

右辺にthisポインタがない事情について

https://brain.cc.kogakuin.ac.jp/~kanamaru/lecture/C++2/09/09-03.html

コピーコンストラクタについて

https://hakase0274.hatenablog.com/entry/2019/09/28/200000

明示的初期化について

http://wisdom.sakura.ne.jp/programming/cpp/cpp15.html

thisポインタについて

https://cpprefjp.github.io/reference/vector/vector.html

<vector>について

https://skpme.com/662/

friendについて

https://pknight.hatenablog.com/entry/20090830/1251603528

friend演算子オーバーロードのコンボについて

https://www.ibm.com/docs/ja/xl-c-and-cpp-aix/13.1.0?topic=only-variadic-templates-c11

可変数引数テンプレートというのもあったがそもそもEigenのやり方が便利なので採用しなかった

https://kaworu.jpn.org/cpp/%E3%82%AA%E3%83%BC%E3%83%90%E3%83%BC%E3%83%AD%E3%83%BC%E3%83%89

オーバーロードの概要と事例

https://marycore.jp/prog/cpp/function-object/

()オーバーロードは関数オブジェクトと呼称されるらしい

https://programming-place.net/ppp/contents/cpp/language/019.html

https://programming-place.net/ppp/contents/cpp/language/034.html

あとはここがとても詳しかったと思う

C言語の2次元配列の謎仕様とオレオレマトリックス

これの続き

https://qiita.com/Soluna_Eureka/items/8ff36a03c0bdf7d91de3

概要

  • 前回に続き配列の勉強を始めた
    • charの配列は扱わない
  • オブジェクト指向なオレオレマトリックスを実装した
  • 具体的にはオレオレ構造体に2次元配列をぶち込んだ
    • メモリ(配置と総量)がガバ
    • 1次元配列の方が良いんじゃ(感想に後述する)
  • ついでに行列積を実装した
    • 計算量がガバ($O(n)=3$)
  • その他の要素はだいたい前回と同じだと思って良いよ

設計方針

  • 前回の反省からオレオレオブジェクト専用オレオレ関数は引数をアドレス渡しで実装することにした
    • 4通りのコーディング規約でミニコンペやった結果,記法を変えるためだけにアドレスを1つ食う自己参照構造体を使うのは非効率だという結論が出た
    • 配列のポインタを持つだけのオレオレマトリックスは避ける,オレオレオブジェクトはオレオレオブジェクト以外を参照しないと決めているのだ

以下,出来上がったもの

#ifndef objMtx2d
#define objMtx2d


// matrix method

typedef struct mtx2d {
    int row;
    int clm;
    long double mtx[5][5]; // set enough large size
} mtx2d;

mtx2d defmtx2d(int row, int clm, long double num[row][clm]);

void delmtx2d(mtx2d *adr);

void expmtx2d(mtx2d *adr);

void prdmtx2d(mtx2d *adr0, mtx2d *adr1, mtx2d *adr2);


#endif
#include <stdlib.h>
#include <stdio.h>

#include "objMtx2d.h"


mtx2d defmtx2d(int row, int clm, long double mtx[row][clm]) {
    mtx2d themtx = *((mtx2d*)calloc(1,2*sizeof(int)+(row*clm)*sizeof(long double)));
    themtx.row = row;
    themtx.clm = clm;
    for (int i = 0; i < row; i++) {
        for (int j = 0; j < clm; j++){
            themtx.mtx[i][j] = mtx[i][j];
        }
    }
    return (themtx);
};

void delmtx2d(mtx2d *adr){
    free(adr);
};


void expmtx2d(mtx2d *adr){
    printf("mtx2d =");
    for (int i = 0; i < (adr->row); i++) {
        printf("\n");
        for (int j = 0; j < (adr->clm); j++){
            printf("%Lf, ",(adr->mtx)[i][j]);
        }
    }
    printf("\n");
};

void prdmtx2d(mtx2d *adr0, mtx2d *adr1, mtx2d *adr2){

    int row0 = adr0->row;
    int clm0 = adr0->clm;

    int row1 = adr1->row;
    int clm1 = adr1->clm;
    long double mtx1[row1][clm1];
    for (int i = 0; i < row1; i++) {
        for (int j = 0; j < clm1; j++) {
                mtx1[i][j] = adr1->mtx[i][j];
        }
    }

    int row2 = adr2->row;
    int clm2 = adr2->clm;
    long double mtx2[row2][clm2];
    for (int i = 0; i < row2; i++) {
        for (int j = 0; j < clm2; j++) {
                mtx2[i][j] = adr2->mtx[i][j];
        }
    }
    
    printf("(clm1: %d == row2: %d), ",clm1,row2);
    printf("(clm0: %d == clm2: %d), ",clm0,clm2);
    printf("(raw0: %d == row1: %d)\n",row0,row1);

    long double temp;
    if ((clm1 == row2) && (clm0 == clm2) && (row0 == row1)) {
        printf("condition true : calc production of mtx2d\n");
        for (int i = 0; i < row0; i++) {
            for (int j = 0; j < clm0; j++) {
                temp = 0;
                for (int k = 0; k < row2; k++) {
                    temp = temp + (mtx1[i][k])*(mtx2[k][j]);
                }
                adr0->mtx[i][j] = temp;
            }
        }
    } else {
        printf("condition false : return original matrix\n");
    }
};
#include <stdlib.h>
#include <stdio.h>
#include "objMtx2d.h"


int main(){

    int row = 1;
    int clm = 1;
    long double num[row][clm];
    for (int i = 0; i < row; i++) {
        for (int j = 0; j < clm; j++) {
            num[i][j] = (long double)(0);
        }
    }
    mtx2d mtx = defmtx2d(row, clm, num);

    int row0 = 3;
    int clm0 = 3;
    long double num0[row0][clm0];
    for (int i = 0; i < row0; i++) {
        for (int j = 0; j < clm0; j++) {
            num0[i][j] = (long double)(1);
        }
    }
    mtx2d mtx0 = defmtx2d(row0, clm0, num0);

    int row1 = 4;
    int clm1 = 4;
    long double num1[row1][clm1];
    for (int i = 0; i < row1; i++) {
        for (int j = 0; j < clm1; j++) {
            num1[i][j] = (long double)((i+j+1));
        }
    }
    mtx2d mtx1 = defmtx2d(row1, clm1, num1);

    int row2 = 5;
    int clm2 = 5;
    long double num2[row2][clm2];
    for (int i = 0; i < row2; i++) {
        for (int j = 0; j < clm2; j++) {
            num2[i][j] = (long double)((i+1)*(j+1));
        }
    }
    mtx2d mtx2 = defmtx2d(row2, clm2, num2);

    printf("mtx : ");
    expmtx2d(&mtx);
    printf("mtx0 : ");
    expmtx2d(&mtx0);
    printf("mtx1 : ");
    expmtx2d(&mtx1);
    printf("mtx2 : ");
    expmtx2d(&mtx2);


    for (int i = 0; i < 14; i++){
        prdmtx2d(&mtx0, &mtx0, &mtx0);
        printf("mtx0 : ");
        expmtx2d(&mtx0);
    }



    return(0);
}

機能

  • オレオレマトリックスの定義
    • ただし構造体の定義で最大サイズが決定される,超えたらデータが消える
    • 構造体の配列の初期化とメモリの関係がよくわからないせいかも(感想に後述)
  • オレオレマトリックスの乗算
    • チェック機能を入れたりした,文献は多くあるので
  • main()では以下を意図しているぜ
    • $0\times0$の単位行列でスタート
    • いろんなアルゴリズムで行列を生成
    • 一気に行列を定義しても問題がない
    • 行列の乗算のテスト(これは累乗)

コンパイル,実行

NAME    =   test.exe
SRMN    =   main.c
SRSB    =   objMtx2d.c
OBMN    =   test.exe
OBSB    =   $(SRSB:%.c=%.o)
GCCC    =   clang
GCOP    =   -std=c11 -O2

make    :   $(SRMN) $(SRSB)
    $(GCCC) $(GCOP) $(SRMN) $(SRSB) -o $(OBMN)
% make
% ./test.exe
mtx : mtx2d =
0.000000, 
mtx0 : mtx2d =
1.000000, 1.000000, 1.000000, 
1.000000, 1.000000, 1.000000, 
1.000000, 1.000000, 1.000000, 
mtx1 : mtx2d =
1.000000, 2.000000, 3.000000, 4.000000, 
2.000000, 3.000000, 4.000000, 5.000000, 
3.000000, 4.000000, 5.000000, 6.000000, 
4.000000, 5.000000, 6.000000, 7.000000, 
mtx2 : mtx2d =
1.000000, 2.000000, 3.000000, 4.000000, 5.000000, 
2.000000, 4.000000, 6.000000, 8.000000, 10.000000, 
3.000000, 6.000000, 9.000000, 12.000000, 15.000000, 
4.000000, 8.000000, 12.000000, 16.000000, 20.000000, 
5.000000, 10.000000, 15.000000, 20.000000, 25.000000, 
(clm1: 3 == row2: 3), (clm0: 3 == clm2: 3), (raw0: 3 == row1: 3)
condition true : calc production of mtx2d
mtx0 : mtx2d =
3.000000, 3.000000, 3.000000, 
3.000000, 3.000000, 3.000000, 
3.000000, 3.000000, 3.000000, 
(clm1: 3 == row2: 3), (clm0: 3 == clm2: 3), (raw0: 3 == row1: 3)
condition true : calc production of mtx2d
mtx0 : mtx2d =
27.000000, 27.000000, 27.000000, 
27.000000, 27.000000, 27.000000, 
27.000000, 27.000000, 27.000000, 
(clm1: 3 == row2: 3), (clm0: 3 == clm2: 3), (raw0: 3 == row1: 3)
condition true : calc production of mtx2d
mtx0 : mtx2d =
2187.000000, 2187.000000, 2187.000000, 
2187.000000, 2187.000000, 2187.000000, 
2187.000000, 2187.000000, 2187.000000, 
(clm1: 3 == row2: 3), (clm0: 3 == clm2: 3), (raw0: 3 == row1: 3)
condition true : calc production of mtx2d
mtx0 : mtx2d =
14348907.000000, 14348907.000000, 14348907.000000, 
14348907.000000, 14348907.000000, 14348907.000000, 
14348907.000000, 14348907.000000, 14348907.000000, 
(clm1: 3 == row2: 3), (clm0: 3 == clm2: 3), (raw0: 3 == row1: 3)
condition true : calc production of mtx2d
mtx0 : mtx2d =
617673396283947.000000, 617673396283947.000000, 617673396283947.000000, 
617673396283947.000000, 617673396283947.000000, 617673396283947.000000, 
617673396283947.000000, 617673396283947.000000, 617673396283947.000000, 
(clm1: 3 == row2: 3), (clm0: 3 == clm2: 3), (raw0: 3 == row1: 3)
condition true : calc production of mtx2d
mtx0 : mtx2d =
1144561273430837494845183885312.000000, 1144561273430837494845183885312.000000, 1144561273430837494845183885312.000000, 
1144561273430837494845183885312.000000, 1144561273430837494845183885312.000000, 1144561273430837494845183885312.000000, 
1144561273430837494845183885312.000000, 1144561273430837494845183885312.000000, 1144561273430837494845183885312.000000, 
(clm1: 3 == row2: 3), (clm0: 3 == clm2: 3), (raw0: 3 == row1: 3)
condition true : calc production of mtx2d
mtx0 : mtx2d =
3930061525912861056856039664195120899525747653564164619632640.000000, 3930061525912861056856039664195120899525747653564164619632640.000000, 3930061525912861056856039664195120899525747653564164619632640.000000, 
3930061525912861056856039664195120899525747653564164619632640.000000, 3930061525912861056856039664195120899525747653564164619632640.000000, 3930061525912861056856039664195120899525747653564164619632640.000000, 
3930061525912861056856039664195120899525747653564164619632640.000000, 3930061525912861056856039664195120899525747653564164619632640.000000, 3930061525912861056856039664195120899525747653564164619632640.000000, 
(clm1: 3 == row2: 3), (clm0: 3 == clm2: 3), (raw0: 3 == row1: 3)
condition true : calc production of mtx2d
mtx0 : mtx2d =
46336150792381577580441239896895688970594296724344342106277055401576891261935051484049504936756506018444052709181594009600.000000, 46336150792381577580441239896895688970594296724344342106277055401576891261935051484049504936756506018444052709181594009600.000000, 46336150792381577580441239896895688970594296724344342106277055401576891261935051484049504936756506018444052709181594009600.000000, 
46336150792381577580441239896895688970594296724344342106277055401576891261935051484049504936756506018444052709181594009600.000000, 46336150792381577580441239896895688970594296724344342106277055401576891261935051484049504936756506018444052709181594009600.000000, 46336150792381577580441239896895688970594296724344342106277055401576891261935051484049504936756506018444052709181594009600.000000, 
46336150792381577580441239896895688970594296724344342106277055401576891261935051484049504936756506018444052709181594009600.000000, 46336150792381577580441239896895688970594296724344342106277055401576891261935051484049504936756506018444052709181594009600.000000, 46336150792381577580441239896895688970594296724344342106277055401576891261935051484049504936756506018444052709181594009600.000000, 
(clm1: 3 == row2: 3), (clm0: 3 == clm2: 3), (raw0: 3 == row1: 3)
condition true : calc production of mtx2d
mtx0 : mtx2d =
6441116610762971699604786972075827240991111134226371557890839505381727722959583218110803621947938397785075523545125817931881102592633088605277064533820541832989122656660547839334241610630219753859921180228190705776676535411167326231925937405952.000000, 6441116610762971699604786972075827240991111134226371557890839505381727722959583218110803621947938397785075523545125817931881102592633088605277064533820541832989122656660547839334241610630219753859921180228190705776676535411167326231925937405952.000000, 6441116610762971699604786972075827240991111134226371557890839505381727722959583218110803621947938397785075523545125817931881102592633088605277064533820541832989122656660547839334241610630219753859921180228190705776676535411167326231925937405952.000000, 
6441116610762971699604786972075827240991111134226371557890839505381727722959583218110803621947938397785075523545125817931881102592633088605277064533820541832989122656660547839334241610630219753859921180228190705776676535411167326231925937405952.000000, 6441116610762971699604786972075827240991111134226371557890839505381727722959583218110803621947938397785075523545125817931881102592633088605277064533820541832989122656660547839334241610630219753859921180228190705776676535411167326231925937405952.000000, 6441116610762971699604786972075827240991111134226371557890839505381727722959583218110803621947938397785075523545125817931881102592633088605277064533820541832989122656660547839334241610630219753859921180228190705776676535411167326231925937405952.000000, 
6441116610762971699604786972075827240991111134226371557890839505381727722959583218110803621947938397785075523545125817931881102592633088605277064533820541832989122656660547839334241610630219753859921180228190705776676535411167326231925937405952.000000, 6441116610762971699604786972075827240991111134226371557890839505381727722959583218110803621947938397785075523545125817931881102592633088605277064533820541832989122656660547839334241610630219753859921180228190705776676535411167326231925937405952.000000, 6441116610762971699604786972075827240991111134226371557890839505381727722959583218110803621947938397785075523545125817931881102592633088605277064533820541832989122656660547839334241610630219753859921180228190705776676535411167326231925937405952.000000, 
(clm1: 3 == row2: 3), (clm0: 3 == clm2: 3), (raw0: 3 == row1: 3)
condition true : calc production of mtx2d
mtx0 : mtx2d =
124463949580340014419653854881293695482547961419230733163334979753855664989390762785569734892562797392553558135682283731822586600417439939647875174652473451375277645491415471369918673160129080236883344839284813214990428321837837369612888003083665267539128437282191029741136872138937569842828636845985894146502574920841897524653835593001003177246344623704015411308725532117281723059709552260302528572382799541182616410744022608272022375212282230934581248044375379465853143710073053308256256.000000, 124463949580340014419653854881293695482547961419230733163334979753855664989390762785569734892562797392553558135682283731822586600417439939647875174652473451375277645491415471369918673160129080236883344839284813214990428321837837369612888003083665267539128437282191029741136872138937569842828636845985894146502574920841897524653835593001003177246344623704015411308725532117281723059709552260302528572382799541182616410744022608272022375212282230934581248044375379465853143710073053308256256.000000, 124463949580340014419653854881293695482547961419230733163334979753855664989390762785569734892562797392553558135682283731822586600417439939647875174652473451375277645491415471369918673160129080236883344839284813214990428321837837369612888003083665267539128437282191029741136872138937569842828636845985894146502574920841897524653835593001003177246344623704015411308725532117281723059709552260302528572382799541182616410744022608272022375212282230934581248044375379465853143710073053308256256.000000, 
124463949580340014419653854881293695482547961419230733163334979753855664989390762785569734892562797392553558135682283731822586600417439939647875174652473451375277645491415471369918673160129080236883344839284813214990428321837837369612888003083665267539128437282191029741136872138937569842828636845985894146502574920841897524653835593001003177246344623704015411308725532117281723059709552260302528572382799541182616410744022608272022375212282230934581248044375379465853143710073053308256256.000000, 124463949580340014419653854881293695482547961419230733163334979753855664989390762785569734892562797392553558135682283731822586600417439939647875174652473451375277645491415471369918673160129080236883344839284813214990428321837837369612888003083665267539128437282191029741136872138937569842828636845985894146502574920841897524653835593001003177246344623704015411308725532117281723059709552260302528572382799541182616410744022608272022375212282230934581248044375379465853143710073053308256256.000000, 124463949580340014419653854881293695482547961419230733163334979753855664989390762785569734892562797392553558135682283731822586600417439939647875174652473451375277645491415471369918673160129080236883344839284813214990428321837837369612888003083665267539128437282191029741136872138937569842828636845985894146502574920841897524653835593001003177246344623704015411308725532117281723059709552260302528572382799541182616410744022608272022375212282230934581248044375379465853143710073053308256256.000000, 
124463949580340014419653854881293695482547961419230733163334979753855664989390762785569734892562797392553558135682283731822586600417439939647875174652473451375277645491415471369918673160129080236883344839284813214990428321837837369612888003083665267539128437282191029741136872138937569842828636845985894146502574920841897524653835593001003177246344623704015411308725532117281723059709552260302528572382799541182616410744022608272022375212282230934581248044375379465853143710073053308256256.000000, 124463949580340014419653854881293695482547961419230733163334979753855664989390762785569734892562797392553558135682283731822586600417439939647875174652473451375277645491415471369918673160129080236883344839284813214990428321837837369612888003083665267539128437282191029741136872138937569842828636845985894146502574920841897524653835593001003177246344623704015411308725532117281723059709552260302528572382799541182616410744022608272022375212282230934581248044375379465853143710073053308256256.000000, 124463949580340014419653854881293695482547961419230733163334979753855664989390762785569734892562797392553558135682283731822586600417439939647875174652473451375277645491415471369918673160129080236883344839284813214990428321837837369612888003083665267539128437282191029741136872138937569842828636845985894146502574920841897524653835593001003177246344623704015411308725532117281723059709552260302528572382799541182616410744022608272022375212282230934581248044375379465853143710073053308256256.000000, 
(clm1: 3 == row2: 3), (clm0: 3 == clm2: 3), (raw0: 3 == row1: 3)
condition true : calc production of mtx2d
mtx0 : mtx2d =
46473824235412263755978134112835368131560194921502328749601828231990635994626715194824563401350721101953829823582892400888813058014414453609560392929971404645433550304050434818880460325582796054741841411179903953621375585945153814526147224821501015406343078952178147470174458602664228659680756574839144410024933595855562483030647808658279121849189013407887023014268921602919602221256346179393939216936316431034290583845031853342588518146605182247212196903301453006122253228527568675960210459739645882524863119328545974792107498090708040334466377529024324675975114983970754730545526983508559475608516579838407866848617855124866810254718819976369110029149829420715251914797520614402138443130935064484512030599334460394809369077014630548147215646539402719971324994072453116756050768829750276635579237375103313982181368212127703736957378573683790403332349416239262746725078031422969847438785968130317262384356804054824673287438491585599423639970822171445619235294276204888953192448.000000, 46473824235412263755978134112835368131560194921502328749601828231990635994626715194824563401350721101953829823582892400888813058014414453609560392929971404645433550304050434818880460325582796054741841411179903953621375585945153814526147224821501015406343078952178147470174458602664228659680756574839144410024933595855562483030647808658279121849189013407887023014268921602919602221256346179393939216936316431034290583845031853342588518146605182247212196903301453006122253228527568675960210459739645882524863119328545974792107498090708040334466377529024324675975114983970754730545526983508559475608516579838407866848617855124866810254718819976369110029149829420715251914797520614402138443130935064484512030599334460394809369077014630548147215646539402719971324994072453116756050768829750276635579237375103313982181368212127703736957378573683790403332349416239262746725078031422969847438785968130317262384356804054824673287438491585599423639970822171445619235294276204888953192448.000000, 46473824235412263755978134112835368131560194921502328749601828231990635994626715194824563401350721101953829823582892400888813058014414453609560392929971404645433550304050434818880460325582796054741841411179903953621375585945153814526147224821501015406343078952178147470174458602664228659680756574839144410024933595855562483030647808658279121849189013407887023014268921602919602221256346179393939216936316431034290583845031853342588518146605182247212196903301453006122253228527568675960210459739645882524863119328545974792107498090708040334466377529024324675975114983970754730545526983508559475608516579838407866848617855124866810254718819976369110029149829420715251914797520614402138443130935064484512030599334460394809369077014630548147215646539402719971324994072453116756050768829750276635579237375103313982181368212127703736957378573683790403332349416239262746725078031422969847438785968130317262384356804054824673287438491585599423639970822171445619235294276204888953192448.000000, 
46473824235412263755978134112835368131560194921502328749601828231990635994626715194824563401350721101953829823582892400888813058014414453609560392929971404645433550304050434818880460325582796054741841411179903953621375585945153814526147224821501015406343078952178147470174458602664228659680756574839144410024933595855562483030647808658279121849189013407887023014268921602919602221256346179393939216936316431034290583845031853342588518146605182247212196903301453006122253228527568675960210459739645882524863119328545974792107498090708040334466377529024324675975114983970754730545526983508559475608516579838407866848617855124866810254718819976369110029149829420715251914797520614402138443130935064484512030599334460394809369077014630548147215646539402719971324994072453116756050768829750276635579237375103313982181368212127703736957378573683790403332349416239262746725078031422969847438785968130317262384356804054824673287438491585599423639970822171445619235294276204888953192448.000000, 46473824235412263755978134112835368131560194921502328749601828231990635994626715194824563401350721101953829823582892400888813058014414453609560392929971404645433550304050434818880460325582796054741841411179903953621375585945153814526147224821501015406343078952178147470174458602664228659680756574839144410024933595855562483030647808658279121849189013407887023014268921602919602221256346179393939216936316431034290583845031853342588518146605182247212196903301453006122253228527568675960210459739645882524863119328545974792107498090708040334466377529024324675975114983970754730545526983508559475608516579838407866848617855124866810254718819976369110029149829420715251914797520614402138443130935064484512030599334460394809369077014630548147215646539402719971324994072453116756050768829750276635579237375103313982181368212127703736957378573683790403332349416239262746725078031422969847438785968130317262384356804054824673287438491585599423639970822171445619235294276204888953192448.000000, 46473824235412263755978134112835368131560194921502328749601828231990635994626715194824563401350721101953829823582892400888813058014414453609560392929971404645433550304050434818880460325582796054741841411179903953621375585945153814526147224821501015406343078952178147470174458602664228659680756574839144410024933595855562483030647808658279121849189013407887023014268921602919602221256346179393939216936316431034290583845031853342588518146605182247212196903301453006122253228527568675960210459739645882524863119328545974792107498090708040334466377529024324675975114983970754730545526983508559475608516579838407866848617855124866810254718819976369110029149829420715251914797520614402138443130935064484512030599334460394809369077014630548147215646539402719971324994072453116756050768829750276635579237375103313982181368212127703736957378573683790403332349416239262746725078031422969847438785968130317262384356804054824673287438491585599423639970822171445619235294276204888953192448.000000, 
46473824235412263755978134112835368131560194921502328749601828231990635994626715194824563401350721101953829823582892400888813058014414453609560392929971404645433550304050434818880460325582796054741841411179903953621375585945153814526147224821501015406343078952178147470174458602664228659680756574839144410024933595855562483030647808658279121849189013407887023014268921602919602221256346179393939216936316431034290583845031853342588518146605182247212196903301453006122253228527568675960210459739645882524863119328545974792107498090708040334466377529024324675975114983970754730545526983508559475608516579838407866848617855124866810254718819976369110029149829420715251914797520614402138443130935064484512030599334460394809369077014630548147215646539402719971324994072453116756050768829750276635579237375103313982181368212127703736957378573683790403332349416239262746725078031422969847438785968130317262384356804054824673287438491585599423639970822171445619235294276204888953192448.000000, 46473824235412263755978134112835368131560194921502328749601828231990635994626715194824563401350721101953829823582892400888813058014414453609560392929971404645433550304050434818880460325582796054741841411179903953621375585945153814526147224821501015406343078952178147470174458602664228659680756574839144410024933595855562483030647808658279121849189013407887023014268921602919602221256346179393939216936316431034290583845031853342588518146605182247212196903301453006122253228527568675960210459739645882524863119328545974792107498090708040334466377529024324675975114983970754730545526983508559475608516579838407866848617855124866810254718819976369110029149829420715251914797520614402138443130935064484512030599334460394809369077014630548147215646539402719971324994072453116756050768829750276635579237375103313982181368212127703736957378573683790403332349416239262746725078031422969847438785968130317262384356804054824673287438491585599423639970822171445619235294276204888953192448.000000, 46473824235412263755978134112835368131560194921502328749601828231990635994626715194824563401350721101953829823582892400888813058014414453609560392929971404645433550304050434818880460325582796054741841411179903953621375585945153814526147224821501015406343078952178147470174458602664228659680756574839144410024933595855562483030647808658279121849189013407887023014268921602919602221256346179393939216936316431034290583845031853342588518146605182247212196903301453006122253228527568675960210459739645882524863119328545974792107498090708040334466377529024324675975114983970754730545526983508559475608516579838407866848617855124866810254718819976369110029149829420715251914797520614402138443130935064484512030599334460394809369077014630548147215646539402719971324994072453116756050768829750276635579237375103313982181368212127703736957378573683790403332349416239262746725078031422969847438785968130317262384356804054824673287438491585599423639970822171445619235294276204888953192448.000000, 
(clm1: 3 == row2: 3), (clm0: 3 == clm2: 3), (raw0: 3 == row1: 3)
condition true : calc production of mtx2d
mtx0 : mtx2d =
6479449017191976845284885233438089816275645517799666531122462921699683025830671700582471292904715695124539840006623495665475542481104908223177391979168382521687083369948432382069606287810245217627453907738840674699698004853610039266818536796570058008963195813757672646590660645806552624485934345844294905387103955542458338009186982296160765243701513669441451203268477493025378789555597712822122540668679029244183234805344644951663555100172900430280845293423918050968914319844528102377743450444067715266300545183226106379677851492981244926575133159499481020042866180968604943179348795515632261157153768924366196463385281100743383802549689929029584712014251588999648958525038815625612463203689950707239816109547920833228112245699993360599165364169699710381204091993943328996275370388347649792744804492769608407966381575691468019804649458755490352515104314037877155638653282162590011336350072818835455111849199881566861852187339442404350100265257192844605692092310815365281938337967228827864147384793409636744878827158437704876789888464675180473592530838339855120294515023888380338397093542856393262213429923309344998257625132320676127671576679845956819306194010900749579621077600120672095868980759955420932755813739466126616503895299414189337681880882094421980518249486563188328455886201077377715501586220873108819490358450189757308659188755760708843404237509002753041582734406696457917361015130255972944922145947304753924731682215836971712071343308086688750403275991573389990913748552992287021049764410658340282637811372792284515507794983999311853240549621953033910303743028822949651050403827865852328487473249652665450441403511636771519680335174685204157359702395343576511968114555883841285699068593776301254045829880568214472435726359108852003111166448055797793047117975060746078376370360591368113250262330503311346935116777042243606169637017427648782730262569867780740768147113920814883054772618895868488368503233232869519518179158464460942772640153600.000000, 6479449017191976845284885233438089816275645517799666531122462921699683025830671700582471292904715695124539840006623495665475542481104908223177391979168382521687083369948432382069606287810245217627453907738840674699698004853610039266818536796570058008963195813757672646590660645806552624485934345844294905387103955542458338009186982296160765243701513669441451203268477493025378789555597712822122540668679029244183234805344644951663555100172900430280845293423918050968914319844528102377743450444067715266300545183226106379677851492981244926575133159499481020042866180968604943179348795515632261157153768924366196463385281100743383802549689929029584712014251588999648958525038815625612463203689950707239816109547920833228112245699993360599165364169699710381204091993943328996275370388347649792744804492769608407966381575691468019804649458755490352515104314037877155638653282162590011336350072818835455111849199881566861852187339442404350100265257192844605692092310815365281938337967228827864147384793409636744878827158437704876789888464675180473592530838339855120294515023888380338397093542856393262213429923309344998257625132320676127671576679845956819306194010900749579621077600120672095868980759955420932755813739466126616503895299414189337681880882094421980518249486563188328455886201077377715501586220873108819490358450189757308659188755760708843404237509002753041582734406696457917361015130255972944922145947304753924731682215836971712071343308086688750403275991573389990913748552992287021049764410658340282637811372792284515507794983999311853240549621953033910303743028822949651050403827865852328487473249652665450441403511636771519680335174685204157359702395343576511968114555883841285699068593776301254045829880568214472435726359108852003111166448055797793047117975060746078376370360591368113250262330503311346935116777042243606169637017427648782730262569867780740768147113920814883054772618895868488368503233232869519518179158464460942772640153600.000000, 6479449017191976845284885233438089816275645517799666531122462921699683025830671700582471292904715695124539840006623495665475542481104908223177391979168382521687083369948432382069606287810245217627453907738840674699698004853610039266818536796570058008963195813757672646590660645806552624485934345844294905387103955542458338009186982296160765243701513669441451203268477493025378789555597712822122540668679029244183234805344644951663555100172900430280845293423918050968914319844528102377743450444067715266300545183226106379677851492981244926575133159499481020042866180968604943179348795515632261157153768924366196463385281100743383802549689929029584712014251588999648958525038815625612463203689950707239816109547920833228112245699993360599165364169699710381204091993943328996275370388347649792744804492769608407966381575691468019804649458755490352515104314037877155638653282162590011336350072818835455111849199881566861852187339442404350100265257192844605692092310815365281938337967228827864147384793409636744878827158437704876789888464675180473592530838339855120294515023888380338397093542856393262213429923309344998257625132320676127671576679845956819306194010900749579621077600120672095868980759955420932755813739466126616503895299414189337681880882094421980518249486563188328455886201077377715501586220873108819490358450189757308659188755760708843404237509002753041582734406696457917361015130255972944922145947304753924731682215836971712071343308086688750403275991573389990913748552992287021049764410658340282637811372792284515507794983999311853240549621953033910303743028822949651050403827865852328487473249652665450441403511636771519680335174685204157359702395343576511968114555883841285699068593776301254045829880568214472435726359108852003111166448055797793047117975060746078376370360591368113250262330503311346935116777042243606169637017427648782730262569867780740768147113920814883054772618895868488368503233232869519518179158464460942772640153600.000000, 
6479449017191976845284885233438089816275645517799666531122462921699683025830671700582471292904715695124539840006623495665475542481104908223177391979168382521687083369948432382069606287810245217627453907738840674699698004853610039266818536796570058008963195813757672646590660645806552624485934345844294905387103955542458338009186982296160765243701513669441451203268477493025378789555597712822122540668679029244183234805344644951663555100172900430280845293423918050968914319844528102377743450444067715266300545183226106379677851492981244926575133159499481020042866180968604943179348795515632261157153768924366196463385281100743383802549689929029584712014251588999648958525038815625612463203689950707239816109547920833228112245699993360599165364169699710381204091993943328996275370388347649792744804492769608407966381575691468019804649458755490352515104314037877155638653282162590011336350072818835455111849199881566861852187339442404350100265257192844605692092310815365281938337967228827864147384793409636744878827158437704876789888464675180473592530838339855120294515023888380338397093542856393262213429923309344998257625132320676127671576679845956819306194010900749579621077600120672095868980759955420932755813739466126616503895299414189337681880882094421980518249486563188328455886201077377715501586220873108819490358450189757308659188755760708843404237509002753041582734406696457917361015130255972944922145947304753924731682215836971712071343308086688750403275991573389990913748552992287021049764410658340282637811372792284515507794983999311853240549621953033910303743028822949651050403827865852328487473249652665450441403511636771519680335174685204157359702395343576511968114555883841285699068593776301254045829880568214472435726359108852003111166448055797793047117975060746078376370360591368113250262330503311346935116777042243606169637017427648782730262569867780740768147113920814883054772618895868488368503233232869519518179158464460942772640153600.000000, 6479449017191976845284885233438089816275645517799666531122462921699683025830671700582471292904715695124539840006623495665475542481104908223177391979168382521687083369948432382069606287810245217627453907738840674699698004853610039266818536796570058008963195813757672646590660645806552624485934345844294905387103955542458338009186982296160765243701513669441451203268477493025378789555597712822122540668679029244183234805344644951663555100172900430280845293423918050968914319844528102377743450444067715266300545183226106379677851492981244926575133159499481020042866180968604943179348795515632261157153768924366196463385281100743383802549689929029584712014251588999648958525038815625612463203689950707239816109547920833228112245699993360599165364169699710381204091993943328996275370388347649792744804492769608407966381575691468019804649458755490352515104314037877155638653282162590011336350072818835455111849199881566861852187339442404350100265257192844605692092310815365281938337967228827864147384793409636744878827158437704876789888464675180473592530838339855120294515023888380338397093542856393262213429923309344998257625132320676127671576679845956819306194010900749579621077600120672095868980759955420932755813739466126616503895299414189337681880882094421980518249486563188328455886201077377715501586220873108819490358450189757308659188755760708843404237509002753041582734406696457917361015130255972944922145947304753924731682215836971712071343308086688750403275991573389990913748552992287021049764410658340282637811372792284515507794983999311853240549621953033910303743028822949651050403827865852328487473249652665450441403511636771519680335174685204157359702395343576511968114555883841285699068593776301254045829880568214472435726359108852003111166448055797793047117975060746078376370360591368113250262330503311346935116777042243606169637017427648782730262569867780740768147113920814883054772618895868488368503233232869519518179158464460942772640153600.000000, 6479449017191976845284885233438089816275645517799666531122462921699683025830671700582471292904715695124539840006623495665475542481104908223177391979168382521687083369948432382069606287810245217627453907738840674699698004853610039266818536796570058008963195813757672646590660645806552624485934345844294905387103955542458338009186982296160765243701513669441451203268477493025378789555597712822122540668679029244183234805344644951663555100172900430280845293423918050968914319844528102377743450444067715266300545183226106379677851492981244926575133159499481020042866180968604943179348795515632261157153768924366196463385281100743383802549689929029584712014251588999648958525038815625612463203689950707239816109547920833228112245699993360599165364169699710381204091993943328996275370388347649792744804492769608407966381575691468019804649458755490352515104314037877155638653282162590011336350072818835455111849199881566861852187339442404350100265257192844605692092310815365281938337967228827864147384793409636744878827158437704876789888464675180473592530838339855120294515023888380338397093542856393262213429923309344998257625132320676127671576679845956819306194010900749579621077600120672095868980759955420932755813739466126616503895299414189337681880882094421980518249486563188328455886201077377715501586220873108819490358450189757308659188755760708843404237509002753041582734406696457917361015130255972944922145947304753924731682215836971712071343308086688750403275991573389990913748552992287021049764410658340282637811372792284515507794983999311853240549621953033910303743028822949651050403827865852328487473249652665450441403511636771519680335174685204157359702395343576511968114555883841285699068593776301254045829880568214472435726359108852003111166448055797793047117975060746078376370360591368113250262330503311346935116777042243606169637017427648782730262569867780740768147113920814883054772618895868488368503233232869519518179158464460942772640153600.000000, 
6479449017191976845284885233438089816275645517799666531122462921699683025830671700582471292904715695124539840006623495665475542481104908223177391979168382521687083369948432382069606287810245217627453907738840674699698004853610039266818536796570058008963195813757672646590660645806552624485934345844294905387103955542458338009186982296160765243701513669441451203268477493025378789555597712822122540668679029244183234805344644951663555100172900430280845293423918050968914319844528102377743450444067715266300545183226106379677851492981244926575133159499481020042866180968604943179348795515632261157153768924366196463385281100743383802549689929029584712014251588999648958525038815625612463203689950707239816109547920833228112245699993360599165364169699710381204091993943328996275370388347649792744804492769608407966381575691468019804649458755490352515104314037877155638653282162590011336350072818835455111849199881566861852187339442404350100265257192844605692092310815365281938337967228827864147384793409636744878827158437704876789888464675180473592530838339855120294515023888380338397093542856393262213429923309344998257625132320676127671576679845956819306194010900749579621077600120672095868980759955420932755813739466126616503895299414189337681880882094421980518249486563188328455886201077377715501586220873108819490358450189757308659188755760708843404237509002753041582734406696457917361015130255972944922145947304753924731682215836971712071343308086688750403275991573389990913748552992287021049764410658340282637811372792284515507794983999311853240549621953033910303743028822949651050403827865852328487473249652665450441403511636771519680335174685204157359702395343576511968114555883841285699068593776301254045829880568214472435726359108852003111166448055797793047117975060746078376370360591368113250262330503311346935116777042243606169637017427648782730262569867780740768147113920814883054772618895868488368503233232869519518179158464460942772640153600.000000, 6479449017191976845284885233438089816275645517799666531122462921699683025830671700582471292904715695124539840006623495665475542481104908223177391979168382521687083369948432382069606287810245217627453907738840674699698004853610039266818536796570058008963195813757672646590660645806552624485934345844294905387103955542458338009186982296160765243701513669441451203268477493025378789555597712822122540668679029244183234805344644951663555100172900430280845293423918050968914319844528102377743450444067715266300545183226106379677851492981244926575133159499481020042866180968604943179348795515632261157153768924366196463385281100743383802549689929029584712014251588999648958525038815625612463203689950707239816109547920833228112245699993360599165364169699710381204091993943328996275370388347649792744804492769608407966381575691468019804649458755490352515104314037877155638653282162590011336350072818835455111849199881566861852187339442404350100265257192844605692092310815365281938337967228827864147384793409636744878827158437704876789888464675180473592530838339855120294515023888380338397093542856393262213429923309344998257625132320676127671576679845956819306194010900749579621077600120672095868980759955420932755813739466126616503895299414189337681880882094421980518249486563188328455886201077377715501586220873108819490358450189757308659188755760708843404237509002753041582734406696457917361015130255972944922145947304753924731682215836971712071343308086688750403275991573389990913748552992287021049764410658340282637811372792284515507794983999311853240549621953033910303743028822949651050403827865852328487473249652665450441403511636771519680335174685204157359702395343576511968114555883841285699068593776301254045829880568214472435726359108852003111166448055797793047117975060746078376370360591368113250262330503311346935116777042243606169637017427648782730262569867780740768147113920814883054772618895868488368503233232869519518179158464460942772640153600.000000, 6479449017191976845284885233438089816275645517799666531122462921699683025830671700582471292904715695124539840006623495665475542481104908223177391979168382521687083369948432382069606287810245217627453907738840674699698004853610039266818536796570058008963195813757672646590660645806552624485934345844294905387103955542458338009186982296160765243701513669441451203268477493025378789555597712822122540668679029244183234805344644951663555100172900430280845293423918050968914319844528102377743450444067715266300545183226106379677851492981244926575133159499481020042866180968604943179348795515632261157153768924366196463385281100743383802549689929029584712014251588999648958525038815625612463203689950707239816109547920833228112245699993360599165364169699710381204091993943328996275370388347649792744804492769608407966381575691468019804649458755490352515104314037877155638653282162590011336350072818835455111849199881566861852187339442404350100265257192844605692092310815365281938337967228827864147384793409636744878827158437704876789888464675180473592530838339855120294515023888380338397093542856393262213429923309344998257625132320676127671576679845956819306194010900749579621077600120672095868980759955420932755813739466126616503895299414189337681880882094421980518249486563188328455886201077377715501586220873108819490358450189757308659188755760708843404237509002753041582734406696457917361015130255972944922145947304753924731682215836971712071343308086688750403275991573389990913748552992287021049764410658340282637811372792284515507794983999311853240549621953033910303743028822949651050403827865852328487473249652665450441403511636771519680335174685204157359702395343576511968114555883841285699068593776301254045829880568214472435726359108852003111166448055797793047117975060746078376370360591368113250262330503311346935116777042243606169637017427648782730262569867780740768147113920814883054772618895868488368503233232869519518179158464460942772640153600.000000, 
(clm1: 3 == row2: 3), (clm0: 3 == clm2: 3), (raw0: 3 == row1: 3)
condition true : calc production of mtx2d
mtx0 : mtx2d =
125949778699170223958700868330802362644498167757805517861043843906655386393608952657509971526483249328006268930958321525697159843613810860690520348978460433947913291044736009472691699056484423747154724574769325247895737034100296302373899201469165912117005698942956119217940735979321067543644798953191068100382244283599965501045296770214585553021564051258493468591819355631485727281553786989108882596729120539722507487140216768856522463994718593252675250968712841774809921156252383898706294115210134530395619913749115239791334421562306922697711480325843375805071568927178993124774268511895060372525932228340013309854663443091477801643537356603020568506389033844292474295503672488195206768590193638911162276007464512000007381976822564741551454465141868972336117389513103152404795252149237731936279457813089471443447444265145742957329170149464747852794107936963602510358910617652794325139951960528713662558596949216933681628834436889754008644493027223854539576405990807461307064209205519506784715930801706537631673179811563223601493889346467905676393286580090109753587983383546344842270823133898796776990133600562351982475315101529327858531575362320278825010788291514275188907438394586812443539326408178973721057653280211898518809907284213386057118802893005018388410494596376661510329876136668911996651306744795827551947722142187663870323837220544594382339912947465861402496341675707887793460325434634205298605286153643520649215937098115173345827156431763855222809058248431412724844861386161655377022816831589426393082670540170740562285306287424685356800743921835599065302221899146324185346114422759503904776146041027295638813087962489494381867826918788989691559986165615995566761216614640650520218927342640190742984543967269544699538714531101281523929187312448499665253144386723082642206845738644544483171571497932865513722082729422302598894586781195305257547421791792334615787978717206758194934987888685048870034514410671471336258660193278738194359972802348813897593447768006550825660284793538760965670455153488079083839942514883760532931162958247491162156566192099206208782432492924384691837177831969408858767396038710730504827236862619633003593026779939001004318103180956963832836729256528791144918569289036572423535984972205609520126788459484159402649135080126550555181917686779970420604812467599092708355665388491226556275026479146552056976312047939410232259683806120183682095949398678060909866217628221652668231931901297737000118308457579545810709203213266661820674300023501074339739729719442364642665734217074096923161915304717330666903706782189853738619396829200691502866473144581931797278027868770947107118927155590494076941829121475599722042709464921732260247771618242239441709548530476578659911875330849600093134173584341781886181307866871268728298837297168612881422090885705931252996485274908842125876063244272392931147578726935710366617334758209828176749016189338293868094229756638851002317863308119797687440386114218587371781433214651368875143368035573861662771466277343528967278937670859694430260008525248071007465112622638205966362437455207423171170589520453325413566183678300483594047598734868341639016372093592927342264902837165607263769618288603837522428378298083766379332349687120473442254103276936640635266076086588934557393102026112284472978542418814681241315715616957937166562251420265956100536018524610409526285234079534643942582237947882433788038742332695719626261275220607431398208149268668639220728327029103446352406879678458655796257467140353582840729406085530943943728711574834213088524647400550134899819633377681275893233121150966373087979534931223490274024787563896047226491027278474245828534056160891087995607349582835468904957416116142424753528941851879019803561188033312007323371474034929529879429371372024794390146425624902197710693407779476385017662353942441921560687636817046160707604753412391662260954260256111993794765870159428352808805507167719751698316292912799851479040.000000, 125949778699170223958700868330802362644498167757805517861043843906655386393608952657509971526483249328006268930958321525697159843613810860690520348978460433947913291044736009472691699056484423747154724574769325247895737034100296302373899201469165912117005698942956119217940735979321067543644798953191068100382244283599965501045296770214585553021564051258493468591819355631485727281553786989108882596729120539722507487140216768856522463994718593252675250968712841774809921156252383898706294115210134530395619913749115239791334421562306922697711480325843375805071568927178993124774268511895060372525932228340013309854663443091477801643537356603020568506389033844292474295503672488195206768590193638911162276007464512000007381976822564741551454465141868972336117389513103152404795252149237731936279457813089471443447444265145742957329170149464747852794107936963602510358910617652794325139951960528713662558596949216933681628834436889754008644493027223854539576405990807461307064209205519506784715930801706537631673179811563223601493889346467905676393286580090109753587983383546344842270823133898796776990133600562351982475315101529327858531575362320278825010788291514275188907438394586812443539326408178973721057653280211898518809907284213386057118802893005018388410494596376661510329876136668911996651306744795827551947722142187663870323837220544594382339912947465861402496341675707887793460325434634205298605286153643520649215937098115173345827156431763855222809058248431412724844861386161655377022816831589426393082670540170740562285306287424685356800743921835599065302221899146324185346114422759503904776146041027295638813087962489494381867826918788989691559986165615995566761216614640650520218927342640190742984543967269544699538714531101281523929187312448499665253144386723082642206845738644544483171571497932865513722082729422302598894586781195305257547421791792334615787978717206758194934987888685048870034514410671471336258660193278738194359972802348813897593447768006550825660284793538760965670455153488079083839942514883760532931162958247491162156566192099206208782432492924384691837177831969408858767396038710730504827236862619633003593026779939001004318103180956963832836729256528791144918569289036572423535984972205609520126788459484159402649135080126550555181917686779970420604812467599092708355665388491226556275026479146552056976312047939410232259683806120183682095949398678060909866217628221652668231931901297737000118308457579545810709203213266661820674300023501074339739729719442364642665734217074096923161915304717330666903706782189853738619396829200691502866473144581931797278027868770947107118927155590494076941829121475599722042709464921732260247771618242239441709548530476578659911875330849600093134173584341781886181307866871268728298837297168612881422090885705931252996485274908842125876063244272392931147578726935710366617334758209828176749016189338293868094229756638851002317863308119797687440386114218587371781433214651368875143368035573861662771466277343528967278937670859694430260008525248071007465112622638205966362437455207423171170589520453325413566183678300483594047598734868341639016372093592927342264902837165607263769618288603837522428378298083766379332349687120473442254103276936640635266076086588934557393102026112284472978542418814681241315715616957937166562251420265956100536018524610409526285234079534643942582237947882433788038742332695719626261275220607431398208149268668639220728327029103446352406879678458655796257467140353582840729406085530943943728711574834213088524647400550134899819633377681275893233121150966373087979534931223490274024787563896047226491027278474245828534056160891087995607349582835468904957416116142424753528941851879019803561188033312007323371474034929529879429371372024794390146425624902197710693407779476385017662353942441921560687636817046160707604753412391662260954260256111993794765870159428352808805507167719751698316292912799851479040.000000, 125949778699170223958700868330802362644498167757805517861043843906655386393608952657509971526483249328006268930958321525697159843613810860690520348978460433947913291044736009472691699056484423747154724574769325247895737034100296302373899201469165912117005698942956119217940735979321067543644798953191068100382244283599965501045296770214585553021564051258493468591819355631485727281553786989108882596729120539722507487140216768856522463994718593252675250968712841774809921156252383898706294115210134530395619913749115239791334421562306922697711480325843375805071568927178993124774268511895060372525932228340013309854663443091477801643537356603020568506389033844292474295503672488195206768590193638911162276007464512000007381976822564741551454465141868972336117389513103152404795252149237731936279457813089471443447444265145742957329170149464747852794107936963602510358910617652794325139951960528713662558596949216933681628834436889754008644493027223854539576405990807461307064209205519506784715930801706537631673179811563223601493889346467905676393286580090109753587983383546344842270823133898796776990133600562351982475315101529327858531575362320278825010788291514275188907438394586812443539326408178973721057653280211898518809907284213386057118802893005018388410494596376661510329876136668911996651306744795827551947722142187663870323837220544594382339912947465861402496341675707887793460325434634205298605286153643520649215937098115173345827156431763855222809058248431412724844861386161655377022816831589426393082670540170740562285306287424685356800743921835599065302221899146324185346114422759503904776146041027295638813087962489494381867826918788989691559986165615995566761216614640650520218927342640190742984543967269544699538714531101281523929187312448499665253144386723082642206845738644544483171571497932865513722082729422302598894586781195305257547421791792334615787978717206758194934987888685048870034514410671471336258660193278738194359972802348813897593447768006550825660284793538760965670455153488079083839942514883760532931162958247491162156566192099206208782432492924384691837177831969408858767396038710730504827236862619633003593026779939001004318103180956963832836729256528791144918569289036572423535984972205609520126788459484159402649135080126550555181917686779970420604812467599092708355665388491226556275026479146552056976312047939410232259683806120183682095949398678060909866217628221652668231931901297737000118308457579545810709203213266661820674300023501074339739729719442364642665734217074096923161915304717330666903706782189853738619396829200691502866473144581931797278027868770947107118927155590494076941829121475599722042709464921732260247771618242239441709548530476578659911875330849600093134173584341781886181307866871268728298837297168612881422090885705931252996485274908842125876063244272392931147578726935710366617334758209828176749016189338293868094229756638851002317863308119797687440386114218587371781433214651368875143368035573861662771466277343528967278937670859694430260008525248071007465112622638205966362437455207423171170589520453325413566183678300483594047598734868341639016372093592927342264902837165607263769618288603837522428378298083766379332349687120473442254103276936640635266076086588934557393102026112284472978542418814681241315715616957937166562251420265956100536018524610409526285234079534643942582237947882433788038742332695719626261275220607431398208149268668639220728327029103446352406879678458655796257467140353582840729406085530943943728711574834213088524647400550134899819633377681275893233121150966373087979534931223490274024787563896047226491027278474245828534056160891087995607349582835468904957416116142424753528941851879019803561188033312007323371474034929529879429371372024794390146425624902197710693407779476385017662353942441921560687636817046160707604753412391662260954260256111993794765870159428352808805507167719751698316292912799851479040.000000, 
125949778699170223958700868330802362644498167757805517861043843906655386393608952657509971526483249328006268930958321525697159843613810860690520348978460433947913291044736009472691699056484423747154724574769325247895737034100296302373899201469165912117005698942956119217940735979321067543644798953191068100382244283599965501045296770214585553021564051258493468591819355631485727281553786989108882596729120539722507487140216768856522463994718593252675250968712841774809921156252383898706294115210134530395619913749115239791334421562306922697711480325843375805071568927178993124774268511895060372525932228340013309854663443091477801643537356603020568506389033844292474295503672488195206768590193638911162276007464512000007381976822564741551454465141868972336117389513103152404795252149237731936279457813089471443447444265145742957329170149464747852794107936963602510358910617652794325139951960528713662558596949216933681628834436889754008644493027223854539576405990807461307064209205519506784715930801706537631673179811563223601493889346467905676393286580090109753587983383546344842270823133898796776990133600562351982475315101529327858531575362320278825010788291514275188907438394586812443539326408178973721057653280211898518809907284213386057118802893005018388410494596376661510329876136668911996651306744795827551947722142187663870323837220544594382339912947465861402496341675707887793460325434634205298605286153643520649215937098115173345827156431763855222809058248431412724844861386161655377022816831589426393082670540170740562285306287424685356800743921835599065302221899146324185346114422759503904776146041027295638813087962489494381867826918788989691559986165615995566761216614640650520218927342640190742984543967269544699538714531101281523929187312448499665253144386723082642206845738644544483171571497932865513722082729422302598894586781195305257547421791792334615787978717206758194934987888685048870034514410671471336258660193278738194359972802348813897593447768006550825660284793538760965670455153488079083839942514883760532931162958247491162156566192099206208782432492924384691837177831969408858767396038710730504827236862619633003593026779939001004318103180956963832836729256528791144918569289036572423535984972205609520126788459484159402649135080126550555181917686779970420604812467599092708355665388491226556275026479146552056976312047939410232259683806120183682095949398678060909866217628221652668231931901297737000118308457579545810709203213266661820674300023501074339739729719442364642665734217074096923161915304717330666903706782189853738619396829200691502866473144581931797278027868770947107118927155590494076941829121475599722042709464921732260247771618242239441709548530476578659911875330849600093134173584341781886181307866871268728298837297168612881422090885705931252996485274908842125876063244272392931147578726935710366617334758209828176749016189338293868094229756638851002317863308119797687440386114218587371781433214651368875143368035573861662771466277343528967278937670859694430260008525248071007465112622638205966362437455207423171170589520453325413566183678300483594047598734868341639016372093592927342264902837165607263769618288603837522428378298083766379332349687120473442254103276936640635266076086588934557393102026112284472978542418814681241315715616957937166562251420265956100536018524610409526285234079534643942582237947882433788038742332695719626261275220607431398208149268668639220728327029103446352406879678458655796257467140353582840729406085530943943728711574834213088524647400550134899819633377681275893233121150966373087979534931223490274024787563896047226491027278474245828534056160891087995607349582835468904957416116142424753528941851879019803561188033312007323371474034929529879429371372024794390146425624902197710693407779476385017662353942441921560687636817046160707604753412391662260954260256111993794765870159428352808805507167719751698316292912799851479040.000000, 125949778699170223958700868330802362644498167757805517861043843906655386393608952657509971526483249328006268930958321525697159843613810860690520348978460433947913291044736009472691699056484423747154724574769325247895737034100296302373899201469165912117005698942956119217940735979321067543644798953191068100382244283599965501045296770214585553021564051258493468591819355631485727281553786989108882596729120539722507487140216768856522463994718593252675250968712841774809921156252383898706294115210134530395619913749115239791334421562306922697711480325843375805071568927178993124774268511895060372525932228340013309854663443091477801643537356603020568506389033844292474295503672488195206768590193638911162276007464512000007381976822564741551454465141868972336117389513103152404795252149237731936279457813089471443447444265145742957329170149464747852794107936963602510358910617652794325139951960528713662558596949216933681628834436889754008644493027223854539576405990807461307064209205519506784715930801706537631673179811563223601493889346467905676393286580090109753587983383546344842270823133898796776990133600562351982475315101529327858531575362320278825010788291514275188907438394586812443539326408178973721057653280211898518809907284213386057118802893005018388410494596376661510329876136668911996651306744795827551947722142187663870323837220544594382339912947465861402496341675707887793460325434634205298605286153643520649215937098115173345827156431763855222809058248431412724844861386161655377022816831589426393082670540170740562285306287424685356800743921835599065302221899146324185346114422759503904776146041027295638813087962489494381867826918788989691559986165615995566761216614640650520218927342640190742984543967269544699538714531101281523929187312448499665253144386723082642206845738644544483171571497932865513722082729422302598894586781195305257547421791792334615787978717206758194934987888685048870034514410671471336258660193278738194359972802348813897593447768006550825660284793538760965670455153488079083839942514883760532931162958247491162156566192099206208782432492924384691837177831969408858767396038710730504827236862619633003593026779939001004318103180956963832836729256528791144918569289036572423535984972205609520126788459484159402649135080126550555181917686779970420604812467599092708355665388491226556275026479146552056976312047939410232259683806120183682095949398678060909866217628221652668231931901297737000118308457579545810709203213266661820674300023501074339739729719442364642665734217074096923161915304717330666903706782189853738619396829200691502866473144581931797278027868770947107118927155590494076941829121475599722042709464921732260247771618242239441709548530476578659911875330849600093134173584341781886181307866871268728298837297168612881422090885705931252996485274908842125876063244272392931147578726935710366617334758209828176749016189338293868094229756638851002317863308119797687440386114218587371781433214651368875143368035573861662771466277343528967278937670859694430260008525248071007465112622638205966362437455207423171170589520453325413566183678300483594047598734868341639016372093592927342264902837165607263769618288603837522428378298083766379332349687120473442254103276936640635266076086588934557393102026112284472978542418814681241315715616957937166562251420265956100536018524610409526285234079534643942582237947882433788038742332695719626261275220607431398208149268668639220728327029103446352406879678458655796257467140353582840729406085530943943728711574834213088524647400550134899819633377681275893233121150966373087979534931223490274024787563896047226491027278474245828534056160891087995607349582835468904957416116142424753528941851879019803561188033312007323371474034929529879429371372024794390146425624902197710693407779476385017662353942441921560687636817046160707604753412391662260954260256111993794765870159428352808805507167719751698316292912799851479040.000000, 125949778699170223958700868330802362644498167757805517861043843906655386393608952657509971526483249328006268930958321525697159843613810860690520348978460433947913291044736009472691699056484423747154724574769325247895737034100296302373899201469165912117005698942956119217940735979321067543644798953191068100382244283599965501045296770214585553021564051258493468591819355631485727281553786989108882596729120539722507487140216768856522463994718593252675250968712841774809921156252383898706294115210134530395619913749115239791334421562306922697711480325843375805071568927178993124774268511895060372525932228340013309854663443091477801643537356603020568506389033844292474295503672488195206768590193638911162276007464512000007381976822564741551454465141868972336117389513103152404795252149237731936279457813089471443447444265145742957329170149464747852794107936963602510358910617652794325139951960528713662558596949216933681628834436889754008644493027223854539576405990807461307064209205519506784715930801706537631673179811563223601493889346467905676393286580090109753587983383546344842270823133898796776990133600562351982475315101529327858531575362320278825010788291514275188907438394586812443539326408178973721057653280211898518809907284213386057118802893005018388410494596376661510329876136668911996651306744795827551947722142187663870323837220544594382339912947465861402496341675707887793460325434634205298605286153643520649215937098115173345827156431763855222809058248431412724844861386161655377022816831589426393082670540170740562285306287424685356800743921835599065302221899146324185346114422759503904776146041027295638813087962489494381867826918788989691559986165615995566761216614640650520218927342640190742984543967269544699538714531101281523929187312448499665253144386723082642206845738644544483171571497932865513722082729422302598894586781195305257547421791792334615787978717206758194934987888685048870034514410671471336258660193278738194359972802348813897593447768006550825660284793538760965670455153488079083839942514883760532931162958247491162156566192099206208782432492924384691837177831969408858767396038710730504827236862619633003593026779939001004318103180956963832836729256528791144918569289036572423535984972205609520126788459484159402649135080126550555181917686779970420604812467599092708355665388491226556275026479146552056976312047939410232259683806120183682095949398678060909866217628221652668231931901297737000118308457579545810709203213266661820674300023501074339739729719442364642665734217074096923161915304717330666903706782189853738619396829200691502866473144581931797278027868770947107118927155590494076941829121475599722042709464921732260247771618242239441709548530476578659911875330849600093134173584341781886181307866871268728298837297168612881422090885705931252996485274908842125876063244272392931147578726935710366617334758209828176749016189338293868094229756638851002317863308119797687440386114218587371781433214651368875143368035573861662771466277343528967278937670859694430260008525248071007465112622638205966362437455207423171170589520453325413566183678300483594047598734868341639016372093592927342264902837165607263769618288603837522428378298083766379332349687120473442254103276936640635266076086588934557393102026112284472978542418814681241315715616957937166562251420265956100536018524610409526285234079534643942582237947882433788038742332695719626261275220607431398208149268668639220728327029103446352406879678458655796257467140353582840729406085530943943728711574834213088524647400550134899819633377681275893233121150966373087979534931223490274024787563896047226491027278474245828534056160891087995607349582835468904957416116142424753528941851879019803561188033312007323371474034929529879429371372024794390146425624902197710693407779476385017662353942441921560687636817046160707604753412391662260954260256111993794765870159428352808805507167719751698316292912799851479040.000000, 
125949778699170223958700868330802362644498167757805517861043843906655386393608952657509971526483249328006268930958321525697159843613810860690520348978460433947913291044736009472691699056484423747154724574769325247895737034100296302373899201469165912117005698942956119217940735979321067543644798953191068100382244283599965501045296770214585553021564051258493468591819355631485727281553786989108882596729120539722507487140216768856522463994718593252675250968712841774809921156252383898706294115210134530395619913749115239791334421562306922697711480325843375805071568927178993124774268511895060372525932228340013309854663443091477801643537356603020568506389033844292474295503672488195206768590193638911162276007464512000007381976822564741551454465141868972336117389513103152404795252149237731936279457813089471443447444265145742957329170149464747852794107936963602510358910617652794325139951960528713662558596949216933681628834436889754008644493027223854539576405990807461307064209205519506784715930801706537631673179811563223601493889346467905676393286580090109753587983383546344842270823133898796776990133600562351982475315101529327858531575362320278825010788291514275188907438394586812443539326408178973721057653280211898518809907284213386057118802893005018388410494596376661510329876136668911996651306744795827551947722142187663870323837220544594382339912947465861402496341675707887793460325434634205298605286153643520649215937098115173345827156431763855222809058248431412724844861386161655377022816831589426393082670540170740562285306287424685356800743921835599065302221899146324185346114422759503904776146041027295638813087962489494381867826918788989691559986165615995566761216614640650520218927342640190742984543967269544699538714531101281523929187312448499665253144386723082642206845738644544483171571497932865513722082729422302598894586781195305257547421791792334615787978717206758194934987888685048870034514410671471336258660193278738194359972802348813897593447768006550825660284793538760965670455153488079083839942514883760532931162958247491162156566192099206208782432492924384691837177831969408858767396038710730504827236862619633003593026779939001004318103180956963832836729256528791144918569289036572423535984972205609520126788459484159402649135080126550555181917686779970420604812467599092708355665388491226556275026479146552056976312047939410232259683806120183682095949398678060909866217628221652668231931901297737000118308457579545810709203213266661820674300023501074339739729719442364642665734217074096923161915304717330666903706782189853738619396829200691502866473144581931797278027868770947107118927155590494076941829121475599722042709464921732260247771618242239441709548530476578659911875330849600093134173584341781886181307866871268728298837297168612881422090885705931252996485274908842125876063244272392931147578726935710366617334758209828176749016189338293868094229756638851002317863308119797687440386114218587371781433214651368875143368035573861662771466277343528967278937670859694430260008525248071007465112622638205966362437455207423171170589520453325413566183678300483594047598734868341639016372093592927342264902837165607263769618288603837522428378298083766379332349687120473442254103276936640635266076086588934557393102026112284472978542418814681241315715616957937166562251420265956100536018524610409526285234079534643942582237947882433788038742332695719626261275220607431398208149268668639220728327029103446352406879678458655796257467140353582840729406085530943943728711574834213088524647400550134899819633377681275893233121150966373087979534931223490274024787563896047226491027278474245828534056160891087995607349582835468904957416116142424753528941851879019803561188033312007323371474034929529879429371372024794390146425624902197710693407779476385017662353942441921560687636817046160707604753412391662260954260256111993794765870159428352808805507167719751698316292912799851479040.000000, 125949778699170223958700868330802362644498167757805517861043843906655386393608952657509971526483249328006268930958321525697159843613810860690520348978460433947913291044736009472691699056484423747154724574769325247895737034100296302373899201469165912117005698942956119217940735979321067543644798953191068100382244283599965501045296770214585553021564051258493468591819355631485727281553786989108882596729120539722507487140216768856522463994718593252675250968712841774809921156252383898706294115210134530395619913749115239791334421562306922697711480325843375805071568927178993124774268511895060372525932228340013309854663443091477801643537356603020568506389033844292474295503672488195206768590193638911162276007464512000007381976822564741551454465141868972336117389513103152404795252149237731936279457813089471443447444265145742957329170149464747852794107936963602510358910617652794325139951960528713662558596949216933681628834436889754008644493027223854539576405990807461307064209205519506784715930801706537631673179811563223601493889346467905676393286580090109753587983383546344842270823133898796776990133600562351982475315101529327858531575362320278825010788291514275188907438394586812443539326408178973721057653280211898518809907284213386057118802893005018388410494596376661510329876136668911996651306744795827551947722142187663870323837220544594382339912947465861402496341675707887793460325434634205298605286153643520649215937098115173345827156431763855222809058248431412724844861386161655377022816831589426393082670540170740562285306287424685356800743921835599065302221899146324185346114422759503904776146041027295638813087962489494381867826918788989691559986165615995566761216614640650520218927342640190742984543967269544699538714531101281523929187312448499665253144386723082642206845738644544483171571497932865513722082729422302598894586781195305257547421791792334615787978717206758194934987888685048870034514410671471336258660193278738194359972802348813897593447768006550825660284793538760965670455153488079083839942514883760532931162958247491162156566192099206208782432492924384691837177831969408858767396038710730504827236862619633003593026779939001004318103180956963832836729256528791144918569289036572423535984972205609520126788459484159402649135080126550555181917686779970420604812467599092708355665388491226556275026479146552056976312047939410232259683806120183682095949398678060909866217628221652668231931901297737000118308457579545810709203213266661820674300023501074339739729719442364642665734217074096923161915304717330666903706782189853738619396829200691502866473144581931797278027868770947107118927155590494076941829121475599722042709464921732260247771618242239441709548530476578659911875330849600093134173584341781886181307866871268728298837297168612881422090885705931252996485274908842125876063244272392931147578726935710366617334758209828176749016189338293868094229756638851002317863308119797687440386114218587371781433214651368875143368035573861662771466277343528967278937670859694430260008525248071007465112622638205966362437455207423171170589520453325413566183678300483594047598734868341639016372093592927342264902837165607263769618288603837522428378298083766379332349687120473442254103276936640635266076086588934557393102026112284472978542418814681241315715616957937166562251420265956100536018524610409526285234079534643942582237947882433788038742332695719626261275220607431398208149268668639220728327029103446352406879678458655796257467140353582840729406085530943943728711574834213088524647400550134899819633377681275893233121150966373087979534931223490274024787563896047226491027278474245828534056160891087995607349582835468904957416116142424753528941851879019803561188033312007323371474034929529879429371372024794390146425624902197710693407779476385017662353942441921560687636817046160707604753412391662260954260256111993794765870159428352808805507167719751698316292912799851479040.000000, 125949778699170223958700868330802362644498167757805517861043843906655386393608952657509971526483249328006268930958321525697159843613810860690520348978460433947913291044736009472691699056484423747154724574769325247895737034100296302373899201469165912117005698942956119217940735979321067543644798953191068100382244283599965501045296770214585553021564051258493468591819355631485727281553786989108882596729120539722507487140216768856522463994718593252675250968712841774809921156252383898706294115210134530395619913749115239791334421562306922697711480325843375805071568927178993124774268511895060372525932228340013309854663443091477801643537356603020568506389033844292474295503672488195206768590193638911162276007464512000007381976822564741551454465141868972336117389513103152404795252149237731936279457813089471443447444265145742957329170149464747852794107936963602510358910617652794325139951960528713662558596949216933681628834436889754008644493027223854539576405990807461307064209205519506784715930801706537631673179811563223601493889346467905676393286580090109753587983383546344842270823133898796776990133600562351982475315101529327858531575362320278825010788291514275188907438394586812443539326408178973721057653280211898518809907284213386057118802893005018388410494596376661510329876136668911996651306744795827551947722142187663870323837220544594382339912947465861402496341675707887793460325434634205298605286153643520649215937098115173345827156431763855222809058248431412724844861386161655377022816831589426393082670540170740562285306287424685356800743921835599065302221899146324185346114422759503904776146041027295638813087962489494381867826918788989691559986165615995566761216614640650520218927342640190742984543967269544699538714531101281523929187312448499665253144386723082642206845738644544483171571497932865513722082729422302598894586781195305257547421791792334615787978717206758194934987888685048870034514410671471336258660193278738194359972802348813897593447768006550825660284793538760965670455153488079083839942514883760532931162958247491162156566192099206208782432492924384691837177831969408858767396038710730504827236862619633003593026779939001004318103180956963832836729256528791144918569289036572423535984972205609520126788459484159402649135080126550555181917686779970420604812467599092708355665388491226556275026479146552056976312047939410232259683806120183682095949398678060909866217628221652668231931901297737000118308457579545810709203213266661820674300023501074339739729719442364642665734217074096923161915304717330666903706782189853738619396829200691502866473144581931797278027868770947107118927155590494076941829121475599722042709464921732260247771618242239441709548530476578659911875330849600093134173584341781886181307866871268728298837297168612881422090885705931252996485274908842125876063244272392931147578726935710366617334758209828176749016189338293868094229756638851002317863308119797687440386114218587371781433214651368875143368035573861662771466277343528967278937670859694430260008525248071007465112622638205966362437455207423171170589520453325413566183678300483594047598734868341639016372093592927342264902837165607263769618288603837522428378298083766379332349687120473442254103276936640635266076086588934557393102026112284472978542418814681241315715616957937166562251420265956100536018524610409526285234079534643942582237947882433788038742332695719626261275220607431398208149268668639220728327029103446352406879678458655796257467140353582840729406085530943943728711574834213088524647400550134899819633377681275893233121150966373087979534931223490274024787563896047226491027278474245828534056160891087995607349582835468904957416116142424753528941851879019803561188033312007323371474034929529879429371372024794390146425624902197710693407779476385017662353942441921560687636817046160707604753412391662260954260256111993794765870159428352808805507167719751698316292912799851479040.000000, 
(clm1: 3 == row2: 3), (clm0: 3 == clm2: 3), (raw0: 3 == row1: 3)
condition true : calc production of mtx2d
mtx0 : mtx2d =
inf, inf, inf, 
inf, inf, inf, 
inf, inf, inf, 

long doubleでもあっという間にinfになる,非単位行列・非零行列の自乗とは恐ろしいものである

感想

  • 多次元方向の配列サイズの初期化が十分にできないcの構造体を使うなら,結局は1次元配列でやった方がメモリがスマートになるよな…?
    • どうせオレオレマトリックスの演算の実装は表からは見えないんだし,多少はコードが汚くても理解できればそれで十分かもしれないね
  • 構造体のメンバ変数に2次元配列の最大サイズを定義する時に,あまりにも大きすぎるとスタックサイズの上限を超えてセグフォを吐く
    • 要はオブジェクトを実体化させる前に構造体を呼び出した時点でセグフォが起きているので,これは明らかに欠陥的な実装である
    • 最大サイズより小さい設定で()calloc()しても問題がなかった理由にも密接に関わってくる,structの仕様を理解しなければ…

参考

https://qiita.com/t-yama-3/items/e3304cc4dce2193f9300

https://tondol.hatenablog.jp/entry/20090713/1247426321

http://mitsunagistudio.net/old_posts/tips/variable_length/

↑ どうもこの記事の挙動と手元の挙動が違う [1][1]で構造体を設定すると動かない 実装というか処理の場所が違うせいなの?

https://webkaru.net/clang/matrix-multiplication/

https://qiita.com/tyoshitake/items/83ce47f169c5b037f06c

cの2次元配列のメモリはrow-major orderで設置されるらしいが,ここで*((mtx2d*)calloc(1,size))して得たmtx2dでメモリを確保して,そこにmtx2d.mtx[100][100]が入りきらない(sizeが小さい)場合は,あくまでmtx2d.mtx[100][100]の一部を使うんだろと(直感的には)思うけど,その場合はrow-major orderのせいで任意の形状の配列が必ず使えるとは限らないと(直感的には)思う しかし今回の実装ではそういった問題は起きていない,確かに前回の自己参照構造体は他の構造体や自己参照ポインタのサイズが自動的に勘定されない問題があったが,今回は構造体の大きさの定義がちゃんとわかるため,十分なメモリサイズを手動で与えなくても勝手に定義に則ってlong double[5][5]を持ってくる可能性がある,もしそうなら()callcoc()の処理は不要だしメモリが無駄にデカくなっているかも…

補足

  • なんか「c++使えんじゃね?」みたいな話が来てるので,cの練習はもしかしたらこれでおしまいかも

C言語でオレオレオブジェクト

概要

  • cのお勉強
    • c++ではない
    • C11をターゲットにする
      • C17ほどの新環境ではない
    • 本格的に開始して3日目の記事です
  • matlabで書けるやつをcに移行したい
    • オブジェクト指向の設計がちょっとできるようになった
    • 試しにcodegenを使ってみたけど納得できなかった…
  • どうしても組み込み開発にオブジェクト指向を使ってみたい…
    • 簡単なルーチンのコードならぶっちゃけ引き継ぎで確保している
    • handle classがとても便利だよね,ぜひともあれをやりたい
  • 結果,オレオレ自己参照構造体にオレオレ関数を設定する方針に至る
  • MBP-2016-15(Intel Core i7), macOS Monterey, Xcode CommandLine Tool clang
    • これ-std=c11にするとC11を基準にやってくれるらしい
    • はじめてmakefileをつくってみたけどかなりべんりだった

設計方針

  • 初心者なので最も簡単な事例を考える
    • 「依存関係を生成して変更に追従して参照できる」
  • main関数でハンドルオブジェクト的に使える
    • A.b();みたいなのは無理やわ
      • (実際やろうと思えばいけるっぽいけど設計も用法も無茶苦茶になりそうで流石に却下した)
    • b(A);みたいなので実装した
  • segmentation faultbus errorを吐かない
    • メモリ確保からメモリ解放まで一通り実践する

重要問題

  • callocを適切に設置しないと詰む
  • (少なくとも上記の環境では)オレオレ自己参照を含むオレオレ構造体のサイズをコンパイラがまともに推定してくれなかったので,自力でオレオレ構造体の容量を計算してアドレス空間を動的に生成した上でオレオレ自己参照に割り当てする必要がある
    • これはつまり仕様の変更に対して自動的に修正するコードパターンにしないとサイアクな目(連鎖的なセグフォ)に遭う
    • 仕様を記述した1つだけのstructexternして参照してメモリ確保を連鎖的に実装した(最適かどうかは知らない)
  • cは関数型の言語ゆえにmain()で手元でアドレスを取って引数に入れる手間をかけない限りどうやっても必ず値代入になる
    • 今回の縛りプレイの原因はほぼこれのせい,これを達成しながらどうにかして連鎖的な実装ができるように無茶苦茶やった
    • 魔改造でなんとかする方法があるなら知りたい,=を場合分けして強制的にアドレス代入にするとかやれば良いかもしれん
    • 普通に書いたら見た目はハンドルを握れたオブジェクトでも代入した時点で引数のコピーが生成されることになる
    • 抱える引数のアドレスがオブジェクトに割り当てるアドレス空間にならない,オブジェクトをコピーして所有して肥大化する

以下,出来上がったもの

#ifndef subPrm
#define subPrm


typedef struct Elm {
    int mem;
    int prv;
} Elm;


// parameter method

extern const Elm Prm;

typedef struct prm { //24
    struct prm *adr; //8
    long double num; //16
} prm;

prm defprm(long double num);

void setprm(prm theprm, long double num);

void delprm(prm theprm);

void expprm(prm theprm);

long double getprm(prm theprm);


#endif
  • prmでオレオレ構造体を定義する
  • prm *adrでオレオレ自己参照を定義する
  • ヘッダファイルはメンバ変数と関数宣言を置く
    • 仕様の大幅な変更がない限りはソースファイルだけで処理しよう
  • 関数定義はソースファイルに分ける
    • プロトタイプ宣言はヘッダファイルにおくという意味
  • ifndefタイプのインクルードガードを冒頭に設置する
  • Elmに仕様(拡張性がある)を持つ構造体を定義してPlmで公開する

他も似たような感じ

#include <stdlib.h>
#include <stdio.h>
#include "subPrm.h"


const Elm Prm = {
    .mem = 24
};

prm defprm(long double num){
    prm *adr = (prm*)calloc(1,Prm.mem);
    prm theprm = *adr;
    theprm.adr = adr;
    theprm.adr->num = num;
    return (theprm);
};

void setprm(prm theprm, long double num){
    theprm.adr->num = num;
};

void delprm(prm theprm){
    free(theprm.adr);
};

void expprm(prm theprm){
    printf("%Lf\n",theprm.adr->num);
};

long double getprm(prm theprm){
    return (theprm.adr->num);
};
  • prm *adr = (prm*)calloc(1,Prm.mem)で確保してprm theprm = *adr;に定義
  • free(theprm.adr)でメモリ解放(これってmatlabclearに相当するのでは?)
  • const Elm Prm = {.mem = 24};に仕様(メモリサイズ)を設定する
  • 使いたい関数をあらかじめ定義しておく(命名規則に注意)

他も似たような感じ

#ifndef subAxs2d
#define subAxs2d

#include "subPrm.h"


// axis method

extern const Elm Axs;

typedef struct axs2d { // 56
    struct axs2d* adr; //8
    prm px; //24
    prm py; //24
} axs2d;

axs2d defaxs2d(prm px, prm py);

void setaxs2d(axs2d xy, prm px, prm py);

void delaxs2d(axs2d xy);

void expaxs2d(axs2d xy);

long double getaxs2dx(axs2d xy);

long double getaxs2dy(axs2d xy);


#endif
#include <stdlib.h>
#include <stdio.h>

#include "subPrm.h"
#include "subAxs2d.h"


const Elm Axs = {
    .mem = 56
};

axs2d defaxs2d(prm px, prm py){
    axs2d *adr = (axs2d*)calloc(1,Axs.mem);
    axs2d xy = *adr;
    xy.adr = adr;
    xy.adr->px = px;
    xy.adr->py = py;
    return (xy);
};

void setaxs2d(axs2d xy, prm px, prm py){
    xy.adr->px = px;
    xy.adr->py = py;
};

void delaxs2d(axs2d xy){
    free(xy.adr);
};

void expaxs2d(axs2d xy){
    printf("(%Lf, %Lf)\n", getprm(xy.adr->px), getprm(xy.adr->py));
};

long double getaxs2dx(axs2d xy){
    return (getprm(xy.adr->px));
};

long double getaxs2dy(axs2d xy){
    return (getprm(xy.adr->py));
};
  • getprm()を連鎖的に仕様する,ポインタ地獄をある程度に回避できる
#ifndef subVec2d
#define subVec2d

#include "subAxs2d.h"


// vector method

extern const Elm Vec;

typedef struct vec2d { //152
    struct vec2d *adr; //8
    axs2d xy1; //56
    axs2d xy2; //56
    long double len; //16
    long double ang; //16
} vec2d;

vec2d defvec2d(axs2d xy1, axs2d xy2);

void setvec2d(vec2d v, axs2d xy1, axs2d xy2);

void delvec2d(vec2d v);

void expvec2d(vec2d v);

void calvec2d(vec2d v);


#endif
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include "test7subAxs2d.h"
#include "test7subVec2d.h"


const Elm Vec = {
    .mem = 152
};

vec2d defvec2d(axs2d xy1, axs2d xy2){
    vec2d *adr = (vec2d*)calloc(1,Vec.mem);
    vec2d v = *adr;
    v.adr = adr;
    v.adr->xy1 = xy1;
    v.adr->xy2 = xy2;
    return (v);
};

void setvec2d(vec2d v, axs2d xy1, axs2d xy2){
    v.adr->xy1 = xy1;
    v.adr->xy2 = xy2;
};

void delvec2d(vec2d v){
    free(v.adr);
}

void expvec2d(vec2d v){
    long double x1 = getaxs2dx(v.adr->xy1);
    long double y1 = getaxs2dy(v.adr->xy1);
    long double x2 = getaxs2dx(v.adr->xy2);
    long double y2 = getaxs2dy(v.adr->xy2);
    printf("(%Lf, %Lf) -> (%Lf, %Lf)\n",x1,y1,x2,y2);
}

void calvec2d(vec2d v){
    long double x1 = getaxs2dx(v.adr->xy1);
    long double y1 = getaxs2dy(v.adr->xy1);
    long double x2 = getaxs2dx(v.adr->xy2);
    long double y2 = getaxs2dy(v.adr->xy2);
    v.adr->len = pow(pow((x2-x1),2)+pow((y2-y1),2),0.5);
    if (v.adr->len == 0){
        v.adr->ang = 0;
    } else {
        v.adr->ang = atan2((y2 - y1), (x2 - x1));
    };
    printf("len : %Lf, ang : %Lf\n",v.adr->len,(v.adr->ang)*180/M_PI);
};
  • getaxs2dx()getaxs2dy()を連鎖的に仕様する,ポインタ地獄をある程度に回避できる
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include "test7subAxs2d.h"
#include "test7subVec2d.h"


int main(){

    double in;

    printf("x1 : ");
    scanf("%lf", &in);
    prm x1 = defprm(in);
    printf("rep : ");
    expprm(x1);
    printf("y1 : ");
    scanf("%lf", &in);
    prm y1 = defprm(in);
    printf("rep : ");
    expprm(y1);
    axs2d xy1 = defaxs2d(x1,y1);
    printf("axs xy1 : ");
    expaxs2d(xy1);

    printf("x2 : ");
    scanf("%lf", &in);
    prm x2 = defprm(in);
    printf("rep : ");
    expprm(x2);
    printf("y2 : ");
    scanf("%lf", &in);
    prm y2 = defprm(in);
    printf("rep : ");
    expprm(y2);
    axs2d xy2 = defaxs2d(x2,y2);
    printf("axs xy2 : ");
    expaxs2d(xy2);

    printf("vec xy1 -> xy2 : ");
    vec2d v = defvec2d(xy1, xy2);
    expvec2d(v);
    calvec2d(v);


    int amn;
    printf("fib-n order : ");
    scanf("%d", &amn);

    for (int i=0; i<amn; i++){
        if (0==(i%2)){
            setprm(x2, getprm(x2) + getprm(y2));
        }else{
            setprm(y2, getprm(x2) + getprm(y2));
        }
        printf("axs xy2 : ");
        expaxs2d(xy2);
    }
    calvec2d(v);


    return(0);
}

機能

  • 変更および参照が可能な変数を設定するprmオブジェクト
  • 2つのprmオブジェクトで位置座標を表現するaxs2dオブジェクト
  • 2つのaxs2dオブジェクトでベクトルを表現するvec2dオブジェクト
    • vec2dオブジェクトに向きと大きさを計算して与えるcalvec2d関数
    • 自動更新もちょっと考えたけど地獄が生まれるから無理だと判定
  • main()では以下を意図しているぜ
    • 数字入力の受付
    • オブジェクトの生成と代入
    • オブジェクトの連鎖的な生成
    • オブジェクトに固有の関数の実行
    • 下位オブジェクトの再代入と上位オブジェクトからの参照

コンパイル,実行

NAME    =   test.exe
SRMN    =   main.c
SRSB    =   subPrm.c subAxs2d.c subVec2d.c
OBMN    =   test.exe
OBSB    =   $(SRSB:%.c=%.o)
GCCC    =   clang
GCOP    =   -std=c11

make    :   $(SRMN) $(SRSB)
    $(GCCC) $(GCOP) $(SRMN) $(SRSB) -o $(OBMN)

いちいち全部コンパイルするので効率は悪い,もっと最適化できる

% make
% ./test.exe
x1 : 0
rep : 0.000000
y1 : 0
rep : 0.000000
axs xy1 : (0.000000, 0.000000)
x2 : 1
rep : 1.000000
y2 : 1
rep : 1.000000
axs xy2 : (1.000000, 1.000000)
vec xy1 -> xy2 : (0.000000, 0.000000) -> (1.000000, 1.000000)
len : 1.414214, ang : 45.000000
fib-n order : 70
axs xy2 : (2.000000, 1.000000)
axs xy2 : (2.000000, 3.000000)
axs xy2 : (5.000000, 3.000000)
axs xy2 : (5.000000, 8.000000)
axs xy2 : (13.000000, 8.000000)
axs xy2 : (13.000000, 21.000000)
axs xy2 : (34.000000, 21.000000)
axs xy2 : (34.000000, 55.000000)
axs xy2 : (89.000000, 55.000000)
axs xy2 : (89.000000, 144.000000)
axs xy2 : (233.000000, 144.000000)
axs xy2 : (233.000000, 377.000000)
axs xy2 : (610.000000, 377.000000)
axs xy2 : (610.000000, 987.000000)
axs xy2 : (1597.000000, 987.000000)
axs xy2 : (1597.000000, 2584.000000)
axs xy2 : (4181.000000, 2584.000000)
axs xy2 : (4181.000000, 6765.000000)
axs xy2 : (10946.000000, 6765.000000)
axs xy2 : (10946.000000, 17711.000000)
axs xy2 : (28657.000000, 17711.000000)
axs xy2 : (28657.000000, 46368.000000)
axs xy2 : (75025.000000, 46368.000000)
axs xy2 : (75025.000000, 121393.000000)
axs xy2 : (196418.000000, 121393.000000)
axs xy2 : (196418.000000, 317811.000000)
axs xy2 : (514229.000000, 317811.000000)
axs xy2 : (514229.000000, 832040.000000)
axs xy2 : (1346269.000000, 832040.000000)
axs xy2 : (1346269.000000, 2178309.000000)
axs xy2 : (3524578.000000, 2178309.000000)
axs xy2 : (3524578.000000, 5702887.000000)
axs xy2 : (9227465.000000, 5702887.000000)
axs xy2 : (9227465.000000, 14930352.000000)
axs xy2 : (24157817.000000, 14930352.000000)
axs xy2 : (24157817.000000, 39088169.000000)
axs xy2 : (63245986.000000, 39088169.000000)
axs xy2 : (63245986.000000, 102334155.000000)
axs xy2 : (165580141.000000, 102334155.000000)
axs xy2 : (165580141.000000, 267914296.000000)
axs xy2 : (433494437.000000, 267914296.000000)
axs xy2 : (433494437.000000, 701408733.000000)
axs xy2 : (1134903170.000000, 701408733.000000)
axs xy2 : (1134903170.000000, 1836311903.000000)
axs xy2 : (2971215073.000000, 1836311903.000000)
axs xy2 : (2971215073.000000, 4807526976.000000)
axs xy2 : (7778742049.000000, 4807526976.000000)
axs xy2 : (7778742049.000000, 12586269025.000000)
axs xy2 : (20365011074.000000, 12586269025.000000)
axs xy2 : (20365011074.000000, 32951280099.000000)
axs xy2 : (53316291173.000000, 32951280099.000000)
axs xy2 : (53316291173.000000, 86267571272.000000)
axs xy2 : (139583862445.000000, 86267571272.000000)
axs xy2 : (139583862445.000000, 225851433717.000000)
axs xy2 : (365435296162.000000, 225851433717.000000)
axs xy2 : (365435296162.000000, 591286729879.000000)
axs xy2 : (956722026041.000000, 591286729879.000000)
axs xy2 : (956722026041.000000, 1548008755920.000000)
axs xy2 : (2504730781961.000000, 1548008755920.000000)
axs xy2 : (2504730781961.000000, 4052739537881.000000)
axs xy2 : (6557470319842.000000, 4052739537881.000000)
axs xy2 : (6557470319842.000000, 10610209857723.000000)
axs xy2 : (17167680177565.000000, 10610209857723.000000)
axs xy2 : (17167680177565.000000, 27777890035288.000000)
axs xy2 : (44945570212853.000000, 27777890035288.000000)
axs xy2 : (44945570212853.000000, 72723460248141.000000)
axs xy2 : (117669030460994.000000, 72723460248141.000000)
axs xy2 : (117669030460994.000000, 190392490709135.000000)
axs xy2 : (308061521170129.000000, 190392490709135.000000)
axs xy2 : (308061521170129.000000, 498454011879264.000000)
len : 585967834257297.125000, ang : 58.282526

(1,1)スタートだとオーダーは70が限界,(0.1,0.1)スタートだとオーダーは80が限界 それ以上だとcalvec2d()infが発生してる,math.hでも2乗はキツいらしいな…

感想

  • 行列とか実装して演算も設計すれば自由度が広がりそう
  • でもやっぱりアドレス代入(&Obj)でいい気がしてきた
    • 32bitか64bitかでメモリサイズが変わる
    • OSとコンパイラでメモリサイズが変わる
    • const Elm Obj1={.mem=val1};val1コンパイル時に決定できないとエラーを吐く,例えば他のconst Elm Obj2={.mem=val2};val2参照できない
    • アドレスを羅列するだけならsizeof(void*)を参照先の数だけ用意すれば良いし,cに固有なデータ型のサイズはデフォで使えるはずだし,かえって環境や仕様の変化に強いのは
    • 結果的にメモリリーク対策がやりやすくなりそうなので次はそのバージョンもやってみる
      • main()を書くのがちょっと面倒になるけどしょうがない,c++使わせて欲しい

参考

http://www9.plala.or.jp/sgwr-t/lib/calloc.html

https://yu-nix.com/archives/c-object-extends/

https://programming-place.net/ppp/contents/c/037.html

https://c.perlzemi.com/blog/20210212090234.html

http://www.c-lang.org/self.html

https://dixq.net/forum/viewtopic.php?t=18103

上記に加えてTwitterの観測結果

PID(+R)コントローラの離散化のテンプレ

古典制御手法の離散化

組み込みフィードバック制御をお前に教える
俺はなるべく双一次変換を使いたいけど貴様は?

変数

  •  T_s は周期時間
  •  T_u は緩和時間
    •  K_u は緩和時間 =\dfrac{T_u}{T_s}

z変換の実装

sドメインからzドメインに変換する時の双一次変換は

 \displaystyle
    s \to \dfrac{2}{T_s} \dfrac{1-\frac{1}{z}}{1+\frac{1}{z}}

で定義される

離散化制御器の実装

上で得た式をそのまんまテンプレート

 \displaystyle
    H_z = \dfrac{\Sigma_{p=0}^{m}\frac{a_p}{z^p}}{1-\Sigma_{q=0}^{n}\frac{b_q}{z^q}}

に対応させてIIRにぶち込めばおk
 aフィードフォワード bはフィードバック, zの次数に対応させて遅延をかければヨシ

一覧

比例(P)コントローラ

まぁそれはそう

 \displaystyle
    K_P \to K_P

積分(I)コントローラ

1次遅れ系の定常偏差を消去する時に使うやつ

 \displaystyle
    \dfrac{K_I}{s} \to \dfrac{\frac{T_sK_I}{2}+\frac{T_sK_I}{2z}}{1-\frac{1}{z}}

微分(D)コントローラ

分野的に使ったことないからよくわからん
が,擬似微分の実装は大事なので書いておく

 \displaystyle
    \dfrac{\rm{d}}{\rm{d}t} \to \dfrac{s}{1+T_us}
    \to \dfrac{\frac{2}{T_s(1+2K_u)}+\frac{-2}{T_s(1+2K_u)z}}{1-\frac{2K_u-1}{(2K_u+1)z}} \\
    \therefore K_Ds \simeq \dfrac{K_Ds}{1+T_us} \\
    \to \dfrac{\frac{2K_D}{T_s(1+2K_u)}+\frac{-2K_D}{T_s(1+2K_u)z}}{1-\frac{2K_u-1}{(2K_u+1)z}}

共鳴(R)コントローラ

あんま聞かないかもしれんが,特定の周波数成分だけゲインを爆上げできる
通過させる周波数 \omega_cと通過させる帯域 \omega_bと帯域ゲイン K_Rの設定が必要になる
負ループ組んだ時の安定性は勝手に確認してくれ,ボード線図が必要かも

 \displaystyle
    \dfrac{K_R\omega_bs}{s^2+\omega_bs+\omega_c^2}
    \to \dfrac{ \frac{2T_sK_R\omega_b}{4+2T_s\omega_b+T_s^2\omega_c^2} + \frac{0}{z} + \frac{-2T_sK_R\omega_b}{(4+2T_s\omega_b+T_s^2\omega_c^2)z^2} }{ 1 - \frac{8-2T_s^2\omega_c^2}{(4+2T_s\omega_b+T_s^2\omega_c^2)z} - \frac{2T_s\omega_b-4-T_s^2\omega_c^2}{(4+2T_s\omega_b+T_s^2\omega_c^2)z^2} }

matlabで並列処理を伴う高次方程式の解計算とグラフ作成

なにがしたいか

  • 5次以上の高次方程式の数値解を網羅したい
    • 一般解の表現が存在しない以上は数値的に求めるしかない
    • パラメータを弄るとどんな感じに変化するかを確認したい
    • でもちょっと面倒なので簡単な2次方程式で実装してみるよ
  • 国の金で買った多コアCPUなんだから使い潰したいね
    • 簡単な並列処理の導入と通信手法のテンプレート化を図る

注意

  • matlabの並列化にはParallel Computing Toolboxのライセンスが必要だぞ
    • 対応していないと並列化は(多分)できない,設定も表示されないかも

jp.mathworks.com

方程式を定義しよう

.mlxって知ってる?
ライブスクリプトを使うと方程式の作成と編集が楽になるよ

clear;

syms a b x;
symfx = x^2 + a*x + b;

save("testEquation.mat");

.mファイルに保存すれば同じ方程式をいつでも呼び出せる

並列処理の環境設定

ライセンスがあれば左下のアイコンが表示されるので,並列基本設定に進む

手元のPCだけならlocalを選ぶ(普通はそれ以外は出てこないはず),ワーカー数を指定する(物理コアよりも少なめで設定)

OKを押したら並列プールを起動してみる,謎の模様が青く光ってればOKだ

実装と実験

簡単にルールを説明すると,

  • parforforループの体をしながらも処理を1つずつ並列ワーカーに送信する
  • parforの中にparforを入れてはいけない
  • parforの内から外に変数をダイレクトに持ち出してはいけない
    • 外から内だとメモリ空間を共用できるけど内から外だとできるわけないからね
    • 代わりにparforの中からparallel.pool.DataQueuesendすることはできる
  • 以上の条件から実装したい処理は以下の通りになる
    • 親プロセスで方程式,パラメータ,グラフ,キュー,ちょっとした関数などの環境を整える
    • 子プロセスにターゲットの方程式とそれに適用するパラメータを与えて解かせる
    • 解を出したらデータセットを整形して子プロセスがキューを更新(事実上のプッシュ)する
    • 親プロセスはキューを監視してデータセットを元にグラフを(リアルタイムで)反映させる
  • 2種類のパラメータの総当たりを1つのparforで振り分けるので,そのへんの工夫は必要になる
    • 1次元の配列に2次元のデータをマッピングする競プロ感のある実装になってる,しゃーない
  • 実数解は青十字,虚数解は赤正円で表示を分けてみる
    • このビジュアライズとても便利なのでちょっと布教したい

コード

clear;
load('testEquation.mat');

brStr = convertCharsToStrings(char(10));


arrayA = -10:1:10;
lengtA = [-10,10];
arrayB = -10:1:10;
lengtB = [-10,10];


stDateTime = datetime();
messg = "Launched Analysis: testEquation"+brStr+"Start at: "+datestr(stDateTime);
disp(messg);
sendSlackTxt('simulinkMonitor',messg);



try
    image = imread(title+".png");
    clear("image");
    messg = "Already Analysed"+brStr+"Terminate Situation";
    disp(messg);
    sendSlackTxt('simulinkMonitor',messg);
catch


    title = "testEquation";
    disp(title);

    index = "testEquationSolver"+brStr+"with Parallel Computing";
    graph = initGraph(index);
    graph.WindowState="maximized";


    titleSolve = "Solutions Mapping";
    tableSolve = initTable(titleSolve,1,2,1);
    xlabel(tableSolve,"$\rm{Re}$",'Interpreter','latex');
    ylabel(tableSolve,"$\rm{Im}$",'Interpreter','latex');
    xticks(tableSolve,-10:1:10);
    xlim(tableSolve,[-10,10]);
    yticks(tableSolve,-10:1:10);
    ylim(tableSolve,[-10,10]);
    tableSolve.XAxis.Exponent = 0;
    tableSolve.YAxis.Exponent = 0;

    titleParam = "Parameter Mapping";
    tableParam = initTable(titleParam,1,2,2);
    xlabel(tableParam,"$a$",'Interpreter','latex')
    ylabel(tableParam,"$b$",'Interpreter','latex')
    xticks(tableParam,arrayA);
    xlim(tableParam,lengtA);
    yticks(tableParam,arrayB);
    ylim(tableParam,lengtB);
    tableParam.XAxis.Exponent = 0;
    tableParam.YAxis.Exponent = 0;


    pListSolve = parallel.pool.DataQueue;
    pListSolve.afterEach(@(data) addPlot(tableSolve,data));

    pListParam = parallel.pool.DataQueue;
    pListParam.afterEach(@(data) addPlot(tableParam,data));



    parfor countPattr = 1:(length(arrayA)*length(arrayB))


        [countA,countB] = addAxis(length(arrayA),length(arrayB),countPattr);
        paramA = arrayA(countA);
        paramB = arrayB(countB);


        numfx = subs(symfx,a,paramA);
        numfx = subs(numfx,b,paramB);

        poles = vpasolve(numfx,x);
        reals = real(poles);
        imgns = imag(poles);
        color = 'b';
        shape = '+';
        diamt = 8;
        for check=imgns.'
            if (check~=0)
                color='r';
                shape='o';
                diamt=16;
            else
            end
        end


        send(pListSolve,{reals,imgns,diamt,shape,color});
        send(pListParam,{paramA,paramB,diamt,shape,color});


    end

    %saveas(graph,title+".png");
    %close(graph);

    edDateTime = datetime();
    messg = "Finished Analysis: testEquation"+brStr+"End at: "+datestr(edDateTime);
    disp(messg);
    sendSlackTxt('simulinkMonitor',messg);


end



function [] = addPlot(table,data)
scatter(table,data{1},data{2},data{3}^2,data{4},data{5});
hold on;
drawnow('limitrate');
end



function [countA,countB] = addAxis(lengthA,lengthB,countPattr)
ii = countPattr;
jj = 0;
while ii>0
    ii = ii-lengthA;
    jj = jj+1;
end
countA = ii+lengthA;
countB = jj;
end

ちなみにグラフのプリセットはこれで生成している

function graph = initGraph(index)

    graph = figure;
    set(graph,'color','white');
    
    if index==""
    else
        sgtitle(graph,index,'FontName','Times New Roman','FontSize',48,'interpreter','latex');
    end

end
function [table] = initTable(index,heigt,width,order)

    table = subplot(heigt,width,order);
    set(table,'FontName','Times New Roman','FontSize',24);

    if index==""
    else
        title(index,'Interpreter','latex','FontSize',36);
    end

    set(table,'Box','on','LineWidth',1,'GridLineStyle','-','MinorGridLineStyle','none');
    set(table,'XColor','k','YColor','k','ZColor','k','GridColor','k');
    set(table,'GridColor','k','MinorGridColor','k','GridAlpha',0.5);
    set(table,'TickLabelInterpreter','latex')
    grid on;
    hold on;
    
end

結果

あー,中学校の数学でこういうのをやった記憶,みなさんにあるはずっすよねぇ
$a2-4b<0$で虚数になるから$b>\dfrac{a2}{4}$で青十字から赤正円に切り替わる

ちなみに私は普段はvpasolverで8次方程式を解かせています
2次方程式だと計算スピードがプロットスピードを超えるのでちょっともたついて感じるかもしれん

OutlookがAzureから中間者攻撃を受けている…かもしれない?

Outlookのメールアカウント(xxx.outlook.com)において,2022年7月11日よりも後に,IPv4アドレス13.101.0.0-13.101.255.255(13.101.0.0./16)から,IMAPでの不正なログイン(通常とは異なるアクティビティ)が,世界各地で確認されています
「これはAzure(Microsoftクラウドサービス)を経由した攻撃である」「パスワードの変更と2要素認証を設定するべきだ」というのが公式スタッフ(モデレータ)による説明(初報)であるため,こちらでも全く同様の対処を推奨しています
またこの問題を報告する際は,以下のリンクから提出できるAbuse Reportの利用が指定されています,こちらはその名の通りにAzureの不正利用に関するものとなっています,なお私は既に提出していますがこれは皆さまの判断にお任せしたいと思います

msrc.microsoft.com


日本語コミュニティにおいても類似または同様の事象を指摘する幾つかのスレッドが立っているようですが,英語コミュニティの以下の該当スレッドが(恐らく最も早い段階から活発に)情報の収集や問題の議論が行われているようです,というより私がこれを立てたのですが想像よりも多くの投稿があって驚いています,Abuse Reportも何回か出されている雰囲気がありますね…

answers.microsoft.com

ちなみにサポートセンターの末端のスタッフは恐らくこれについては何も知らされていないはずなので,今からチャットや電話で何かを聞き出してやる〜とするのはかなり迷惑になると思います,サービスの品質維持に協力するという体裁で控えましょう


そのタイミング性から中間者攻撃およびリプレイ攻撃が疑われていますが,現在はMicrosoftからの報告が途絶しています
またAzureの公式のIPリストには「13.101.0.0/16」が対象として掲載されておらず,ならばOutlookの仕様によるものではないかとの見方もあり,しかしそれならばアラートが出るのは不誠実だろうというツッコミがされています(下はjsonダウンロード)

www.microsoft.com

matlabでpng画像をbase64経由のエンコード・デコード

やりかた

主に2つある,基本的には上で事足りるよね…?

matlab純正関数を使う

matlab.net.base64encodematlab.net.base64decodeを直で叩く

jp.mathworks.com

jp.mathworks.com

そもそも画像データを読み込んで云々という動作させるには工夫が必要,データと型の扱いとか…

org.apacheを拝借する

org.apache.commons.codec.binary.base64インスタンス化する

weblabo.oscasierra.net

ただなんでJavaのライブラリが使えているのかよくわからん,R2022aで動いたけどこれはおま環かもしれないので要注意
あとmatlabとの食い合わせが悪いかもしれないので工夫が必要

使用例

やること

  • htmlData URI Schemeを出す
    • Chromeなら見れるはず
  • encode/decodeで元のファイルを復元する
  • そのままslackのwebhookにも送りつけてみる
    • typeにはmrkdwnを指定する
    • 試したい人はapiを用意してね
clear;


imgUrl = 'test.png';

fid = fopen(imgUrl);
fbt = fread(fid);
fclose(fid);


% With Apache
base64Coder = org.apache.commons.codec.binary.Base64;
fbtB64apa = uint8(base64Coder.encode(uint8(fbt)));
fbtB64apaChr = char(fbtB64apa.');
revfbtapa = double(typecast(base64Coder.decode(fbtB64apa),'uint8'));

newfid=fopen('test1Apache.png','w+');
fwrite(newfid,revfbtapa);
fclose(newfid);

% With Matlab
fbtB64matChr = matlab.net.base64encode(uint8(fbt));
revfbtmat = double(matlab.net.base64decode(fbtB64matChr).');

newfid=fopen('test1Matlab.png','w+');
fwrite(newfid,revfbtmat);
fclose(newfid);


% html base64 uri data scheme
html = '<head></head><body><img src="data:image/png;base64,'+string(fbtB64apaChr)+'"></body>'; % easy html style

newfid=fopen('test1.html','w+');
fwrite(newfid,html);
fclose(newfid);


% try to send Slack webhook
url = 'https://hooks.slack.com/services/xxx/yyy/zzz'; % your Webhook API url

content.type="html";
content.text = '<img src="data:image/png;base64,'+string(fbtB64apaChr)+'">'; % easy markdown style

payload = jsonencode(content);
options = weboptions('CharacterEncoding','UTF-8','UserAgent','matlab_simulink','Timeout',8);

webwrite(url,payload,options);

どうなるか

こうなれば良い,matlabapacheで結果が一致するはず

htmlはブラウザで画像が見えていればOK
フォルダを見て画像が復元されていればOK

slackはクッソ長い文字列しか見えない,そもそもData URI Schemeに非対応か,もしくは文字数制限でインタプリタが動作しないか…
やはりどうしても画像投稿用のAPIを使う必要があるらしいな?

matlabの問題点

自前でuint8(binary)しないとダメ,内部で変換してくれるらしいのだが恐らくtypecast(binary,'uint8')をされている
画像データの読み込み時にdoublearrayになるので,それをcastしながらdecodeしてはいけない

apacheの問題点

恐らくちゃんとしたバイナリ列を返してくれるが,matlab側がint8で受け取るためオーバーフローみたいになる
ここではuint8castする必要がある

Powershell,ワンライナー,正規表現でファイルを選択,そのままtar.gzに圧縮

本当はあまりPowershelをは使いたくないが,需要に駆られたので適当に対策した時のメモ…
最近になってようやくtargzipが使えるようになったらしい,あまりにも最低限すぎるだろ

コード

ls | ? { $_.Name -match '.*.mp4'} -outvariable files |  tar -cf 'xxx.tar' $files | gzip -9 'xxx.tar'

最大圧縮以外あり得ない

ブロックダイアグラム作成御用達のdiagrams(旧称draw.io)

紹介

制御とか処理とかでブロックダイアグラムを作成したい時に利用できる

microsoftvisioみたいなものではあるが,例えば詳細な図面の設計に使えるものではないし,あくまで情報・工業・数学・産業といった分野において,ブロックダイアグラムなどの作成を支援してくれる

環境

ブラウザ

JavaScriptを有効にしておくだけでOK

app.diagrams.net

アプリ

インストールはこちらから,OSに対応してダウンロードしてね

get.diagrams.net

利点

  • 利用開始までの手順が簡単
  • 利用環境のハードルが低い
  • 機能が単純だから扱い易い
  • LaTeXの基礎的なコマンドに対応
  • 論文とかでも使えそうね

欠点

  • 美術的な創作業には不向き
  • レイヤーは扱いづらいかも

導入

ぶっちゃけhomebrewで入れられるのが強み

brew install --cask drawio                                             

ちなドキュメント

www.diagrams.net

faqは役に立つかも

www.diagrams.net

ビギナーズページ

drawio-app.com

drawio-app.com

drawio-app.com

drawio-app.com

drawio-app.com

drawio-app.com

drawio-app.com

drawio-app.com

drawio-app.com

drawio-app.com

作成

基本的には.drawioとそのバックアップ.drawio.bkpが作成される

加えてテンプレートも自由に選べる,ソフトウェア設計・クラウドネットワーク・ハードウェア設計のいずれも網羅している

ページ

下部でページを切り替えて作業できる,イラレっぽい

よく使う図形

各種テンプレートにはよく使う図形が同封されているが,これはライブラリ表示を有効化することでいつでも利用できる 左下の「図形を追加」から入って

適当にチェックを入れれば良い

または上部の「表示」->「図形」からでも設定できる

一応はそれぞれがライブラリという扱いをされている

数式組版

テキストを編集する際に$$で囲むと,その内部の文字列がLaTeXソースとして解釈され,編集後に組版されて表示される
上部の「拡張」->「数式組版」をオンにすれば良い

編集

ページ表示

グリッドが利用できるのがとても強い,ついでに点や線に合わせて自動的にスナップしてくれる

用紙サイズを設定してページビューをオンにすると境界線や中央線が表示される,背景色も一応は入れておこう

カラーパレットが使えるなら変えられる,枠線・テキスト・塗りつぶしで利用できる

グラデーション

4方向+放射状の5種類,かつ2色変化しか使えない,しょうがないね

レイヤー

上部の「表示」->「レイヤー」から展開できる

あとはお好みで作業しよう,やっぱりイラレっぽい

図形

左のブラウザからドラッグ&ドロップ,もしくは後述するインポートを行う

図のコネクタをドラッグで繋ぐとできる
ただし始点と終点の概念があるので方向に注意しよう,一応は右クリックから「逆」を選ぶと反転できる

drawio-app.com

分岐の書き方

接点が発生するのは図形と線の間のみなので,交点には必ず黒点を配置すると良い

交差の書き方

逆に交点を設けない場合は,わかりやすくジャンプさせると良い
線を選択して「スタイル」から「line jumps」で「円弧」を選択する

実際こうなるが,

前面と背面の関係によってどちらがジャンプするか決定される

入れ替えることも可能である

適度に大きい方がわかりやすいね!

矢マークの調整

「スタイル」の中段のリスト群の下列で,始点と終点のそれぞれにアイコンを適用できる
その下の「サイズ」で大きさを決められるが,線の太さに比例する係数であって絶対値ではないので注意

テキスト

選択した図形や線の上でダブルクリックすれば編集画面に入れる

drawio-app.com

フォント

「フォント」->「カスタム」に入れるので,

そこにシステムから入れるなりGoogleフォントを使うなりすれば良い

LaTeXコンパイルにおいて

フォントや自体は影響しないけど,色は上書きできるしレイアウトは変更できるし,サイズも比例して調整できる

インポート

上部の「ファイル」->「次をインポート:」

drawio-app.com

エクスポート

上部の「ファイル」->「形式を指定してエクスポート」->「(拡張子を選択)」

drawio-app.com

解像度について

このままでは弄れないので,「ファイル」->「形式を指定してエクスポート」->「高度な設定」から

DPIを上げれば良い,ついでに背景や余白についても設定しよう

「横幅」と「縦幅」は据え置きで,「ズーム」と「DPI」が変化するだけ
ちなみにここで言う余白は用紙サイズを基準としたものではないらしい,具体的には図形を収められる最小の長方形に勝手にトリミングしてくるので,pdfで出力すると表示やページがおかしくなってしまう,素直にpngで吐き出した方が良いかも

自作ライブラリ

drawio-app.com

作成

「ファイル」->「新規ライブラリ」で.xmlファイルとして作成できる お目当ての画像などを追加して保存する,上書き更新もできるはずだけど何故か動作がフリーズする場合があるかもしれないね(私は手元でよくバグるので)

読込

「ファイル->ライブラリを開く」で該当の.xmlファイルを選択する

自作シェイプ

図形そのものを自作できるが,コーディングが必要になってくるので辛い,そこまでする必要に駆られることはそうないと思う

www.diagrams.net

ググっても思った以上に資料が出ないので,本気でやるとなるとかなり辛そう
ただどこかsvgに似ているので,svgに慣れている人ならできそうな気もする

制御の資料を作るだけならぶっちゃけ不要だし,それくらいデフォルトのライブラリが充実しているので心配しなくても良い

dockの大きさをdefaults writeで限界突破させる

やり方

デスクトップの写真を設定しようとして間違えてdockのところ触っちゃうと,なぜか勝手に限界値に設定されちゃうので

defaults write com.apple.dock largesize -int 256 | killall Dock

する必要がある

デカい方がいいね!

defaultsについて

read [ファイル名]

読み込み
辞書型のうち1つだけを操作する場合のコマンド,という解釈が近そう

特定のアプリ

アプリ名に対応するファイル名を入れれば選択できる
入れない場合は全ての設定を吐き出す

辞書型

.plist<dict></dict>タグが{}で置換されるらしい
オプション名に後付けしていけば抜き出せるかも?

配列型

.plist<array></array>タグが()で置換されるらしい,JSONっぽいがJSONではない
ちなみに配列の番号を指定して読み込むのは不可能っぽい

export

.plistファイルを吐き出す

write [アプリ名] [オプション名] [値]

書き換え
辞書型のうち1つだけを操作する場合のコマンド,という解釈が近そう

addする場合

一般人の需要こそないだろうが,array-adddictionary-addがあるらしい

型指定

.plistではタグで型を指定する,-string-float-int-bool

Node.jsで.csv形式でログを取って.tar.gz形式で圧縮する

soluna-eureka.hatenablog.com

の続き

開発背景

電力が貴重なこの時代!学術研究でも計算機の消費電力は無視できない!そもそもCPU温度が下がらない状況は危ない!
ということで常駐で温度を監視してログを取れるやつにまで昇華しました,やってることは基礎的なことのはずなんだけどな…

ちなみに冷却装置の設定によっては室温との相関があるかもしれない,流体の熱伝導を考えればそれはそうという感じはあるが

機能

  • 1秒毎にCPU温度を監視
    • 設定温度を超過するとSlackにログを送信
  • 毎分10n秒でログを.csvに書き込む
    • excelとかで見るのを前提に
  • 毎時0分でSlackにログを送信
    • 動作確認の意味合いも兼ねて
  • 毎日0時5分に前日の.csv.tar.gzに圧縮し元の.csvを削除
    • もちろん最大圧縮

以下,反省と言い訳

csvの操作がクソ難しい

こちらもオブジェクト型や配列型の酷使に慣れていなかったというのもあるが,単純にnpmcsvの各ライブラリ(csv-parseとかcsv-stringifyとか)の仕様がかなり変わっていて導入が面倒だった,ごく最近のいい感じのブログとかもなかったので公式ドキュメントを見ないとなかなか実装できなかった,あっ営利目的でこの記事を参考にしてもいいけど参考にしたらここのリンクを広めといてね♡

async/await多すぎ問題

これってsyncなライブラリだよな〜と思ったらasyncでした〜みたいなことがちょっと多すぎて頭にきますよ〜,じゃけんasync/awaitかけますね(保険的な意味合いで),async functionで定義した関数をawaitなしで呼び出すとpromiseが返ってくるなんて初めて知りましたね…言われてみればそうなんだけど,本当にそうなんだ…

.csvファイルの成形問題

ヘッダの有無くらいしか実装できなかったが,実際の利用においては問題はないと判断したのでこれで行くことにした,調べた限りではヘッダありで.csvをパースしてjsonライクにオブジェクト型でデータを操作する的な場合もあるらしいが,わざわざ各ループの間で状態を渡し続ける実装なんて面倒だし,もう1行目の完全一致だけで判定した方がはるかに早そうなのでなぁ…

その無駄っぽい変数宣言いる?

いる(確信),書いてるうちにわからなくなりかけたので必要だった(確信),ちなみに文字数と修飾語で用途を分けている

地味に温度の精度が悪い

1℃単位の測定しか許容されていなかったり誤差が無駄に大きかったりという噂がOpen Hardware Monitorにはあるらしいが,まぁ気休め程度だと思って使うことにする,実際に測定結果を見ていても面白いから問題なし

コード

// IO plugin
const fs = require('fs-extra');
const tar = require('tar');
const tryCatch = require('try-catch');
const scheduler = require('node-schedule');

// API plugin
const { getJSON } = require('simple-get-json');
const { stringify } = require('csv-stringify/sync');
const { parse } = require('csv-parse/sync');
const csvStringify = stringify;
const csvParsing = parse;

//Util plugin
const datetime = require('date-and-time');
const { IncomingWebhook } = require("@slack/webhook");

// Parameters
const slackURL = "https://hooks.slack.com/services/xxx/yyy/zzz";
const slackWebhook = new IncomingWebhook(slackURL);
const monitorURL = "http://localhost:8085/data.json";
const coreTempLimit = 60;




// API for Open Hardware Monitor
async function accessJSON() {
    try {
        var res = await getJSON(monitorURL);
        var raw = JSON.stringify(res, null, 4);
        var obj = JSON.parse(raw)['Children']; // for Open Hardware Monitor
        var tgt = obj[0]['Children'][1]['Children'][1]['Children']; // for Open Hardware Monitor
        return tgt;
    } catch (err) {
        console.log("something wrong happened with CPU Monitor!")
        tgt = [
            { Text: "0", Value: "0" } // for open hardware monitor
        ];
        return tgt;
    }
}


// Shaper for Open Hardware Monitor
async function makeMessage(tgt) {
    var cpuParam = "";
    var coreName = "";
    var coreTemp = "";
    var heatFlag = false;

    var i = 0;
    var j = 0;
    tgt.forEach(cpuCore => {
        coreName = cpuCore['Text']; // for Open Hardware Monitor
        coreTemp = cpuCore['Value']; // for Open Hardware Monitor
        cpuParam += (coreName + " is " + coreTemp + "\n");
        floatCoreTemp = parseFloat(coreTemp);
        i = i + 1
        if (floatCoreTemp > coreTempLimit) {
            j = j + 1;
        }
    });
    if (i == j) {
        heatFlag = true; // whether need to notice or not
    }

    var txt = cpuParam + datetime.format(new Date(), 'YYYY/MM/DD HH:mm:ss:SSS') + "\n";
    var flg = heatFlag;
    return [flg, txt];
}


async function makeCSVtext(tgt) {
    var cpuParam = [];
    var coreName = "";
    var coreNames = ["date"];
    var coreTemp = "";
    var coreTemps = [datetime.format(new Date(), 'YYYY/MM/DD HH:mm:ss:SSS')];
    var heatFlag = false;

    var i = 0;
    var j = 0;
    tgt.forEach(cpuCore => {
        coreName = cpuCore['Text']; // for Open Hardware Monitor
        coreNames.push(coreName);
        coreTemp = cpuCore['Value']; // for Open Hardware Monitor
        floatCoreTemp = parseFloat(coreTemp);
        coreTemps.push(floatCoreTemp);
        i = i + 1
        if (floatCoreTemp > coreTempLimit) {
            j = j + 1;
        }
    });
    if (i == j) {
        heatFlag = true; // judge whether to notice or not
    }

    cpuParam = [coreNames, coreTemps];
    var txt = csvStringify(cpuParam, { header: false }, { delimiter: "," });
    var flg = heatFlag;
    return [flg, txt];
}



// csv(array)_txt(string) Parse&Build interface
async function parseCSVdata(txt) {
    var csv = await csvParsing(txt, { columns: false, delimiter: "," });
    return csv;
}

async function parseCSVdataHead(txt) {
    var csv = await csvParsing(txt, { columns: false, delimiter: ",", to_line: 1 }); // get only header line
    return csv;
}

async function buildCSVdata(csv) {
    var txt = await csvStringify(csv, { header: false, delimiter: "," });
    return txt;
}



// API for Slack
async function sendMessage(flg, txt) {
    if (flg) { // grasp whether to notice or not
        try {
            await slackWebhook.send({
                text: `${txt}`
            });
        } catch (err) {
            var text = "temp flag is " + flg + ", but something error happened with slack!";
            console.log(text);
        }
    }
}

async function sendLogging(flg, txt) {
    try {
        await slackWebhook.send({
            text: `${txt}`
        });
    } catch (err) {
        var text = "something error happened with slack!";
        console.log(text);
    }
}



// commonly file system utils
async function createFolder(path) {
    try {
        await fs.ensureDir(path);
    } catch (err) {
        var text = path + " (folder) can not be created!";
        console.log(text);
    };
}

async function createFile(path) {
    try {
        await fs.ensureFile(path);
    } catch (err) {
        var text = path + " (file) can not be created!";
        console.log(text);
    };
}

async function writeupFile(path, txt) {
    await createFile(path);
    try {
        await fs.appendFile(path, txt);
    } catch (err) {
        var text = path + " (file) can not be written!";
        console.log(text);
    };
}

async function writeupCSVdata(path, txt) {
    var preTxt;
    var preCsv;
    var csv;
    try {
        preTxt = await fs.readFile(path);
    } catch (err) {
        var text = path + " (file) can not be read!";
        console.log(text);
        preTxt = "";
    };
    preCsv = await parseCSVdataHead(preTxt);
    csv = await parseCSVdataHead(txt);
    if (JSON.stringify(preCsv) == JSON.stringify(csv)) { // check a header, need to developed
        csv = await parseCSVdata(txt);
        csv.shift();
        txt = await buildCSVdata(csv);
    }
    await writeupFile(path, txt);
}



async function createArchive(filePath, archivePath) {
    try {
        tar.create({
            sync: true,
            file: archivePath,
            gzip: '-k -9'
        }, [
            filePath
        ])
    } catch (err) {
        var text = archivePath + " (archive) can not be created!";
        console.log(text);
    };
}


async function removeFileFolder(path) {
    try {
        fs.removeSync(path);
    } catch (err) {
        var text = path + " (file) can not be removed!";
        console.log(text);
    };
}




// initialize
(async() => {
    createFolder(".", "/Logs");
})();




// routine definition
const scheduleSendMessage = scheduler.scheduleJob("0-59 * * * * *", function() {
    var tgt;
    var txt;
    var flg;
    (async() => {
        tgt = await accessJSON();
        [flg, txt] = await makeMessage(tgt);
        await sendMessage(flg, txt);
    })();
});



const scheduleSendLogging = scheduler.scheduleJob("0 0 */1 * * * ", function() {
    var tgt;
    var txt;
    var flg;
    (async() => {
        tgt = await accessJSON();
        [flg, txt] = await makeMessage(tgt);
        await sendLogging(flg, txt);
    })();
});



const scheduleLogging = scheduler.scheduleJob("0,10,20,30,40,50 * * * * *", function() {
    var date = datetime.format(new Date(), 'YYYY_MM_DD');
    var path = "./Logs/" + date + ".csv"
    var tgt;
    var txt;
    var flg;
    (async() => {
        tgt = await accessJSON();
        [flg, txt] = await makeCSVtext(tgt);
        await writeupCSVdata(path, txt);
    })();
});



const manageLogfiles = scheduler.scheduleJob("0 5 0 */1 * *", function() {
    var cur = new Date();
    var old = datetime.addDays(cur, -1);
    var curDate = datetime.format(cur, 'YYYY_MM_DD');
    var oldDate = datetime.format(old, 'YYYY_MM_DD');
    var curPath = "./Logs/" + curDate + ".csv";
    var oldPath = "./Logs/" + oldDate + ".csv";
    var curGzip = "./Logs/" + curDate + ".tar.gz";
    var oldGzip = "./Logs/" + oldDate + ".tar.gz";
    (async() => {
        await createFile(curPath);
        await createFile(curGzip);
        await createArchive(oldPath, oldGzip);
        await removeFileFolder(oldPath);
    })();
    console.log(datetime.format(new Date(), 'YYYY/MM/DD HH:mm:ss:SSS'));
    var text = "logging files are regularLy updated!";
    console.log(text);
});

CPUをOpen Hardware MonitorとNode.JSで監視してSlackで通知する

何がしたいか

重いシミュレーションを長い時間かけてリモートPCで回し続けるのはやっぱり不安な点があり,特に知らん間に冷却装置が不調を来したらどうしようという不安に苛まれる,まして多少はCPUをチューニングしているような状態だとそれは尚更になる
ということでスクリプトでCPU監視し続けて,温度が一定値を超えたらSlackに通知を投げ,Remote Desktopで非常措置を迅速に行えるようにした(ソフトの関係上でWindows限定だけど)(ネットワークが切れた場合のことは知らんものとする)

大まかな筋書き

  • サーバーモードのOpen Hardware MonitorでPCを監視
  • NodeJSでそのAPIを叩いてJSONを取得・加工
  • CPUの状態を評価して必要な場合はWebhookのAPIを叩く
  • Slackで確認して対応する

内容

Open Hardware Monitorの設定

インストール

openhardwaremonitor.org

サーバーモードで起動

管理者権限でOpenHardwareMonitor.exeを立ち上げた後に「Options」->「Remote Web Server」->「Run」で開始
localhostでアクセス可能,ポートはOptions->Remote Web Server->Portで設定できる,ここに出るリンクのIPアドレスはグローバルアドレスらしいけど,普通にlocalhostのほうが早いし楽なのでオススメ,環境によってはコロコロ変わるし

NodeJSの用意

ハードウェアが絡むせいで色々と面倒だからWSLとか使わずにPowerShellから直にNodeJSを動かせるようにする

管理(nvm)の入手

他のツールで工夫するのも面倒なので公式が推してるnvm-windowsを入れる

openhardwaremonitor.org

github.com

最新版のnvm-setup.zipを落として解凍,適当に回答してインストール

NodeJSの入手

PowerShell管理者権限で起動(じゃないとインストール後に有効化できない)
nvm list availableで出てきたバージョンから好きなものを選んでnvm install x.y.z
最後にnvm use x.y.z,なぜか管理者権限が必要でない場合はstatus:1が返ってくる

VSCodeの用意

あったら楽なので

code.visualstudio.com

入れたらgitの拡張機能も入れておくべし

gitの用意

soluna-eureka.hatenablog.com

実は上の記事でWSL2のUbuntuの中にgitを入れる前にWindowsにもgitを入れていた
特に変なことをしなければインストールに問題は起きないしVSCode拡張機能にも対応してくれている(この場合は絶対にAdjusting your PATH environmentで真ん中を選ぶ必要があるので注意)

git-scm.com

docs.microsoft.com

下の記事がわかりやすいかも

sukkiri.jp

Slackの用意

適当なメアドでサインインしてブラウザ上で適当にワークスペースを作って通知専用のチャンネルを作る
「設定と管理」「ワークスペースの設定」から「管理者設定」の画面が出るので左の「App管理」をクリック
上の「Appディレクトリ」で「webhook」を検索して「Incoming Webhook」をクリック,「Slackに追加」を選択
「チャンネルへの投稿」と「名前をカスタマイズ」「説明ラベル」を適当に編集して「Webhook URL」を確保

なお,複数のWebhook URLを使い分けたい場合は「Slackに追加」で更に作成できる,上限数は知らんけど

プロジェクト作成

良さげなディレクトリを作ったらVSCodeから開いて拡張機能からgit initする
次にVSCode内でPowershell(ターミナル)を開いてnpm init,適当に入力する<br. さらに以下をnpm installする

  • @slack/webhook
  • date-and-time
  • get-json
  • node-schedule
  • post-json
  • simple-get-json
  • simple-post-json

スクリプト作成

  • JSONデータのうちCPU温度がある場所については各自で確認すること
    • シングルCPUならobj[0]['Children'][1]['Children'][1]['Children']が持ってる配列に格納されている
  • 必ずhttp://localhost:[numTCPport]/data.jsonを叩くこと
    • これは実際ブラウザ上でJSONを確認できる
  • coreTempLimitで通知を出したいCPU温度の下限値を設定できる
const scheduler = require('node-schedule');
const { getJSON } = require('simple-get-json');
const datetime = require('date-and-time');
const { IncomingWebhook } = require("@slack/webhook");

const slackURL = "[slack webhook url]";
const slackWebhook = new IncomingWebhook(slackURL);
const monitorURL = "http://localhost:8085/data.json";

const coreTempLimit = 50;

async function accessJSON() {
    var res = await getJSON(monitorURL);
    var raw = JSON.stringify(res, null, 4);
    var obj = JSON.parse(raw)['Children'];
    var tgt = obj[0]['Children'][1]['Children'][1]['Children'];
    return tgt;
}

async function makeMessage(tgt) {
    var cpuParam = "";
    var coreName = "";
    var coreTemp = "";
    var heatFlag = false;

    tgt.forEach(cpuCore => {
        coreName = cpuCore['Text'];
        coreTemp = cpuCore['Value']
        cpuParam += (coreName + " is " + coreTemp + "\n")
        floatCoreTemp = parseFloat(coreTemp);
        if (floatCoreTemp > coreTempLimit) {
            heatFlag = true;
        }
    });
    var txt = cpuParam + datetime.format(new Date(), 'HH:mm:ss:SSS YYYY/MM/DD');
    var flg = heatFlag;
    console.log(flg);
    return [txt, flg];
}

async function sendMessage(txt, flg) {
    if (flg) {
        await slackWebhook.send({
            text: `${txt}`
        });
    }
}


const scheduleBase = scheduler.scheduleJob("*/1 * * * * *", function() {
    var tgt;
    var txt = "";
    var flg = false;
    (async() => {
        tgt = await accessJSON();
        [txt, flg] = await makeMessage(tgt);
        await sendMessage(txt, flg);
    })();
});

稼働

node index.jsで永久に稼働する,Slackにメッセージが飛べば成功
デバッグ代わりにflgを出力している

改善したいところ

  • 検知間隔の設定を改善
    • */1 * * * * *は1秒毎という意味,2なら2秒毎
  • GUI設定の実装
    • NodeJSのお得意技
  • データ化,グラフ化
  • ローカルネットワークで繋がる他の複数のPCと連携

complex modificationsのjson fileを利用したマルチボタンのマウス + macOS + Karabinerの設定

settings for multi button mouse + macOS + Karabiner with complex modifications .json file

何がしたいか

腱鞘炎対策にマルチボタンのついてる縦型マウスを買ったが,macOSは一部のメーカを除いてマウスごとのドライバというものがなく,またデフォルトではmagic mouse(左右ボタン+中ボタン兼スクローラ)と同程度の動作しか利用できない,そのためKarabinerといった入出力の変換ソフトが必要になる
今回はマルチボタンの有効化とその簡単な割り当てを紹介するが,基本的に左・右・中のボタン(1番・2番・3番)はあんまりイジらない,既存の動作に依存や干渉の関係があると面倒なので

注意

Karabinerは仕様の関係で割と動作が強力である(ほぼハードの動作と直結する)ため,下手をすると壊れて操作を受け付けなくなる可能性がある,なので自己責任で丁寧に作業をすること
一応はアプリごとに動作を変えられたりもするが,あくまでウィンドウがどこにあるか程度でしか判別してくれないので,もしそれがソフト側をイジるだけで解決する問題なら,なるべくソフト側だけをイジった方が良い
例えば ↓

soluna-eureka.hatenablog.com

インストール

cliで取得

brew install --cask karabiner-elements

formulae.brew.sh

これに限る
--caskなので/Applications/Karabiner-Elements.app/Applications/Karabiner-EventViewer.appがあればok,起動しよう

起動,システムへのアクセス許可

初回起動の時点で色々と権限を要求されるので,システム環境設定->セキュリティとプライバシーから適宜に承認する

フォルダの確認

~/.config/karabiner/assets/complex_modificationsが勝手に生成されていればOK,その配下に定義に則って作成された任意のjsonファイルを置くことで,自由に機能を追加できるし管理できる
実際なんだかんだでGUIには頼らずテキストで保存した方がいい,GUIだけでは複雑な挙動を検討できないし,ハードウェア設定をも考慮した本体プロファイルと分けないと混乱する

プログラムの確認

表からはKarabiner-ElementsKarabiner-EventViewerを起動できるが,前者は設定用・後者はデバッグ用に過ぎない
実際は初回起動において監視・制御のデーモンを裏で勝手に展開してくれる,次回起動からはログイン時に勝手にそれらが起動する,ログイン項目に登録する必要はない(ただし再読み込みはKarabiner-Elementsからやる必要がある)

f:id:Soluna_Eureka:20220221012821p:plain

設定

バイス登録

有線・無線・Bluetoothは関係なく,使いたいマウスを接続したらKarabiner-Elements->Devices->Basic configurationに移動,hoge Optional Mouse (fuga)が見つかるはずなので,左端チェックボックスから有効化する
ついでにVendor IDProduct IDをメモする,これらは後で条件設定の時に使いたい

f:id:Soluna_Eureka:20220221223804p:plain

Advancedは特に要らない

基本設定

混乱回避のため,Simple Modificationsを空欄にし,Function keysをリセットする(To Keyをそのまま割り振ると良い)

拡張ファイルの製作

以下に一例を示す

  • 共通設定
    • 5番のみでtab
    • 4番のみでshift+tab
  • ブラウザのみ
    • 1番+2番でcommand+r
    • 5番+6番でcommand+w
    • 1番+5番でcommand+click
    • 1番+4番でshift+click
    • 2番+5番でcommand+c
    • 2番+4番でcommand+v
{
    "title": "MouseWithFiveButtons",
    "rules": [{
        "description": "Define how how a mouse with 5 buttons works",
        "manipulators": [{
                "description": "Rcmd+'w',for Browsers (safari, chrome, firefox, vivaldi, ...) and Editor(vscode, ...)",
                "conditions": [{
                        "type": "device_if",
                        "identifiers": [{
                            "vendor_id": 7119,
                            "product_id": 5,
                            "description": "a mouse with 5 buttons"
                        }]
                    },
                    {
                        "type": "frontmost_application_if",
                        "bundle_identifiers": [
                            "^com\\.apple\\.Safari$",
                            "^com\\.google\\.Chrome$",
                            "^org\\.mozilla\\.firefox$",
                            "^com\\.vivaldi\\.Vivaldi$",
                            "^com\\.microsoft\\.VSCode$"
                        ]
                    }
                ],
                "type": "basic",
                "from": {
                    "simultaneous": [{
                            "pointing_button": "button4"
                        },
                        {
                            "pointing_button": "button5"
                        }
                    ]
                },
                "to": [{
                    "key_code": "w",
                    "modifiers": [
                        "right_command"
                    ]
                }]
            },
            {
                "description": "Rcmd+'w',for Browsers (safari, chrome, firefox, vivaldi, ...) and Editor(vscode, ...)",
                "conditions": [{
                        "type": "device_if",
                        "identifiers": [{
                            "vendor_id": 7119,
                            "product_id": 5,
                            "description": "a mouse with 5 buttons"
                        }]
                    },
                    {
                        "type": "frontmost_application_if",
                        "bundle_identifiers": [
                            "^com\\.apple\\.Safari$",
                            "^com\\.google\\.Chrome$",
                            "^org\\.mozilla\\.firefox$",
                            "^com\\.vivaldi\\.Vivaldi$",
                            "^com\\.microsoft\\.VSCode$"
                        ]
                    }
                ],
                "type": "basic",
                "from": {
                    "simultaneous": [{
                            "pointing_button": "button1"
                        },
                        {
                            "pointing_button": "button2"
                        }
                    ]
                },
                "to": [{
                    "key_code": "r",
                    "modifiers": [
                        "right_command"
                    ]
                }]
            },
            {
                "description": "Lsft+Lclk, for Browsers (safari, chrome, firefox, vivaldi, ...) and Editor(vscode, ...)",
                "conditions": [{
                        "type": "device_if",
                        "identifiers": [{
                            "vendor_id": 7119,
                            "product_id": 5,
                            "description": "a mouse with 5 buttons"
                        }]
                    },
                    {
                        "type": "frontmost_application_if",
                        "bundle_identifiers": [
                            "^com\\.apple\\.Safari$",
                            "^com\\.google\\.Chrome$",
                            "^org\\.mozilla\\.firefox$",
                            "^com\\.vivaldi\\.Vivaldi$",
                            "^com\\.microsoft\\.VSCode$"
                        ]
                    }
                ],
                "type": "basic",
                "from": {
                    "simultaneous": [{
                            "pointing_button": "button1"
                        },
                        {
                            "pointing_button": "button4"
                        }
                    ]
                },
                "to": [{
                    "pointing_button": "button1",
                    "modifiers": [
                        "left_shift"
                    ]
                }]
            },
            {
                "description": "Lcmd+Lclk,for Browsers (safari, chrome, firefox, vivaldi, ...) and Editor(vscode, ...)",
                "conditions": [{
                        "type": "device_if",
                        "identifiers": [{
                            "vendor_id": 7119,
                            "product_id": 5,
                            "description": "a mouse with 5 buttons"
                        }]
                    },
                    {
                        "type": "frontmost_application_if",
                        "bundle_identifiers": [
                            "^com\\.apple\\.Safari$",
                            "^com\\.google\\.Chrome$",
                            "^org\\.mozilla\\.firefox$",
                            "^com\\.vivaldi\\.Vivaldi$",
                            "^com\\.microsoft\\.VSCode$"
                        ]
                    }
                ],
                "type": "basic",
                "from": {
                    "simultaneous": [{
                            "pointing_button": "button1"
                        },
                        {
                            "pointing_button": "button5"
                        }
                    ]
                },
                "to": [{
                    "pointing_button": "button1",
                    "modifiers": [
                        "left_command"
                    ]
                }]
            },
            {
                "description": "Rcmd+'v',for Browsers (safari, chrome, firefox, vivaldi, ...) and Editor(vscode, ...)",
                "conditions": [{
                        "type": "device_if",
                        "identifiers": [{
                            "vendor_id": 7119,
                            "product_id": 5,
                            "description": "a mouse with 5 buttons"
                        }]
                    },
                    {
                        "type": "frontmost_application_if",
                        "bundle_identifiers": [
                            "^com\\.apple\\.Safari$",
                            "^com\\.google\\.Chrome$",
                            "^org\\.mozilla\\.firefox$",
                            "^com\\.vivaldi\\.Vivaldi$",
                            "^com\\.microsoft\\.VSCode$"
                        ]
                    }
                ],
                "type": "basic",
                "from": {
                    "simultaneous": [{
                            "pointing_button": "button2"
                        },
                        {
                            "pointing_button": "button4"
                        }
                    ]
                },
                "to": [{
                    "key_code": "v",
                    "modifiers": [
                        "right_command"
                    ]
                }]
            },
            {
                "description": "Rcmd+'c',for Browsers (safari, chrome, firefox, vivaldi, ...) and Editor(vscode, ...)",
                "conditions": [{
                        "type": "device_if",
                        "identifiers": [{
                            "vendor_id": 7119,
                            "product_id": 5,
                            "description": "a mouse with 5 buttons"
                        }]
                    },
                    {
                        "type": "frontmost_application_if",
                        "bundle_identifiers": [
                            "^com\\.apple\\.Safari$",
                            "^com\\.google\\.Chrome$",
                            "^org\\.mozilla\\.firefox$",
                            "^com\\.vivaldi\\.Vivaldi$",
                            "^com\\.microsoft\\.VSCode$"
                        ]
                    }
                ],
                "type": "basic",
                "from": {
                    "simultaneous": [{
                            "pointing_button": "button2"
                        },
                        {
                            "pointing_button": "button5"
                        }
                    ]
                },
                "to": [{
                    "key_code": "c",
                    "modifiers": [
                        "right_command"
                    ]
                }]
            },
            {
                "description": "global settings for mouse button 4",
                "conditions": [{
                    "type": "device_if",
                    "identifiers": [{
                        "vendor_id": 7119,
                        "product_id": 5,
                        "description": "a mouse with 5 buttons"
                    }]
                }],
                "type": "basic",
                "from": {
                    "pointing_button": "button4"
                },
                "to": [{
                    "key_code": "tab",
                    "modifiers": [
                        "right_shift"
                    ]
                }]
            },
            {
                "description": "global settings for mouse button 5",
                "conditions": [{
                    "type": "device_if",
                    "identifiers": [{
                        "vendor_id": 7119,
                        "product_id": 5,
                        "description": "a mouse with 5 buttons"
                    }]
                }],
                "type": "basic",
                "from": {
                    "pointing_button": "button5"
                },
                "to": [{
                    "key_code": "tab"
                }]
            }
        ]
    }]
}

これを~/.config/karabiner/assets/complex_modificationsに作成する

作成したらKarabiner-Elements->Complex Modifications->Rules->Add ruleを見る,構文ミスさえなければ表示されるので右端のEnableボタンでで有効化,ちなみにここにはファイル名は表示されないので注意(jsonオブジェクトのtitlerules.descriptionのみ表示される)

f:id:Soluna_Eureka:20220221225737p:plain

うまく有効化できたらMisc->Restart Karabiner-Elementsで再起動,これで完全に動作が反映されるはず

特徴

  • 同時押しsimultaneousによって修飾キー以外による同時押しに対応
    • 単一押しと使用するボタンやキーが被る場合は,simultaneousさせたい動作についてjsonオブジェクト上に先に記述すること,後に記述すると単一押しの方が優先されて判定を受けてしまい,同時押しの方は問答無用で無視されてしまう
    • それぞれの動作の定義がrules.manipulatorsの配列に格納される形であるため,処理の優先度が前後関係で決定されている可能性がある,そのためなるべく少ないjsonファイルに関連する設定をまとめた方がむしろ安心
    • 実はKarabiner-Elements->Complex Modifications->Parametersから設定できる
      • マウスで使うにはあまりにもシビアなので,猶予時間は長めにとった方が良いかも
      • f:id:Soluna_Eureka:20220221225755p:plain
  • アプリケーション判定frontmost_application_ifによってブラウザ限定動作に対応
    • マルチディスプレイで別々のアプリをトップに表示すると両方とも有効と扱われるので注意,シングルディスプレイを想定した実装しかされていない(意図しない動作が思わず発生する可能性がある)

カスタマイズ

  • rules.manipulators[].conditions[].identifiersには対応するvendor_idproduct_idが必要,各自で確認
  • マウスのボタン配置も確認して使いやすい組み合わせを検討
  • rules.manipulators[].conditions[].bundle_identifiersには対応するアプリのidentifiersが必要各自で確認
    • アプリを起動してlsappinfo info -only bundleid hogeすれば確認できる

qiita.com

解説

何を読めば理解できるか

公式ドキュメント

karabiner-elements.pqrs.org

jsonオブジェクトについて記載されている

判定時間の設定について

基本的には「キーを下げる」がpressの定義であって,一般的にはtoにて処理が起爆される.後述のhaltも使えるとは思うが動作は未確認,ドキュメントには例文どころか説明すら載ってないし使う価値もなさそう.
また「キーを(指定した時間より長く)下げ続ける」と処理が起爆するto_if_held_down,「下げたキーを上げる」と処理が起爆するto_after_key_upがあり,これら2つは両立して存在できる.その場合,to_if_held_downの中にhalt:trueを用いることで後続のto_after_key_upをキャンセルする,すなわちキーを下げ続ける時間で処理を変えることが可能になる.
to_if_aloneは「キーを(指定した時間より短く)単独で下げ続ける」と処理が起爆する,長く押し続けると判定がtoに移行する.同様にhalt:trueto_after_key_upをキャンセルして処理を変えることが可能になる.

もしくはfrom.simultaneousで修飾キー以外の複数入力を受け付けられるが,これはto系のメンバではなくfrom系のメンバであるために判定時間の概念が異なる.先に述べたようにrules.manipulatorsの配列の順番がfrom系のメンバの実行の優先順序になると推定されており,同じキーを利用した同時押しの判定をやりたいのであれば先に記述すべきである.

また包括されるキーの組み合わせを設定するのも全く推奨されない,例えばhoge+hugahogeを待ち受ける2つのfromオブジェクトがある場合,後者の設定をto_if_held_downでも設定しない限りaを下げて上げた瞬間に後者が起爆する.

総合的に考えると,今回の実装はえらく特殊なものである以上は,真似はしない方が良いだろう.
…実際に使うとなればKarabiner-Elements->Complex Modifications->Parametersto_if_alone_timeout_millisecondssimultaneous_threshold_millisecondsをイジるくらいで,これはデバイスの使用感に依存するだろう.
また変数をset_variableで設定してvariable_ifvariable_unlessで利用できるらしいが,使ったことがない…

`zsh`で`eval`する

evalとは

       eval [ arg ... ]
          Read the arguments as input to the shell and execute the resulting
          command(s) in the current shell process.  The return status is the
          same as if the commands had been executed directly by the shell;
          if there are no args or they contain no commands (i.e. are an
          empty string or whitespace) the return status is zero.

要するに文字列を標準入力としてシェルに与えて実行(した上でその返り値を取得)できる

何が嬉しいのか

変数展開の都合によって通常の記法によるシェルスクリプトでは設定できないようなコマンドをそのまま通すことができる
もっと手軽に言えば,変数展開の実行とevalの実行を分けてしまうことでより簡易に明確に文字列をインジェクションできる

soluna-eureka.hatenablog.com

例えば上記で扱ったc++ likeな文字列の取り扱いについても,シェルスクリプトの文面に直接的にコマンドを書かなくとも

#!/bin/zsh -eu
# this is testZsh5

arg="ab\ncd"

echo "for echo():"

cmd1="echo ${arg}"
cmd2="echo '${arg}'"
cmd3="echo \"${arg}\""
cmd4="echo $'${arg}'"
cmd5="echo $\"${arg}\""

eval ${cmd1}
eval ${cmd2}
eval ${cmd3}
eval ${cmd4}
eval ${cmd5}

echo "for printf():"

cmd6="printf \"%s\n\" ${arg}"
cmd7="printf \"%s\n\" '${arg}'"
cmd8="printf \"%s\n\" \"${arg}\""
cmd9="printf \"%s\n\" $'${arg}'"
cmd10="printf \"%s\n\" $\"${arg}\""

eval ${cmd6}
eval ${cmd7}
eval ${cmd8}
eval ${cmd9}
eval ${cmd10}
% testZsh5 
for echo():
abncd
ab
cd
ab
cd
ab
cd
$ab
cd
for printf():
abncd
ab\ncd
ab\ncd
ab
cd
$ab\ncd

とすればより使い分けやすくなるし挙動がより確実に追跡できる,これと同じものを生で記述するのはかなり面倒になるだろう

curl to ffmpeg

悪用厳禁

インスペクタを開いてネットワークを監視しながら動画を見ていると,ほぼ必ずcurl形式のダウンロードリンクがブラウザにエイリアスとして提供されていることが見て取れるが,そのheader要素をそのままffmpegに渡すことでローカルファイルに落とせる,というのもCookieやsessionによって行われる管理を維持したままブラウザ環境とCLI環境に対応させることができる

しかしいくらそれをコピペしようがcurlにはffmpegのような機能はなく(もし単純にmp4が落ちてくるならまだしもhlsの配信が相手だと無力である),またffmpegとはそれ自身のコマンドはもちろん渡されるオプションのフォーマットも違う,それなら以下のように--ffmpeg [動画ファイルの名前]を末尾に追記するだけで自動的にオプションを加工して(-Hを集めて-headersに渡す)ffmpegを呼び出せる(確実に実行ファイルを指定する)ようにすれば,かなり楽だろうと思われる
現状ではちゃんと動作している

#!/bin/zsh -eu
# this is curl with ffmpeg

default=$argv
ffmpeg='--ffmpeg'

zparseopts -D -E -a optionArray -A optionPair -ffmpeg: X+: H+:

if ((${+optionPair[$ffmpeg]})); then
    echo "--ffmpeg option allowed!"
    n=0
    type=""
    head=""
    for i in $optionArray; do
        (( n += 1))
        if [ $i = "-X" ]; then
            echo "type added"
            type=$type$optionArray[n+1]'\r\n'
        elif [ $i = "-H" ]; then
            echo "head added"
            head=$head$optionArray[n+1]'\r\n'
        fi
    done
    command="/usr/local/bin/ffmpeg -loglevel quirt -headers $'${head}' -i '${*}' -c copy ${optionPair[$ffmpeg]}"
    eval "${command}"
else
    /usr/local/opt/bin/curl ${default}
fi

youtubeとかは

ffmpegだけでは無理なサイトもあるが,そういう時はstreamlinkの方が強いのでそっちに任せたい,しかしstreamlinkも決して万能ではなく対応していないサイトの方がむしろ多い,表向きに.m3u8.mp4が出てくるサイトならffmpegで対応できるが…

soluna-eureka.hatenablog.com

youtube-dlとかよりstreamlinkの方が一元的に利用できて良い

formulae.brew.sh

`echo`と`printf`では制御文字の扱いが異なる件

ffmpegで気づいたこと

ffmpegでは-headersオプションを使えば複数のhttp headerを付与しつつ-iで指定したurlに向かってhttpで叩けるが,複数の内容を利用する際には改行するための制御文字を間々で認識させる必要があるらしく,その場合は$'...'で表せる.

note.kiriukun.com

そしてこの$'...'については確かにzshのmanページでも取り扱い方法が記載されていた,以下を参照のこと.

man zshmisc | col -b | expand -t 4 | pcre2grep -Moe ' {0}(QUOTING\n)( {7,}(\S* *)*\S*\n*)*'

見た感じではprintprintfc++の実装そのままで,対してechozsh用に作られた安全なものという印象を受けた.

zshで実験

準備

以下のシェルスクリプトを用いる

#!/bin/zsh -eu
# this is testZsh4

echo "all arguments : ${*}"

zparseopts -D -E -a optionArray -A optionPair test:

if ((${+optionArray})); then
    for i in $optionArray; do
        echo "echo: component: ${i}"
        printf "printf: %s\n" $i
    done
fi

if ((${+optionPair})); then
    for key in ${(@k)optionPair}; do
        echo "echo: flags: ${key} => value: ${optionPair[$key]}"
        printf "printf: flags: %s => value: %s\n" $key $optionPair[$key]
    done
fi

echo "other arguments : ${*}"

-testオプションにつける引数を変えれば処理の比較ができる

soluna-eureka.hatenablog.com

方針

改行文字を含めた文字列ab\ncdを対象に色々と変えてみよう!

ab\ncd

% testZsh4 -test ab\ncd
all arguments : -test abncd
echo: component: -test
printf: -test
echo: component: abncd
printf: abncd
echo: flags: -test => value: abncd
printf: flags: -test => value: abncd
other arguments : 

両者共に\が消えた

'ab\ncd'

% testZsh4 -test 'ab\ncd'
all arguments : -test ab
cd
echo: component: -test
printf: -test
echo: component: ab
cd

printf: ab\ncd
echo: flags: -test => value: ab
cd
printf: flags: -test => value: ab\ncd
other arguments : 

echoだけ改行文字が読まれた,printfでは文字として扱われた

"ab\ncd"

% testZsh4 -test "ab\ncd" 
all arguments : -test ab
cd
echo: component: -test
printf: -test
echo: component: ab
cd
printf: ab\ncd
echo: flags: -test => value: ab
cd
printf: flags: -test => value: ab\ncd
other arguments : 

'ab\ncd'と変わらない

$'ab\ncd'

% testZsh4 -test $'ab\ncd'
all arguments : -test ab
cd
echo: component: -test
printf: -test
echo: component: ab
cd
printf: ab
cd
echo: flags: -test => value: ab
cd
printf: flags: -test => value: ab
cd
other arguments : 

両者とも改行文字が読まれた

$"ab\ncd"

% testZsh4 -test $"ab\ncd"
all arguments : -test $ab
cd
echo: component: -test
printf: -test
echo: component: $ab
cd
printf: $ab\ncd
echo: flags: -test => value: $ab
cd
printf: flags: -test => value: $ab\ncd
other arguments : 

"..."の動作はそのまま先頭に$が入っただけだった

結論

printfをみるにc++系の実装なら$'...'することでほぼ確実に制御文字を反映させられるっぽい,またechoではそれよりも簡単に制御文字を反映させられるっぽい

ffmpegでの使いかた

-headersオプションは多重の呼び出しが不可能である(2回目からは内容が置き換わる)ため,前述の手法で制御文字を有効にすることではじめて複数の内容を利用できる.とは言えその中で頻用される幾つかはffmpeg側でも専用のオプションとして提供されており,本来ならばそういったものを利用するべきではないかとも考えられる(処理がめんどいって?それはそう).

詳細は以下で確認できる,-loglevel traceで動作が全て標準出力される,-loglevel quietで何も表示されない,また-i [url]-headers [header]より前に持ってくると-headers [header]が認識されない(なぜかドキュメントにはのってないけど)

% ffmpeg \
-loglevel trace \
-headers $'Hoge: hoge\r\nHuga: huga' \
-i 'http://example.com/playlist.m3u8' \
-c copy \
output.mp4
...
User-Agent: Lavf/58.76.100
Accept: */*
Range: bytes=0-
Connection: close
Host: example.com
Icy-MetaData: 1
Hoge: hoge
Huga: huga
...

以上の結果が得られればヘッダが正しく設定されたと言える(該当の動画は存在しないので最終的にはerrorが返される)
本来\r\nms-doswindowsで利用される作法であり,旧MacOSでは\rのみ・現macOSでは\nのみがそれぞれの「標準の改行コード」である,なので\nだけで十分ではある…のだが心配なので\r\nすることを癖にしても良いかもしれない,実際の\rmacOSにおいて「同じ行の先頭まで戻る(そして出力が順に置き換わる)」動作を表すので余計な改行にはならないはず

おまけ

これ読めばわかると思われるが…?

QUOTING
       A character may be quoted (that is, made to stand for itself) by
       preceding it with a `\'.  `\' followed by a newline is ignored.

       A string enclosed between `$'' and `'' is processed the same way as the
       string arguments of the print builtin, and the resulting string is
       considered to be entirely quoted.  A literal `'' character can be
       included in the string by using the `\'' escape.

       All characters enclosed between a pair of single quotes ('') that is not
       preceded by a `$' are quoted.  A single quote cannot appear within single
       quotes unless the option RC_QUOTES is set, in which case a pair of single
       quotes are turned into a single quote.  For example,

          print ''''

       outputs nothing apart from a newline if RC_QUOTES is not set, but one
       single quote if it is set.

       Inside double quotes (""), parameter and command substitution occur, and
       `\' quotes the characters `\', ``', `"', `$', and the first character of
       $histchars (default `!').