見出し画像

解説クラスCopyClear(36)

解説クラスCopyClear(36)


2025年2月27初稿(初講)

この解説は、膨大なクラス「class CopyClear」の定義を
記載したファイル「CopyClear.h」の順番に従い解説して
行く為に今回は、「private:属性」の関数の説明を行う
事にします!今回は「sort_key()」関数からソート系の
説明します!
この解説文章は、
解説『解説クラスCopyClear(35)』の続きです

(4-15-116)関数「void sort_key(TypeSort* pl,TypeSort* pr){・・・}」

/************************************************************************/
/*****  QUIC-SORT:キー付き昇順ソート                      *****/
/*****  ※注1:データを交換するとき、TypeSort型=32bitsを利用して  *****/
/*****          int型=32bitsと見なして処理しています。             *****/
/************************************************************************/

void                        CopyClear::sort_key(
    CopyClear::TypeSort     *pl,                    // データの左側Ptr
    CopyClear::TypeSort     *pr                     // データの右側Ptr
){
    TypeSort    *pi;                                // 内部Ptr
    TypeSort    *pj;                                // 内部Ptr
    short       key;                                // 中央の値
    int         w;                                  // 交換用の場所

    pi  = pl;                                       // 左側をSet
    pj  = pr;                                       // 右側をSet
    key = ( pi + ( (int)pj - (int)pi )              // 右左の中央値を
                / ( 2 * sizeof(TypeSort) ) )->key;  // セット
    do{                                             // 以下繰り返し
        while( pi->key < key ){                     // 左側が小さい間
            pi++;                                   // 左側を中に進める
        }                                           //
        while( key < pj->key ){                     // 右側が大きい間
            pj--;                                   // 右側を中に進める
        }                                           //
        if( pi <= pj ){                             // 左 ≦ 右 なら
            w         = *(int*)pi;                  // 左右を
            *pi       = *pj;                        // 交換
            *(int*)pj = w;                          // し
            pi++;                                   // 左側を中に進める
            pj--;                                   // 右側を中に進める
        }                                           //
    }while( pi <= pj );                             // 左≦右なら繰返し
    if( pl < pj ){                                  // 外左 < 中右 なら
        sort_key( pl, pj );                         // この間をソート
    }                                               //
    if( pi < pr ){                                  // 中左 < 外右 なら
        sort_key( pi, pr );                         // この間をソート
    }                                               //
}

☆備考☆この関数はファイル「CopyClear100.cpp」に存在!
★注意★この関数は「private:属性」ですのでライブラリの
外から使用不能です!

(A)関数「sort_key();」の【関数名】

「Sort」は、勿論、英単語「sort」、カタカナ語ソート・
ソーティング、詰り並び替えです!
「key」は、キー付きを意味します!
この関数は、キー付きのデータ配列を昇順≪小さい方から
大きい方へ整列≫にソートする関数
★備考★「_」で区切って居るのは、極初期に作成された
ので区切りに「_」を使用するか、単語先頭「英大文字」と
色々迷って居た時期です!

(B)関数「void sort_key();」の【返値】

返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!

(C)関数「sort_key()」の【仮引数】

void                        CopyClear::sort_key(
    CopyClear::TypeSort     *pl,                    // データの左側Ptr
    CopyClear::TypeSort     *pr                     // データの右側Ptr
){

「TypeSort* pl,」は、データ配列左端「l=left省略」
「TypeSort* pr」は、データ配列右端「r=right省略」
ここで使用する専用の型「TypeSort」≪
解説『解説クラスCopyClear(1)』の「(3)
クラス内ローカル構造体定義」で解説≫

(D)関数「sort_key()」の【アルゴリズム】

){
    TypeSort    *pi;                                // 内部Ptr
    TypeSort    *pj;                                // 内部Ptr
    short       key;                                // 中央の値
    int         w;                                  // 交換用の場所

    pi  = pl;                                       // 左側をSet
    pj  = pr;                                       // 右側をSet
    key = ( pi + ( (int)pj - (int)pi )              // 右左の中央値を
                / ( 2 * sizeof(TypeSort) ) )->key;  // セット
    do{                                             // 以下繰り返し
        while( pi->key < key ){                     // 左側が小さい間
            pi++;                                   // 左側を中に進める
        }                                           //
        while( key < pj->key ){                     // 右側が大きい間
            pj--;                                   // 右側を中に進める
        }                                           //
        if( pi <= pj ){                             // 左 ≦ 右 なら
            w         = *(int*)pi;                  // 左右を
            *pi       = *pj;                        // 交換
            *(int*)pj = w;                          // し
            pi++;                                   // 左側を中に進める
            pj--;                                   // 右側を中に進める
        }                                           //
    }while( pi <= pj );                             // 左≦右なら繰返し
    if( pl < pj ){                                  // 外左 < 中右 なら
        sort_key( pl, pj );                         // この間をソート
    }                                               //
    if( pi < pr ){                                  // 中左 < 外右 なら
        sort_key( pi, pr );                         // この間をソート
    }                                               //
}

(D-1)ローカル変数

){
    TypeSort    *pi;                                // 内部Ptr
    TypeSort    *pj;                                // 内部Ptr
    short       key;                                // 中央の値
    int         w;                                  // 交換用の場所

「TypeSort* pi;」は、内部ポインタ(左側用)
「TypeSort* pj;」は、内部ポインタ(右側用)
「short key;」は、中央の値(キー比較用)
「int w;」は、データ交換用の場所

(D―2)アルゴリズムコード

    pi  = pl;                                       // 左側をSet
    pj  = pr;                                       // 右側をSet
    key = ( pi + ( (int)pj - (int)pi )              // 右左の中央値を
                / ( 2 * sizeof(TypeSort) ) )->key;  // セット
    do{                                             // 以下繰り返し
        while( pi->key < key ){                     // 左側が小さい間
            pi++;                                   // 左側を中に進める
        }                                           //
        while( key < pj->key ){                     // 右側が大きい間
            pj--;                                   // 右側を中に進める
        }                                           //
        if( pi <= pj ){                             // 左 ≦ 右 なら
            w         = *(int*)pi;                  // 左右を
            *pi       = *pj;                        // 交換
            *(int*)pj = w;                          // し
            pi++;                                   // 左側を中に進める
            pj--;                                   // 右側を中に進める
        }                                           //
    }while( pi <= pj );                             // 左≦右なら繰返し
    if( pl < pj ){                                  // 外左 < 中右 なら
        sort_key( pl, pj );                         // この間をソート
    }                                               //
    if( pi < pr ){                                  // 中左 < 外右 なら
        sort_key( pi, pr );                         // この間をソート
    }                                               //
}

「pi=pl;pj=pr;」は、ローカルな左側・右側をセット
「key=(pi+((int)pj-(int)pi)/(2*sizeof(TypeSort)))
->key;」は、左右の中央の場所(ポインタの中央)の
キー値「->key」を取り出す!
二重ループで外側の
do構文「・・外側ループ本体・・}while(pi<=pj);」と
後置ループ条件「pi<=pj」と内部のポインタの左右関係が
保たれている間繰り返す!そして最初の内側のループ
「while(pi->key<key){pi++;}」は、while構文で
ループ条件「pi->key<key」は、「左側のキーの値が、
比較用の値未満」の間「pi++;」ポインタを右側に移動を
繰り返すと、即ち、「左側がキーの値以上に成るまで繰り
返す」、次の内側ループ
「while(key<pj->key){pj--;}」は、「右」側のキーの
値が、比較用の値越え」の間「pj--;」ポインタを左側に
移動を繰り返すと、即ち、「右側がキーの値以下に成るまで
繰り返す」、そしてif構文
「if(pi<=pj){w=*(int*)pi;*pi=*pj;*(int*)pj=w;pi++;
pj--;}」は、条件「pi<=pj」と左右関係が保たれていたら
「w=*(int)pi;*pi=*pj;*(int*)pj=w;pi++;pj--;}」で先ず
「w=*(int)pi;*pi=*pj;*(int*)pj=w;」で左右を入れ替え、
「pi++;pj--;」とローカル左右ポインタを進める!
★備考★「w=*(int*)pi;」とか「*(int*)pj=w;」で
キャスト「型変換」として「(int*)」とローカル変数
「int w;」と「TypeSort型」と「int型」が4バイトに成る
事を確認した処理系で使用して居ます!この前提が崩れた
CPU&コンパイラシステムの場合は、書き換える必要が
有る事に留意!
そして「if(pl<pj){sort_key(pl,pj);}」で再帰呼び出しを
自分自身「sort_key()」関数をサブルーチン関数として
条件「pl<pj」=「元々の左側が内部の右側と左右関係が保
たれて居る」なら、再帰呼び出し「sort_key(pl,pj);」を
行う事で数学の「帰納的定義法」と考えて再帰呼び出しを
行った部分「plからpjのポインタの示す左右範囲」が昇順に
ソート済みと見なして処理する方法です!★備考★これが
再帰呼び出しを行う事で実現する「クイックソート」と呼ば
れる通常のデータでは最速と言われているアルゴリズムです
同じ様に「if(pi<pr){sort_key(pi,pr);}」で範囲
「piからpr」のポインタの示す左右範囲」が昇順に
ソート済みと見なして処理します!★備考★これが、
再帰呼び出しを行う事で実現する「クイックソート」と呼ば
れる通常のデータでは最速と言われているアルゴリズムです
コレは、多くの画像処理以外のプログラミングで使用されて
居ますので数学的帰納法をアルゴリズムに応用した事を理解
して下さい!C言語的には「再帰呼び出し」との文言で平気
で多用します!

(4-15-117)関数「void sort_key_rev(
TypeSort* pl,TypeSort* pr){・・・}」

/************************************************************************/
/*****  QUIC-SORT:キー付き降順ソート                      *****/
/*****  ※注1:データを交換するとき、TypeSort型=32bitsを利用して  *****/
/*****          int型=32bitsと見なして処理しています。             *****/
/************************************************************************/

void                        CopyClear::sort_key_rev(
    CopyClear::TypeSort     *pl,                    // データの左側Ptr
    CopyClear::TypeSort     *pr                     // データの右側Ptr
){
    TypeSort    *pi;                                // 内部Ptr
    TypeSort    *pj;                                // 内部Ptr
    short       key;                                // 中央の値
    int         w;                                  // 交換用の場所

    pi  = pl;                                       // 左側をSet
    pj  = pr;                                       // 右側をSet
    key = ( pi + ( (int)pj - (int)pi )              // 右左の中央値を
                / ( 2 * sizeof(TypeSort) ) )->key;  // セット
    do{                                             // 以下繰り返し
        while( pi->key > key ){                     // 左側が大きい間
            pi++;                                   // 左側を中に進める
        }                                           //
        while( key > pj->key ){                     // 右側が小さい間
            pj--;                                   // 右側を中に進める
        }                                           //
        if( pi <= pj ){                             // 左 ≦ 右 なら
            w         = *(int*)pi;                  // 左右を
            *pi       = *pj;                        // 交換
            *(int*)pj = w;                          // し
            pi++;                                   // 左側を中に進める
            pj--;                                   // 右側を中に進める
        }                                           //
    }while( pi <= pj );                             // 左≦右なら繰返し
    if( pl < pj ){                                  // 外左 < 中右 なら
        sort_key_rev( pl, pj );                     // この間をソート
    }                                               //
    if( pi < pr ){                                  // 中左 < 外右 なら
        sort_key_rev( pi, pr );                     // この間をソート
    }                                               //
}

☆備考☆この関数はファイル「CopyClear100.cpp」に存在!
★注意★この関数は「private:属性」ですのでライブラリの
外から使用不能です!

(A)関数「sort_key_rev();」の【関数名】

「Sort」は、勿論、英単語「sort」、カタカナ語ソート・
ソーティング、詰り並び替えです!
「key」は、キー付きを意味します!
「rev」は、英単語「reversal」の省略で「逆転」の意味
です!ソートを逆順≪降順「大きい方から小さい方へ整列」
≫で行います!
この関数は、キー付きのデータ配列を降順にソートする関数
★備考★降順≪大きい方からへ小さい方に整列≫
★備考★「_」で区切って居るのは、極初期に作成された
ので区切りに「_」を使用するか、単語先頭「英大文字」と
色々迷って居た時期です!

(B)関数「void sort_key_rev();」の【返値】

返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!

(C)関数「sort_key_rev()」の【仮引数】

void                        CopyClear::sort_key_rev(
    CopyClear::TypeSort     *pl,                    // データの左側Ptr
    CopyClear::TypeSort     *pr                     // データの右側Ptr
){

「TypeSort* pl,」は、データ配列左端「l=left省略」
「TypeSort* pr」は、データ配列右端「r=right省略」
ここで使用する専用の型「TypeSort」≪
解説『解説クラスCopyClear(1)』の「(3)
クラス内ローカル構造体定義」で解説≫

(D)関数「sort_key_rev()」の【アルゴリズム】

){
    TypeSort    *pi;                                // 内部Ptr
    TypeSort    *pj;                                // 内部Ptr
    short       key;                                // 中央の値
    int         w;                                  // 交換用の場所

    pi  = pl;                                       // 左側をSet
    pj  = pr;                                       // 右側をSet
    key = ( pi + ( (int)pj - (int)pi )              // 右左の中央値を
                / ( 2 * sizeof(TypeSort) ) )->key;  // セット
    do{                                             // 以下繰り返し
        while( pi->key > key ){                     // 左側が大きい間
            pi++;                                   // 左側を中に進める
        }                                           //
        while( key > pj->key ){                     // 右側が小さい間
            pj--;                                   // 右側を中に進める
        }                                           //
        if( pi <= pj ){                             // 左 ≦ 右 なら
            w         = *(int*)pi;                  // 左右を
            *pi       = *pj;                        // 交換
            *(int*)pj = w;                          // し
            pi++;                                   // 左側を中に進める
            pj--;                                   // 右側を中に進める
        }                                           //
    }while( pi <= pj );                             // 左≦右なら繰返し
    if( pl < pj ){                                  // 外左 < 中右 なら
        sort_key_rev( pl, pj );                     // この間をソート
    }                                               //
    if( pi < pr ){                                  // 中左 < 外右 なら
        sort_key_rev( pi, pr );                     // この間をソート
    }                                               //
}

(D-1)ローカル変数

){
    TypeSort    *pi;                                // 内部Ptr
    TypeSort    *pj;                                // 内部Ptr
    short       key;                                // 中央の値
    int         w;                                  // 交換用の場所

「TypeSort* pi;」は、内部ポインタ(左側用)
「TypeSort* pj;」は、内部ポインタ(右側用)
「short key;」は、中央の値(キー比較用)
「int w;」は、データ交換用の場所

(D―2)アルゴリズムコード

    pi  = pl;                                       // 左側をSet
    pj  = pr;                                       // 右側をSet
    key = ( pi + ( (int)pj - (int)pi )              // 右左の中央値を
                / ( 2 * sizeof(TypeSort) ) )->key;  // セット
    do{                                             // 以下繰り返し
        while( pi->key > key ){                     // 左側が大きい間
            pi++;                                   // 左側を中に進める
        }                                           //
        while( key > pj->key ){                     // 右側が小さい間
            pj--;                                   // 右側を中に進める
        }                                           //
        if( pi <= pj ){                             // 左 ≦ 右 なら
            w         = *(int*)pi;                  // 左右を
            *pi       = *pj;                        // 交換
            *(int*)pj = w;                          // し
            pi++;                                   // 左側を中に進める
            pj--;                                   // 右側を中に進める
        }                                           //
    }while( pi <= pj );                             // 左≦右なら繰返し
    if( pl < pj ){                                  // 外左 < 中右 なら
        sort_key_rev( pl, pj );                     // この間をソート
    }                                               //
    if( pi < pr ){                                  // 中左 < 外右 なら
        sort_key_rev( pi, pr );                     // この間をソート
    }                                               //
}

「pi=pl;pj=pr;」は、ローカルな左側・右側をセット
「key=(pi+((int)pj-(int)pi)/(2*sizeof(TypeSort)))
->key;」は、左右の中央の場所(ポインタの中央)の
キー値「->key」を取り出す!
二重ループで外側の
do構文「・・外側ループ本体・・}while(pi<=pj);」と
後置ループ条件「pi<=pj」と内部のポインタの左右関係が
保たれている間繰り返す!そして最初の内側のループ
「while(pi->key>key){pi++;}」は、while構文で
ループ条件「pi->key>key」は、「左側のキーの値が、
比較用の値越え」の間「pi++;」ポインタを右側に移動を
繰り返すと、即ち、「左側がキーの値以下に成るまで繰り
返す」、次の内側ループ
「while(key>pj->key){pj--;}」は、「右」側のキーの
値が、比較用の値未満」の間「pj--;」ポインタを左側に
移動を繰り返すと、即ち、「右側がキーの値以下に成るまで
繰り返す」、そしてif構文
「if(pi<=pj){w=*(int*)pi;*pi=*pj;*(int*)pj=w;pi++;
pj--;}」は、条件「pi<=pj」と左右関係が保たれていたら
「w=*(int*)pi;*pi=*pj;*(int*)pj=w;pi++;pj--;}」で先ず
「w=*(int*)pi;*pi=*pj;*(int*)pj=w;」で左右を入れ替え、
「pi++;pj--;」とローカル左右ポインタを進める!
キャスト「型変換」として「(int*)」とローカル変数
「int w;」と「TypeSort型」と「int型」が4バイトに成る
事を確認した処理系で使用して居ます!この前提が崩れた
CPU&コンパイラシステムの場合は、書き換える必要が
有る事に留意!
そして「if(pl<pj){sort_key_rev(pl,pj);}」で再帰呼び出しを
自分自身「sort_key_rev()」関数をサブルーチン関数として
条件「pl<pj」=「元々の左側が内部の右側と左右関係が保
たれて居る」なら、再帰呼び出し「sort_key_rev(pl,pj);」を
行う事で数学の「帰納的定義法」と考えて再帰呼び出しを
行った部分「plからpjのポインタの示す左右範囲」が降順に
ソート済みと見なして処理する方法です!★備考★これが
再帰呼び出しを行う事で実現する「クイックソート」と呼ば
れる通常のデータでは最速と言われているアルゴリズムです
同じ様に「if(pi<pr){sort_key_rev(pi,pr);}」で範囲
「piからpr」のポインタの示す左右範囲」が降順に
ソート済みと見なして処理します!★備考★これが、
再帰呼び出しを行う事で実現する「クイックソート」と呼ば
れる通常のデータでは最速と言われているアルゴリズムです
コレは、多くの画像処理以外のプログラミングで使用されて
居ますので数学的帰納法をアルゴリズムに応用した事を理解
して下さい!C言語的には「再帰呼び出し」との文言で平気
で多用します!

(4-15-118)関数「void hist_byte(int hist[],BYTE* p,int l){・・・}」

/************************************************************************/
/*****      ヒストグラムソート用配列のヒストグラム算出              *****/
/************************************************************************/

void            CopyClear::hist_byte(
    int         hist[],                             // ヒストグラム配列
    BYTE        *p,                                 // データ配列のPtr
    int         l                                   // 配列のサイズ
){
    BYTE        *pend;                              // 終点のPtr

    up_fill_int( 0, hist, 256 );                    // Histogram初期化
    pend  = p + l;                                  // 終点作成
    l   >>= 3;                                      // 8単位毎に
    while( --l >= 0 ){                              // データ配列の
        hist[ *p++ ]++;                             // ヒストグラム算出
        hist[ *p++ ]++;                             // 
        hist[ *p++ ]++;                             // 
        hist[ *p++ ]++;                             // 
        hist[ *p++ ]++;                             // 
        hist[ *p++ ]++;                             // 
        hist[ *p++ ]++;                             // 
        hist[ *p++ ]++;                             // 
    }                                               // 
    while( p < pend ){                              // 残りの
        hist[ *p++ ]++;                             // ヒストグラム算出
    }                                               // 
}

☆備考☆この関数はファイル「CopyClear100.cpp」に存在!
★注意★この関数は「private:属性」ですのでライブラリの
外から使用不能です!

(A)関数「hist_byte();」の【関数名】

「hist」は、英単語「histogram」の略でカタカナ語
ヒストグラムで日本語では度数分布です!
「byte」は、勿論、「BYTE型」、画素が1バイトデータを
意味!
この関数は、対象データ配列のソートする為のヒストグラム
を算出する関数
★備考★画像処理の「ランキングフィルター」と言う処理では、恐ろしい程の高速化を発揮するヒストグラムを使用したソート技法ですが、普通の処理では「最も遅いソーティングアルゴリズム」と思われます!何故、極めて遅いアルゴリズムがランキングフィルター系の関数で高速化処理に成るかは
エッセイ『ヒストグラムソートとランキングフィルター』で解説!
そして、この関数は、コレを使用している関数
「sort_byte_hist()」で使用しているだけでランキングフィ
ルター作成時の実験に使用しただけの関数です!
★備考★「_」で区切って居るのは、極初期に作成された
ので区切りに「_」を使用するか、単語先頭「英大文字」と
色々迷って居た時期です!

(B)関数「void hist_byte();」の【返値】

返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!

(C)関数「hist_byte()」の【仮引数】

void            CopyClear::hist_byte(
    int         hist[],                             // ヒストグラム配列
    BYTE        *p,                                 // データ配列のPtr
    int         l                                   // 配列のサイズ
){

「int hist[],」は、ヒストグラムデータ
「BYTE* p,」は、ソート対象データ配列
「int l」は、対象データ配列のサイズ

(D)関数「hist_byte()」の【アルゴリズム】

){
    BYTE        *pend;                              // 終点のPtr

    up_fill_int( 0, hist, 256 );                    // Histogram初期化
    pend  = p + l;                                  // 終点作成
    l   >>= 3;                                      // 8単位毎に
    while( --l >= 0 ){                              // データ配列の
        hist[ *p++ ]++;                             // ヒストグラム算出
        hist[ *p++ ]++;                             // 
        hist[ *p++ ]++;                             // 
        hist[ *p++ ]++;                             // 
        hist[ *p++ ]++;                             // 
        hist[ *p++ ]++;                             // 
        hist[ *p++ ]++;                             // 
        hist[ *p++ ]++;                             // 
    }                                               // 
    while( p < pend ){                              // 残りの
        hist[ *p++ ]++;                             // ヒストグラム算出
    }                                               // 
}

(D-1)ローカル変数

){
    BYTE        *pend;                              // 終点のPtr

「BYTE *pend;」は、データ配列終点

(D―2)アルゴリズムコード

    up_fill_int( 0, hist, 256 );                    // Histogram初期化
    pend  = p + l;                                  // 終点作成
    l   >>= 3;                                      // 8単位毎に
    while( --l >= 0 ){                              // データ配列の
        hist[ *p++ ]++;                             // ヒストグラム算出
        hist[ *p++ ]++;                             // 
        hist[ *p++ ]++;                             // 
        hist[ *p++ ]++;                             // 
        hist[ *p++ ]++;                             // 
        hist[ *p++ ]++;                             // 
        hist[ *p++ ]++;                             // 
        hist[ *p++ ]++;                             // 
    }                                               // 
    while( p < pend ){                              // 残りの
        hist[ *p++ ]++;                             // ヒストグラム算出
    }                                               // 
}

「up_fill_int(0,hist,256);」は、ヒストグラムデータを
初期化≪0クリア≫
「pend=p+l;l>>=3;」は、終点ポインタをセットと
「l>>=3;」≪シフト演算で「÷8」★備考★極初期に
高速化を考えたので分かり易い依り早いアルゴリズムを
考えた残滓だが今のCPUでは余り意味が無い!≫で8単位
毎の数に変更
「while(--l>=0){・・ループ本体・・}」は、8単位毎に
ダウンカウンタ方式≪高速化処理≫で繰り返し、ループ本体
「hist[*p++]++;hist[*p++]++;hist[*p++]++;hist[*p++]++;
hist[*p++]++;hist[*p++]++;hist[*p++]++;hist[*p++]++;」
は、基本のヒストグラム算出「hist[*p++]++;」を8単位
並べた物です!★備考★「*p++」で画素データ配列の値取り
出しと次へポインタ進行、「hist[式]++;」で仮引数
「int hist[],」のヒストグラムデータの所定の場所を
「++」とヒストグラム(度数分布)自体カウントアップ
して居る事は、理解出来ますね!
そして余りの画素データ配列に対して
「while(p<pend){hist[*p++]++;}」で画素データ配列の
最後までヒストグラムデータ算出!

(4-15-119)関数「void sort_byte_hist(int sw,BYTE* p,int l){・・・}」

/************************************************************************/
/*****      ヒストグラムソート:データ=8bits                      *****/
/************************************************************************/

void            CopyClear::sort_byte_hist(
    int         sw,                                 // 0:昇順、1:降順
    BYTE        *p,                                 // データ配列のPtr
    int         l                                   // 配列のサイズ
){
    int         hist[ 256 ];                        // ヒストグラム配列
    int         *ph;                                // 上記へのポインタ
    int         i;                                  // カウンタ

    hist_byte( hist, p, l );                        // ヒストグラム算出
    if( sw == 0 ){                                  // 昇順なら
        ph = hist;                                  // HistogramPtrをSet
        for( i = 0; i <= 255; i++ ){                // 0..255 の間で
            l = *ph++;                              // 対応する頻度を取
            while( --l >= 0 ){                      // り出しその頻度分
                *p++ = i;                           // データを書き込む
            }                                       // 
        }                                           // 
    }else{                                          // 降順なら
        ph = &hist[ 256 ];                          // HistogramPtrをSet
        for( i = 255; i >= 0; i-- ){                // 255..0 の間で
            l = *--ph;                              // 対応する頻度を取
            while( --l >= 0 ){                      // り出しその頻度分
                *p++ = i;                           // データを書き込む
            }                                       // 
        }                                           // 
    }                                               // 
}

☆備考☆この関数はファイル「CopyClear100.cpp」に存在!
★注意★この関数は「private:属性」ですのでライブラリの
外から使用不能です!

(A)関数「sort_byte_hist();」の【関数名】

「hist」は、英単語「histogram」の略でカタカナ語
ヒストグラムで日本語では度数分布です!
「byte」は、勿論、「BYTE型」、画素が1バイトデータを
意味!
「hist」は、ヒストグラムサーチアルゴリズムを使用して
ソートする為の関数です!
★備考★画像処理の「ランキングフィルター」と言う処理で
は、恐ろしい程の高速化を発揮するヒストグラムを使用した
ソート技法ですが、普通の処理では「最も遅いソーティング
アルゴリズム」と思われます!何故、極めて遅いアルゴリズ
ムがランキングフィルター系の関数で高速化処理に成るかは
エッセイ『ヒストグラムソートとランキングフィルター』
解説!
そして、この関数「sort_byte_hist()」はランキングフィ
ルター作成時の実験に使用しただけの関数です!
★備考★「_」で区切って居るのは、極初期に作成された
ので区切りに「_」を使用するか、単語先頭「英大文字」と
色々迷って居た時期です!

(B)関数「void sort_byte_hist();」の【返値】

返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!

(C)関数「sort_byte_hist()」の【仮引数】

void            CopyClear::sort_byte_hist(
    int         sw,                                 // 0:昇順、1:降順
    BYTE        *p,                                 // データ配列のPtr
    int         l                                   // 配列のサイズ
){

「int sw,」は、ソーティング向き≪0:昇順、1:降順≫
★備考★昇順≪小さい方からへ大きい方に整列≫
★備考★降順≪大きい方からへ小さい方に整列≫
「BYTE* p,」は、ソート対象データ配列
「int l」は、対象データ配列のサイズ

(D)関数「sort_byte_hist()」の【アルゴリズム】

){
    int         hist[ 256 ];                        // ヒストグラム配列
    int         *ph;                                // 上記へのポインタ
    int         i;                                  // カウンタ

    hist_byte( hist, p, l );                        // ヒストグラム算出
    if( sw == 0 ){                                  // 昇順なら
        ph = hist;                                  // HistogramPtrをSet
        for( i = 0; i <= 255; i++ ){                // 0..255 の間で
            l = *ph++;                              // 対応する頻度を取
            while( --l >= 0 ){                      // り出しその頻度分
                *p++ = i;                           // データを書き込む
            }                                       // 
        }                                           // 
    }else{                                          // 降順なら
        ph = &hist[ 256 ];                          // HistogramPtrをSet
        for( i = 255; i >= 0; i-- ){                // 255..0 の間で
            l = *--ph;                              // 対応する頻度を取
            while( --l >= 0 ){                      // り出しその頻度分
                *p++ = i;                           // データを書き込む
            }                                       // 
        }                                           // 
    }                                               // 
}

(D-1)ローカル変数

){
    int         hist[ 256 ];                        // ヒストグラム配列
    int         *ph;                                // 上記へのポインタ
    int         i;                                  // カウンタ

「int hist[256];」は、ヒストグラムデータ配列
「int* ph;」は、上記への操作ポインタ
「int i;」は、ループカウンタ

(D―2)アルゴリズムコード

    hist_byte( hist, p, l );                        // ヒストグラム算出
    if( sw == 0 ){                                  // 昇順なら
        ph = hist;                                  // HistogramPtrをSet
        for( i = 0; i <= 255; i++ ){                // 0..255 の間で
            l = *ph++;                              // 対応する頻度を取
            while( --l >= 0 ){                      // り出しその頻度分
                *p++ = i;                           // データを書き込む
            }                                       // 
        }                                           // 
    }else{                                          // 降順なら
        ph = &hist[ 256 ];                          // HistogramPtrをSet
        for( i = 255; i >= 0; i-- ){                // 255..0 の間で
            l = *--ph;                              // 対応する頻度を取
            while( --l >= 0 ){                      // り出しその頻度分
                *p++ = i;                           // データを書き込む
            }                                       // 
        }                                           // 
    }                                               // 
}

「hist_byte(hist,p,l);」は、1バイト単位画素のデータ
配列からヒストグラムデータ算出

「if(sw==0){ph=hist;for(i=0;i<=255;i++){l=*ph++;
while(--l>=0){*p++=i;}}}」は、if構文「if(sw==0){
・・成立・・}」で条件「sw==0」と昇順ソートの場合が
「ph=hist;」と操作ポインタに先頭をセットし、
「for(i=0;i<=255;i++){・・外側ループ本体・・}」は、
二重ループの外側ループでアップカウンタ「i=0..255」
まで繰り返し、その外側ループ本体で、先ず、
「l=*ph++;」は、ヒストグラムデータ取り出し、
「while(--l>=0){*p++=i;}」は、while構文で内側
ループを構成し、内側ループ条件「--l>=0」とダウンカウ
ンタ方式≪取り出したヒストグラムの値分繰り返し≫で内側
ループ本体「p++=i;」と書き込む!
「else{ph=&hist[256];for(i=255;i>=0;i--){l=--ph;
while(--l>=0){p++=i;}}}」は、「else{・・不成立・・
}」と「降順」の場合の処理で、
「ph=&hist[256];」と操作ポインタに終点をセットし、
「for(i=255;i>=0;i--){外側ループ本体・・}」は、
二重ループの外側ループでダウンカウンタ「i=255..0」
まで繰り返し、その外側ループ本体で、先ず、
「l=--ph;」は、ヒストグラムデータ取り出し、
「while(--l>=0){*p++=i;}」は、while構文で内側
ループを構成し、内側ループ条件「--l>=0」とダウンカウ
ンタ方式≪取り出したヒストグラムの値分繰り返し≫で内側
ループ本体「*p++=i;」と書き込む!

★備考★アルゴリズムを読んで頂いて分かる様に1バイト
画素単位の画像データの様に画素値の取る範囲「0..255」
と狭い範囲で大量のデータが有るので同じ値が長く続く
データを意識して設計したアルゴリズムですと極めて限定
された使用状況が必要な処理と判るでしょう!

(4-15-120)関数「void sort_byte_0(BYTE* pl,BYTE* pr){・・・}」

/************************************************************************/
/*****      QUIC-SORT:昇順ソート:データ=8bits          *****/
/************************************************************************/

void            CopyClear::sort_byte_0(
    BYTE        *pl,                                // データの左側Ptr
    BYTE        *pr                                 // データの右側Ptr
){
    BYTE        *pi;                                // 内部Ptr:  左
    BYTE        *pj;                                // 内部Ptr:  右
    BYTE        key;                                // 中央の値
    BYTE        w;                                  // 交換用の場所

    pi  = pl;                                       // KeyDataの左側Set
    pj  = pr;                                       // KeyDataの右側Set
    key = *( pi + ( (int)pj - (int)pi )             // 右左の中央値を
                        / ( 2 * sizeof(BYTE) ) );   // セット
    do{                                             // 以下繰り返し
        while( *pi < key ){                         // 左側が小さい間
            pi++;                                   // 左側を中に進める
        }                                           //
        while( key < *pj ){                         // 右側が大きい間
            pj--;                                   // 右側を中に進める
        }                                           //
        if( pi <= pj ){                             // 左 ≦ 右 なら
            w   = *pi;                              // 左右のキーデータ
            *pi = *pj;                              // を交換
            *pj = w;                                // し
            pi++;                                   // 左側を中に進める
            pj--;                                   // 右側を中に進める
        }                                           //
    }while( pi <= pj );                             // 左≦右なら繰返し
    if( pl < pj ){                                  // 外左 < 中右 なら
        sort_byte_0( pl, pj );                      // この間をソート
    }                                               //
    if( pi < pr ){                                  // 中左 < 外右 なら
        sort_byte_0( pi, pr );                      // この間をソート
    }                                               //
}

☆備考☆この関数はファイル「CopyClear100.cpp」に存在!
★注意★この関数は「private:属性」ですのでライブラリの
外から使用不能です!

(A)関数「sort_byte_0();」の【関数名】

「Sort」は、勿論、英単語「sort」、カタカナ語ソート・
ソーティング、詰り並び替えです!
「byte」は、1バイト符号無し「BYTE型」データを意味し
ます!
「0」は、昇順にソートする事を意味します!
この関数は、データ配列を昇順≪小さい方から大きい方へ
整列≫にソートする関数
★備考★「_」で区切って居るのは、極初期に作成された
ので区切りに「_」を使用するか、単語先頭「英大文字」と
色々迷って居た時期です!

(B)関数「void sort_byte_0();」の【返値】

返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!

(C)関数「sort_byte_0()」の【仮引数】

void            CopyClear::sort_byte_0(
    BYTE        *pl,                                // データの左側Ptr
    BYTE        *pr                                 // データの右側Ptr
){

「BYTE* pl,」は、データ配列左端「l=left省略」
「BYTE* pr」は、データ配列右端「r=right省略」

(D)関数「sort_byte_0()」の【アルゴリズム】

){
    BYTE        *pi;                                // 内部Ptr:  左
    BYTE        *pj;                                // 内部Ptr:  右
    BYTE        key;                                // 中央の値
    BYTE        w;                                  // 交換用の場所

    pi  = pl;                                       // KeyDataの左側Set
    pj  = pr;                                       // KeyDataの右側Set
    key = *( pi + ( (int)pj - (int)pi )             // 右左の中央値を
                        / ( 2 * sizeof(BYTE) ) );   // セット
    do{                                             // 以下繰り返し
        while( *pi < key ){                         // 左側が小さい間
            pi++;                                   // 左側を中に進める
        }                                           //
        while( key < *pj ){                         // 右側が大きい間
            pj--;                                   // 右側を中に進める
        }                                           //
        if( pi <= pj ){                             // 左 ≦ 右 なら
            w   = *pi;                              // 左右のキーデータ
            *pi = *pj;                              // を交換
            *pj = w;                                // し
            pi++;                                   // 左側を中に進める
            pj--;                                   // 右側を中に進める
        }                                           //
    }while( pi <= pj );                             // 左≦右なら繰返し
    if( pl < pj ){                                  // 外左 < 中右 なら
        sort_byte_0( pl, pj );                      // この間をソート
    }                                               //
    if( pi < pr ){                                  // 中左 < 外右 なら
        sort_byte_0( pi, pr );                      // この間をソート
    }                                               //
}

(D-1)ローカル変数

){
    BYTE        *pi;                                // 内部Ptr:  左
    BYTE        *pj;                                // 内部Ptr:  右
    BYTE        key;                                // 中央の値
    BYTE        w;                                  // 交換用の場所

「BYTE* pi;」は、内部ポインタ(左側用)
「BYTE* pj;」は、内部ポインタ(右側用)
「BYTE key;」は、中央の値(キー比較用)
「BYTE w;」は、データ交換用の場所

(D―2)アルゴリズムコード

    pi  = pl;                                       // KeyDataの左側Set
    pj  = pr;                                       // KeyDataの右側Set
    key = *( pi + ( (int)pj - (int)pi )             // 右左の中央値を
                        / ( 2 * sizeof(BYTE) ) );   // セット
    do{                                             // 以下繰り返し
        while( *pi < key ){                         // 左側が小さい間
            pi++;                                   // 左側を中に進める
        }                                           //
        while( key < *pj ){                         // 右側が大きい間
            pj--;                                   // 右側を中に進める
        }                                           //
        if( pi <= pj ){                             // 左 ≦ 右 なら
            w   = *pi;                              // 左右のキーデータ
            *pi = *pj;                              // を交換
            *pj = w;                                // し
            pi++;                                   // 左側を中に進める
            pj--;                                   // 右側を中に進める
        }                                           //
    }while( pi <= pj );                             // 左≦右なら繰返し
    if( pl < pj ){                                  // 外左 < 中右 なら
        sort_byte_0( pl, pj );                      // この間をソート
    }                                               //
    if( pi < pr ){                                  // 中左 < 外右 なら
        sort_byte_0( pi, pr );                      // この間をソート
    }                                               //
}

「pi=pl;pj=pr;」は、ローカルな左側・右側をセット
「key=*(pi+((int)pj-(int)pi)/(2*sizeof(BYTE)))」は、
左右の中央の場所(ポインタの中央)の値を取り出す!
二重ループで外側の
do構文「・・外側ループ本体・・}while(pi<=pj);」と
後置ループ条件「pi<=pj」と内部のポインタの左右関係が
保たれている間繰り返す!そして最初の内側のループ
「while(*pi<key){pi++;}」は、while構文で
ループ条件「*pi<key」は、「左側の値が、
比較用の値未満」の間「pi++;」ポインタを右側に移動を
繰り返すと、即ち、「左側がキーの値以上に成るまで繰り
返す」、次の内側ループ
「while(key<*pj){pj--;}」は、「右」側の
値が、比較用の値越え」の間「pj--;」ポインタを左側に
移動を繰り返すと、即ち、「右側がキーの値以下に成るまで
繰り返す」、そしてif構文
「if(pi<=pj){w=*pi;*pi=*pj;*pj=w;pi++;
pj--;}」は、条件「pi<=pj」と左右関係が保たれていたら
「w=*pi;*pi=*pj;*pj=w;pi++;pj--;}」で先ず
「w=*pi;*pi=*pj;*pj=w;」で左右を入れ替え、
「pi++;pj--;」とローカル左右ポインタを進める!
そして「if(pl<pj){sort_byte_0(pl,pj);}」で再帰呼び出し
を自分自身「sort_byte_0()」関数をサブルーチン関数とし
て条件「pl<pj」=「元々の左側が内部の右側と左右関係が
保たれて居る」なら、再帰呼び出し
「sort_byte_0(pl,pj);」を行う事で数学の
「帰納的定義法」と考えて再帰呼び出しを行った部分
「plからpjのポインタの示す左右範囲」が昇順にソート済
みと見なして処理する方法です!★備考★これが再帰呼び出
しを行う事で実現する「クイックソート」と呼ばれる通常の
データでは最速と言われているアルゴリズムです同じ様に
「if(pi<pr){sort_byte_0(pi,pr);}」で範囲「piからpr」の
ポインタの示す左右範囲」が昇順にソート済みと見なして
処理します!★備考★これが、再帰呼び出しを行う事で
実現する「クイックソート」と呼ばれる通常のデータでは
最速と言われているアルゴリズムですコレは、多くの画像
処理以外のプログラミングで使用されて居ますので数学的
帰納法をアルゴリズムに応用した事を理解して下さい!
C言語的には「再帰呼び出し」との文言で平気で多用しま
す!

(4-15-121)関数「void sort_byte_1(BYTE* pl,BYTE* pr){・・・}」

/************************************************************************/
/*****      QUIC-SORT:降順ソート:データ=8bits          *****/
/************************************************************************/

void        CopyClear::sort_byte_1(
    BYTE    *pl,                                    // データの左側Ptr
    BYTE    *pr                                     // データの右側Ptr
){
    BYTE    *pi;                                    // 内部Ptr:  左
    BYTE    *pj;                                    // 内部Ptr:  右
    BYTE    key;                                    // 中央の値
    BYTE    w;                                      // 交換用の場所

    pi  = pl;                                       // KeyDataの左側Set
    pj  = pr;                                       // KeyDataの右側Set
    key = *( pi + ( (int)pj - (int)pi )             // 右左の中央値を
                        / ( 2 * sizeof(BYTE) ) );   // セット
    do{                                             // 以下繰り返し
        while( *pi > key ){                         // 左側が大きい間
            pi++;                                   // 左側を中に進める
        }                                           //
        while( key > *pj ){                         // 右側が小さい間
            pj--;                                   // 右側を中に進める
        }                                           //
        if( pi <= pj ){                             // 左 ≦ 右 なら
            w   = *pi;                              // 左右のキーデータ
            *pi = *pj;                              // を交換
            *pj = w;                                // し
            pi++;                                   // 左側を中に進める
            pj--;                                   // 右側を中に進める
        }                                           //
    }while( pi <= pj );                             // 左≦右なら繰返し
    if( pl < pj ){                                  // 外左 < 中右 なら
        sort_byte_1( pl, pj );                      // この間をソート
    }                                               //
    if( pi < pr ){                                  // 中左 < 外右 なら
        sort_byte_1( pi, pr );                      // この間をソート
    }                                               //
}

☆備考☆この関数はファイル「CopyClear100.cpp」に存在!
★注意★この関数は「private:属性」ですのでライブラリの
外から使用不能です!

(A)関数「sort_byte_1();」の【関数名】

「Sort」は、勿論、英単語「sort」、カタカナ語ソート・
ソーティング、詰り並び替えです!
「byte」は、1バイト符号無し「BYTE型」データを意味し
ます!
「1」は、降順にソートする事を意味します!
この関数は、データ配列を降順≪大きい方からへ小さい方に
整列≫にソートする関数
★備考★「_」で区切って居るのは、極初期に作成された
ので区切りに「_」を使用するか、単語先頭「英大文字」と
色々迷って居た時期です!

(B)関数「void sort_byte_1();」の【返値】

返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!

(C)関数「sort_byte_1()」の【仮引数】

void        CopyClear::sort_byte_1(
    BYTE    *pl,                                    // データの左側Ptr
    BYTE    *pr                                     // データの右側Ptr
){

「BYTE* pl,」は、データ配列左端「l=left省略」
「BYTE* pr」は、データ配列右端「r=right省略」

(D)関数「sort_byte_1()」の【アルゴリズム】

){
    BYTE    *pi;                                    // 内部Ptr:  左
    BYTE    *pj;                                    // 内部Ptr:  右
    BYTE    key;                                    // 中央の値
    BYTE    w;                                      // 交換用の場所

    pi  = pl;                                       // KeyDataの左側Set
    pj  = pr;                                       // KeyDataの右側Set
    key = *( pi + ( (int)pj - (int)pi )             // 右左の中央値を
                        / ( 2 * sizeof(BYTE) ) );   // セット
    do{                                             // 以下繰り返し
        while( *pi > key ){                         // 左側が大きい間
            pi++;                                   // 左側を中に進める
        }                                           //
        while( key > *pj ){                         // 右側が小さい間
            pj--;                                   // 右側を中に進める
        }                                           //
        if( pi <= pj ){                             // 左 ≦ 右 なら
            w   = *pi;                              // 左右のキーデータ
            *pi = *pj;                              // を交換
            *pj = w;                                // し
            pi++;                                   // 左側を中に進める
            pj--;                                   // 右側を中に進める
        }                                           //
    }while( pi <= pj );                             // 左≦右なら繰返し
    if( pl < pj ){                                  // 外左 < 中右 なら
        sort_byte_1( pl, pj );                      // この間をソート
    }                                               //
    if( pi < pr ){                                  // 中左 < 外右 なら
        sort_byte_1( pi, pr );                      // この間をソート
    }                                               //
}

(D)ローカル変数

){
    BYTE    *pi;                                    // 内部Ptr:  左
    BYTE    *pj;                                    // 内部Ptr:  右
    BYTE    key;                                    // 中央の値
    BYTE    w;                                      // 交換用の場所

「BYTE* pi;」は、内部ポインタ(左側用)
「BYTE* pj;」は、内部ポインタ(右側用)
「BYTE key;」は、中央の値(キー比較用)
「BYTE w;」は、データ交換用の場所

(D)アルゴリズムコード

    pi  = pl;                                       // KeyDataの左側Set
    pj  = pr;                                       // KeyDataの右側Set
    key = *( pi + ( (int)pj - (int)pi )             // 右左の中央値を
                        / ( 2 * sizeof(BYTE) ) );   // セット
    do{                                             // 以下繰り返し
        while( *pi > key ){                         // 左側が大きい間
            pi++;                                   // 左側を中に進める
        }                                           //
        while( key > *pj ){                         // 右側が小さい間
            pj--;                                   // 右側を中に進める
        }                                           //
        if( pi <= pj ){                             // 左 ≦ 右 なら
            w   = *pi;                              // 左右のキーデータ
            *pi = *pj;                              // を交換
            *pj = w;                                // し
            pi++;                                   // 左側を中に進める
            pj--;                                   // 右側を中に進める
        }                                           //
    }while( pi <= pj );                             // 左≦右なら繰返し
    if( pl < pj ){                                  // 外左 < 中右 なら
        sort_byte_1( pl, pj );                      // この間をソート
    }                                               //
    if( pi < pr ){                                  // 中左 < 外右 なら
        sort_byte_1( pi, pr );                      // この間をソート
    }                                               //
}

「pi=pl;pj=pr;」は、ローカルな左側・右側をセット
「key=*(pi+((int)pj-(int)pi)/(2*sizeof(BYTE)))」は、
左右の中央の場所(ポインタの中央)の値を取り出す!
二重ループで外側の
do構文「・・外側ループ本体・・}while(pi<=pj);」と
後置ループ条件「pi<=pj」と内部のポインタの左右関係が
保たれている間繰り返す!そして最初の内側のループ
「while(*pi>key){pi++;}」は、while構文で
ループ条件「*pi>key」は、「左側の値が、
比較用の値越え」の間「pi++;」ポインタを右側に移動を
繰り返すと、即ち、「左側がキーの値以下に成るまで繰り
返す」、次の内側ループ
「while(key>*pj){pj--;}」は、「右」側の
値が、比較用の値未満」の間「pj--;」ポインタを左側に
移動を繰り返すと、即ち、「右側がキーの値以上に成るまで
繰り返す」、そしてif構文
「if(pi<=pj){w=*pi;*pi=*pj;*pj=w;pi++;
pj--;}」は、条件「pi<=pj」と左右関係が保たれていたら
「w=*pi;*pi=*pj;*pj=w;pi++;pj--;}」で先ず
「w=*pi;*pi=*pj;*pj=w;」で左右を入れ替え、
「pi++;pj--;」とローカル左右ポインタを進める!
そして「if(pl<pj){sort_byte_1(pl,pj);}」で再帰呼び出し
を自分自身「sort_byte_1()」関数をサブルーチン関数とし
て条件「pl<pj」=「元々の左側が内部の右側と左右関係が
保たれて居る」なら、再帰呼び出し
「sort_byte_1(pl,pj);」を行う事で数学の
「帰納的定義法」と考えて再帰呼び出しを行った部分
「plからpjのポインタの示す左右範囲」が昇順にソート済
みと見なして処理する方法です!★備考★これが再帰呼び出
しを行う事で実現する「クイックソート」と呼ばれる通常の
データでは最速と言われているアルゴリズムです同じ様に
「if(pi<pr){sort_byte_1(pi,pr);}」で範囲「piからpr」の
ポインタの示す左右範囲」が昇順にソート済みと見なして
処理します!★備考★これが、再帰呼び出しを行う事で
実現する「クイックソート」と呼ばれる通常のデータでは
最速と言われているアルゴリズムですコレは、多くの画像
処理以外のプログラミングで使用されて居ますので数学的
帰納法をアルゴリズムに応用した事を理解して下さい!
C言語的には「再帰呼び出し」との文言で平気で多用しま
す!

(4-15-122)関数「void sort_short_0(short* pl,short* pr){・・・}」

/************************************************************************/
/*****      QUIC-SORT:昇順ソート:データ=16bits        *****/
/************************************************************************/

void            CopyClear::sort_short_0(
    short       *pl,                                // データの左側Ptr
    short       *pr                                 // データの右側Ptr
){
    short       *pi;                                // 内部Ptr:  左
    short       *pj;                                // 内部Ptr:  右
    short       key;                                // 中央の値
    short       w;                                  // 交換用の場所

    pi  = pl;                                       // KeyDataの左側Set
    pj  = pr;                                       // KeyDataの右側Set
    key = *( pi + ( (int)pj - (int)pi )             // 右左の中央値を
                        / ( 2 * sizeof(short) ) );  // セット
    do{                                             // 以下繰り返し
        while( *pi < key ){                         // 左側が小さい間
            pi++;                                   // 左側を中に進める
        }                                           //
        while( key < *pj ){                         // 右側が大きい間
            pj--;                                   // 右側を中に進める
        }                                           //
        if( pi <= pj ){                             // 左 ≦ 右 なら
            w   = *pi;                              // 左右のキーデータ
            *pi = *pj;                              // を交換
            *pj = w;                                // し
            pi++;                                   // 左側を中に進める
            pj--;                                   // 右側を中に進める
        }                                           //
    }while( pi <= pj );                             // 左≦右なら繰返し
    if( pl < pj ){                                  // 外左 < 中右 なら
        sort_short_0( pl, pj );                     // この間をソート
    }                                               //
    if( pi < pr ){                                  // 中左 < 外右 なら
        sort_short_0( pi, pr );                     // この間をソート
    }                                               //
}

☆備考☆この関数はファイル「CopyClear100.cpp」に存在!
★注意★この関数は「private:属性」ですのでライブラリの
外から使用不能です!

(A)関数「sort_short_0();」の【関数名】

「Sort」は、勿論、英単語「sort」、カタカナ語ソート・
ソーティング、詰り並び替えです!
「short」は、2バイト符号有り「short型」データを意味し
ます!
「0」は、昇順にソートする事を意味します!
この関数は、データ配列を昇順≪小さい方から大きい方へ
整列≫にソートする関数
★備考★「_」で区切って居るのは、極初期に作成された
ので区切りに「_」を使用するか、単語先頭「英大文字」と
色々迷って居た時期です!

(B)関数「void sort_short_0();」の【返値】

返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!

(C)関数「sort_short_0()」の【仮引数】

void            CopyClear::sort_short_0(
    short       *pl,                                // データの左側Ptr
    short       *pr                                 // データの右側Ptr
){

「short* pl,」は、データ配列左端「l=left省略」
「short* pr」は、データ配列右端「r=right省略」

(D)関数「sort_short_0()」の【アルゴリズム】

){
    short       *pi;                                // 内部Ptr:  左
    short       *pj;                                // 内部Ptr:  右
    short       key;                                // 中央の値
    short       w;                                  // 交換用の場所

    pi  = pl;                                       // KeyDataの左側Set
    pj  = pr;                                       // KeyDataの右側Set
    key = *( pi + ( (int)pj - (int)pi )             // 右左の中央値を
                        / ( 2 * sizeof(short) ) );  // セット
    do{                                             // 以下繰り返し
        while( *pi < key ){                         // 左側が小さい間
            pi++;                                   // 左側を中に進める
        }                                           //
        while( key < *pj ){                         // 右側が大きい間
            pj--;                                   // 右側を中に進める
        }                                           //
        if( pi <= pj ){                             // 左 ≦ 右 なら
            w   = *pi;                              // 左右のキーデータ
            *pi = *pj;                              // を交換
            *pj = w;                                // し
            pi++;                                   // 左側を中に進める
            pj--;                                   // 右側を中に進める
        }                                           //
    }while( pi <= pj );                             // 左≦右なら繰返し
    if( pl < pj ){                                  // 外左 < 中右 なら
        sort_short_0( pl, pj );                     // この間をソート
    }                                               //
    if( pi < pr ){                                  // 中左 < 外右 なら
        sort_short_0( pi, pr );                     // この間をソート
    }                                               //
}

(D-1)ローカル変数

){
    short       *pi;                                // 内部Ptr:  左
    short       *pj;                                // 内部Ptr:  右
    short       key;                                // 中央の値
    short       w;                                  // 交換用の場所

「short* pi;」は、内部ポインタ(左側用)
「short* pj;」は、内部ポインタ(右側用)
「short key;」は、中央の値(キー比較用)
「short w;」は、データ交換用の場所

(D―2)アルゴリズムコード

    pi  = pl;                                       // KeyDataの左側Set
    pj  = pr;                                       // KeyDataの右側Set
    key = *( pi + ( (int)pj - (int)pi )             // 右左の中央値を
                        / ( 2 * sizeof(short) ) );  // セット
    do{                                             // 以下繰り返し
        while( *pi < key ){                         // 左側が小さい間
            pi++;                                   // 左側を中に進める
        }                                           //
        while( key < *pj ){                         // 右側が大きい間
            pj--;                                   // 右側を中に進める
        }                                           //
        if( pi <= pj ){                             // 左 ≦ 右 なら
            w   = *pi;                              // 左右のキーデータ
            *pi = *pj;                              // を交換
            *pj = w;                                // し
            pi++;                                   // 左側を中に進める
            pj--;                                   // 右側を中に進める
        }                                           //
    }while( pi <= pj );                             // 左≦右なら繰返し
    if( pl < pj ){                                  // 外左 < 中右 なら
        sort_short_0( pl, pj );                     // この間をソート
    }                                               //
    if( pi < pr ){                                  // 中左 < 外右 なら
        sort_short_0( pi, pr );                     // この間をソート
    }                                               //
}

「pi=pl;pj=pr;」は、ローカルな左側・右側をセット
「key=*(pi+((int)pj-(int)pi)/(2*sizeof(short)))」は、
左右の中央の場所(ポインタの中央)の値を取り出す!
二重ループで外側の
do構文「・・外側ループ本体・・}while(pi<=pj);」と
後置ループ条件「pi<=pj」と内部のポインタの左右関係が
保たれている間繰り返す!そして最初の内側のループ
「while(*pi<key){pi++;}」は、while構文で
ループ条件「*pi<key」は、「左側の値が、
比較用の値未満」の間「pi++;」ポインタを右側に移動を
繰り返すと、即ち、「左側がキーの値以上に成るまで繰り
返す」、次の内側ループ
「while(key<*pj){pj--;}」は、「右」側の
値が、比較用の値越え」の間「pj--;」ポインタを左側に
移動を繰り返すと、即ち、「右側がキーの値以下に成るまで
繰り返す」、そしてif構文
「if(pi<=pj){w=*pi;*pi=*pj;*pj=w;pi++;
pj--;}」は、条件「pi<=pj」と左右関係が保たれていたら
「w=*pi;*pi=*pj;*pj=w;pi++;pj--;}」で先ず
「w=*pi;*pi=*pj;*pj=w;」で左右を入れ替え、
「pi++;pj--;」とローカル左右ポインタを進める!
そして「if(pl<pj){sort_short_0(pl,pj);}」で再帰呼び出し
を自分自身「sort_short_0()」関数をサブルーチン関数とし
て条件「pl<pj」=「元々の左側が内部の右側と左右関係が
保たれて居る」なら、再帰呼び出し
「sort_short_0(pl,pj);」を行う事で数学の
「帰納的定義法」と考えて再帰呼び出しを行った部分
「plからpjのポインタの示す左右範囲」が昇順にソート済
みと見なして処理する方法です!★備考★これが再帰呼び出
しを行う事で実現する「クイックソート」と呼ばれる通常の
データでは最速と言われているアルゴリズムです同じ様に
「if(pi<pr){sort_short_0(pi,pr);}」で範囲「piからpr」の
ポインタの示す左右範囲」が昇順にソート済みと見なして
処理します!★備考★これが、再帰呼び出しを行う事で
実現する「クイックソート」と呼ばれる通常のデータでは
最速と言われているアルゴリズムですコレは、多くの画像
処理以外のプログラミングで使用されて居ますので数学的
帰納法をアルゴリズムに応用した事を理解して下さい!
C言語的には「再帰呼び出し」との文言で平気で多用しま
す!

(4-15-123)関数「void sort_short_1(short* pl,short* pr){・・・}」

/************************************************************************/
/*****      QUIC-SORT:降順ソート:データ=16bits        *****/
/************************************************************************/

void            CopyClear::sort_short_1(
    short       *pl,                                // データの左側Ptr
    short       *pr                                 // データの右側Ptr
){
    short       *pi;                                // 内部Ptr:  左
    short       *pj;                                // 内部Ptr:  右
    short       key;                                // 中央の値
    short       w;                                  // 交換用の場所

    pi  = pl;                                       // KeyDataの左側Set
    pj  = pr;                                       // KeyDataの右側Set
    key = *( pi + ( (int)pj - (int)pi )             // 右左の中央値を
                        / ( 2 * sizeof(short) ) );  // セット
    do{                                             // 以下繰り返し
        while( *pi > key ){                         // 左側が大きい間
            pi++;                                   // 左側を中に進める
        }                                           //
        while( key > *pj ){                         // 右側が小さい間
            pj--;                                   // 右側を中に進める
        }                                           //
        if( pi <= pj ){                             // 左 ≦ 右 なら
            w   = *pi;                              // 左右のキーデータ
            *pi = *pj;                              // を交換
            *pj = w;                                // し
            pi++;                                   // 左側を中に進める
            pj--;                                   // 右側を中に進める
        }                                           //
    }while( pi <= pj );                             // 左≦右なら繰返し
    if( pl < pj ){                                  // 外左 < 中右 なら
        sort_short_1( pl, pj );                     // この間をソート
    }                                               //
    if( pi < pr ){                                  // 中左 < 外右 なら
        sort_short_1( pi, pr );                     // この間をソート
    }                                               //
}

☆備考☆この関数はファイル「CopyClear100.cpp」に存在!
★注意★この関数は「private:属性」ですのでライブラリの
外から使用不能です!

(A)関数「sort_short_1();」の【関数名】

「Sort」は、勿論、英単語「sort」、カタカナ語ソート・
ソーティング、詰り並び替えです!
「short」は、1バイト符号無し「short型」データを意味し
ます!
「1」は、降順にソートする事を意味します!
この関数は、データ配列を降順≪大きい方からへ小さい方に
整列≫にソートする関数
★備考★「_」で区切って居るのは、極初期に作成された
ので区切りに「_」を使用するか、単語先頭「英大文字」と
色々迷って居た時期です!

(B)関数「void sort_short_1();」の【返値】

返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!

(C)関数「sort_short_1()」の【仮引数】

void            CopyClear::sort_short_1(
    short       *pl,                                // データの左側Ptr
    short       *pr                                 // データの右側Ptr
){

「short* pl,」は、データ配列左端「l=left省略」
「short* pr」は、データ配列右端「r=right省略」

(D)関数「sort_short_1()」の【アルゴリズム】

){
    short       *pi;                                // 内部Ptr:  左
    short       *pj;                                // 内部Ptr:  右
    short       key;                                // 中央の値
    short       w;                                  // 交換用の場所

    pi  = pl;                                       // KeyDataの左側Set
    pj  = pr;                                       // KeyDataの右側Set
    key = *( pi + ( (int)pj - (int)pi )             // 右左の中央値を
                        / ( 2 * sizeof(short) ) );  // セット
    do{                                             // 以下繰り返し
        while( *pi > key ){                         // 左側が大きい間
            pi++;                                   // 左側を中に進める
        }                                           //
        while( key > *pj ){                         // 右側が小さい間
            pj--;                                   // 右側を中に進める
        }                                           //
        if( pi <= pj ){                             // 左 ≦ 右 なら
            w   = *pi;                              // 左右のキーデータ
            *pi = *pj;                              // を交換
            *pj = w;                                // し
            pi++;                                   // 左側を中に進める
            pj--;                                   // 右側を中に進める
        }                                           //
    }while( pi <= pj );                             // 左≦右なら繰返し
    if( pl < pj ){                                  // 外左 < 中右 なら
        sort_short_1( pl, pj );                     // この間をソート
    }                                               //
    if( pi < pr ){                                  // 中左 < 外右 なら
        sort_short_1( pi, pr );                     // この間をソート
    }                                               //
}

(D-1)ローカル変数

){
    short       *pi;                                // 内部Ptr:  左
    short       *pj;                                // 内部Ptr:  右
    short       key;                                // 中央の値
    short       w;                                  // 交換用の場所

「short* pi;」は、内部ポインタ(左側用)
「short* pj;」は、内部ポインタ(右側用)
「short key;」は、中央の値(キー比較用)
「short w;」は、データ交換用の場所

(D―2)アルゴリズムコード

    pi  = pl;                                       // KeyDataの左側Set
    pj  = pr;                                       // KeyDataの右側Set
    key = *( pi + ( (int)pj - (int)pi )             // 右左の中央値を
                        / ( 2 * sizeof(short) ) );  // セット
    do{                                             // 以下繰り返し
        while( *pi > key ){                         // 左側が大きい間
            pi++;                                   // 左側を中に進める
        }                                           //
        while( key > *pj ){                         // 右側が小さい間
            pj--;                                   // 右側を中に進める
        }                                           //
        if( pi <= pj ){                             // 左 ≦ 右 なら
            w   = *pi;                              // 左右のキーデータ
            *pi = *pj;                              // を交換
            *pj = w;                                // し
            pi++;                                   // 左側を中に進める
            pj--;                                   // 右側を中に進める
        }                                           //
    }while( pi <= pj );                             // 左≦右なら繰返し
    if( pl < pj ){                                  // 外左 < 中右 なら
        sort_short_1( pl, pj );                     // この間をソート
    }                                               //
    if( pi < pr ){                                  // 中左 < 外右 なら
        sort_short_1( pi, pr );                     // この間をソート
    }                                               //
}

「pi=pl;pj=pr;」は、ローカルな左側・右側をセット
「key=*(pi+((int)pj-(int)pi)/(2*sizeof(short)))」は、
左右の中央の場所(ポインタの中央)の値を取り出す!
二重ループで外側の
do構文「・・外側ループ本体・・}while(pi<=pj);」と
後置ループ条件「pi<=pj」と内部のポインタの左右関係が
保たれている間繰り返す!そして最初の内側のループ
「while(*pi>key){pi++;}」は、while構文で
ループ条件「*pi>key」は、「左側の値が、
比較用の値越え」の間「pi++;」ポインタを右側に移動を
繰り返すと、即ち、「左側がキーの値以下に成るまで繰り
返す」、次の内側ループ
「while(key>*pj){pj--;}」は、「右」側の
値が、比較用の値未満」の間「pj--;」ポインタを左側に
移動を繰り返すと、即ち、「右側がキーの値以上に成るまで
繰り返す」、そしてif構文
「if(pi<=pj){w=*pi;*pi=*pj;*pj=w;pi++;
pj--;}」は、条件「pi<=pj」と左右関係が保たれていたら
「w=*pi;*pi=*pj;*pj=w;pi++;pj--;}」で先ず
「w=*pi;*pi=*pj;*pj=w;」で左右を入れ替え、
「pi++;pj--;」とローカル左右ポインタを進める!
そして「if(pl<pj){sort_short_1(pl,pj);}」で再帰呼び出し
を自分自身「sort_short_1()」関数をサブルーチン関数とし
て条件「pl<pj」=「元々の左側が内部の右側と左右関係が
保たれて居る」なら、再帰呼び出し
「sort_short_1(pl,pj);」を行う事で数学の
「帰納的定義法」と考えて再帰呼び出しを行った部分
「plからpjのポインタの示す左右範囲」が昇順にソート済
みと見なして処理する方法です!★備考★これが再帰呼び出
しを行う事で実現する「クイックソート」と呼ばれる通常の
データでは最速と言われているアルゴリズムです同じ様に
「if(pi<pr){sort_short_1(pi,pr);}」で範囲「piからpr」の
ポインタの示す左右範囲」が昇順にソート済みと見なして
処理します!★備考★これが、再帰呼び出しを行う事で
実現する「クイックソート」と呼ばれる通常のデータでは
最速と言われているアルゴリズムですコレは、多くの画像
処理以外のプログラミングで使用されて居ますので数学的
帰納法をアルゴリズムに応用した事を理解して下さい!
C言語的には「再帰呼び出し」との文言で平気で多用しま
す!

(4-15-124)関数「void sort_long_0(long* pl,long* pr){・・・}」

/************************************************************************/
/*****      QUIC-SORT:昇順ソート:データ=32bits        *****/
/************************************************************************/

void            CopyClear::sort_long_0(
    long        *pl,                                // データの左側Ptr
    long        *pr                                 // データの右側Ptr
){
    long        *pi;                                // 内部Ptr:  左
    long        *pj;                                // 内部Ptr:  右
    int         key;                                // 中央の値
    int         w;                                  // 交換用の場所

    pi  = pl;                                       // KeyDataの左側Set
    pj  = pr;                                       // KeyDataの右側Set
    key = *( pi + ( (int)pj - (int)pi )             // 右左の中央値を
                        / ( 2 * sizeof(long) ) );   // セット
    do{                                             // 以下繰り返し
        while( *pi < key ){                         // 左側が小さい間
            pi++;                                   // 左側を中に進める
        }                                           //
        while( key < *pj ){                         // 右側が大きい間
            pj--;                                   // 右側を中に進める
        }                                           //
        if( pi <= pj ){                             // 左 ≦ 右 なら
            w   = *pi;                              // 左右のキーデータ
            *pi = *pj;                              // を交換
            *pj = w;                                // し
            pi++;                                   // 左側を中に進める
            pj--;                                   // 右側を中に進める
        }                                           //
    }while( pi <= pj );                             // 左≦右なら繰返し
    if( pl < pj ){                                  // 外左 < 中右 なら
        sort_long_0( pl, pj );                      // この間をソート
    }                                               //
    if( pi < pr ){                                  // 中左 < 外右 なら
        sort_long_0( pi, pr );                      // この間をソート
    }                                               //
}

☆備考☆この関数はファイル「CopyClear100.cpp」に存在!
★注意★この関数は「private:属性」ですのでライブラリの
外から使用不能です!

(A)関数「sort_long_0();」の【関数名】

「Sort」は、勿論、英単語「sort」、カタカナ語ソート・
ソーティング、詰り並び替えです!
「long」は、4バイト符号有り「long型」データを意味し
ます!
「0」は、昇順にソートする事を意味します!
この関数は、データ配列を昇順≪小さい方から大きい方へ
整列≫にソートする関数
★備考★「_」で区切って居るのは、極初期に作成された
ので区切りに「_」を使用するか、単語先頭「英大文字」と
色々迷って居た時期です!

(B)関数「void sort_long_0();」の【返値】

返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!

(C)関数「sort_long_0()」の【仮引数】

void            CopyClear::sort_long_0(
    long        *pl,                                // データの左側Ptr
    long        *pr                                 // データの右側Ptr
){

「long* pl,」は、データ配列左端「l=left省略」
「long* pr」は、データ配列右端「r=right省略」

(D)関数「sort_long_0()」の【アルゴリズム】

){
    long        *pi;                                // 内部Ptr:  左
    long        *pj;                                // 内部Ptr:  右
    int         key;                                // 中央の値
    int         w;                                  // 交換用の場所

    pi  = pl;                                       // KeyDataの左側Set
    pj  = pr;                                       // KeyDataの右側Set
    key = *( pi + ( (int)pj - (int)pi )             // 右左の中央値を
                        / ( 2 * sizeof(long) ) );   // セット
    do{                                             // 以下繰り返し
        while( *pi < key ){                         // 左側が小さい間
            pi++;                                   // 左側を中に進める
        }                                           //
        while( key < *pj ){                         // 右側が大きい間
            pj--;                                   // 右側を中に進める
        }                                           //
        if( pi <= pj ){                             // 左 ≦ 右 なら
            w   = *pi;                              // 左右のキーデータ
            *pi = *pj;                              // を交換
            *pj = w;                                // し
            pi++;                                   // 左側を中に進める
            pj--;                                   // 右側を中に進める
        }                                           //
    }while( pi <= pj );                             // 左≦右なら繰返し
    if( pl < pj ){                                  // 外左 < 中右 なら
        sort_long_0( pl, pj );                      // この間をソート
    }                                               //
    if( pi < pr ){                                  // 中左 < 外右 なら
        sort_long_0( pi, pr );                      // この間をソート
    }                                               //
}

(D-1)ローカル変数

){
    long        *pi;                                // 内部Ptr:  左
    long        *pj;                                // 内部Ptr:  右
    int         key;                                // 中央の値
    int         w;                                  // 交換用の場所

「long* pi;」は、内部ポインタ(左側用)
「long* pj;」は、内部ポインタ(右側用)
「int key;」は、中央の値(キー比較用)
「int w;」は、データ交換用の場所

(D―2)アルゴリズムコード

    pi  = pl;                                       // KeyDataの左側Set
    pj  = pr;                                       // KeyDataの右側Set
    key = *( pi + ( (int)pj - (int)pi )             // 右左の中央値を
                        / ( 2 * sizeof(long) ) );   // セット
    do{                                             // 以下繰り返し
        while( *pi < key ){                         // 左側が小さい間
            pi++;                                   // 左側を中に進める
        }                                           //
        while( key < *pj ){                         // 右側が大きい間
            pj--;                                   // 右側を中に進める
        }                                           //
        if( pi <= pj ){                             // 左 ≦ 右 なら
            w   = *pi;                              // 左右のキーデータ
            *pi = *pj;                              // を交換
            *pj = w;                                // し
            pi++;                                   // 左側を中に進める
            pj--;                                   // 右側を中に進める
        }                                           //
    }while( pi <= pj );                             // 左≦右なら繰返し
    if( pl < pj ){                                  // 外左 < 中右 なら
        sort_long_0( pl, pj );                      // この間をソート
    }                                               //
    if( pi < pr ){                                  // 中左 < 外右 なら
        sort_long_0( pi, pr );                      // この間をソート
    }                                               //
}

「pi=pl;pj=pr;」は、ローカルな左側・右側をセット
「key=*(pi+((int)pj-(int)pi)/(2*sizeof(long)))」は、
左右の中央の場所(ポインタの中央)の値を取り出す!
二重ループで外側の
do構文「・・外側ループ本体・・}while(pi<=pj);」と
後置ループ条件「pi<=pj」と内部のポインタの左右関係が
保たれている間繰り返す!そして最初の内側のループ
「while(*pi<key){pi++;}」は、while構文で
ループ条件「*pi<key」は、「左側の値が、
比較用の値未満」の間「pi++;」ポインタを右側に移動を
繰り返すと、即ち、「左側がキーの値以上に成るまで繰り
返す」、次の内側ループ
「while(key<*pj){pj--;}」は、「右」側の
値が、比較用の値越え」の間「pj--;」ポインタを左側に
移動を繰り返すと、即ち、「右側がキーの値以下に成るまで
繰り返す」、そしてif構文
「if(pi<=pj){w=*pi;*pi=*pj;*pj=w;pi++;
pj--;}」は、条件「pi<=pj」と左右関係が保たれていたら
「w=*pi;*pi=*pj;*pj=w;pi++;pj--;}」で先ず
「w=*pi;*pi=*pj;*pj=w;」で左右を入れ替え、
「pi++;pj--;」とローカル左右ポインタを進める!
そして「if(pl<pj){sort_long_0(pl,pj);}」で再帰呼び出し
を自分自身「sort_long_0()」関数をサブルーチン関数とし
て条件「pl<pj」=「元々の左側が内部の右側と左右関係が
保たれて居る」なら、再帰呼び出し
「sort_long_0(pl,pj);」を行う事で数学の
「帰納的定義法」と考えて再帰呼び出しを行った部分
「plからpjのポインタの示す左右範囲」が昇順にソート済
みと見なして処理する方法です!★備考★これが再帰呼び出
しを行う事で実現する「クイックソート」と呼ばれる通常の
データでは最速と言われているアルゴリズムです同じ様に
「if(pi<pr){sort_long_0(pi,pr);}」で範囲「piからpr」の
ポインタの示す左右範囲」が昇順にソート済みと見なして
処理します!★備考★これが、再帰呼び出しを行う事で
実現する「クイックソート」と呼ばれる通常のデータでは
最速と言われているアルゴリズムですコレは、多くの画像
処理以外のプログラミングで使用されて居ますので数学的
帰納法をアルゴリズムに応用した事を理解して下さい!
C言語的には「再帰呼び出し」との文言で平気で多用しま
す!
★★特注「note編集機能不具合」★★
「key=*(pi+((int)pj-(int)pi)/(2*sizeof(long)))」と
コピペでテキストを記載したら、
「key=(pi+((int)pj-(int)pi)/(2sizeof(long)))」等と
主に「*」が消える事が多々ありますので注意して手作業で
修正して居るが、全て修正出来て無い部分が有る事に留意し
て読んで頂きたい!必ず、【<>code】機能で生のテキ
ストを必ず参考にして下さい!!

(4-15-125)関数「void sort_long_1(long* pl,long* pr){・・・}」

/************************************************************************/
/*****      QUIC-SORT:降順ソート:データ=32bits        *****/
/************************************************************************/

void            CopyClear::sort_long_1(
    long        *pl,                                // データの左側Ptr
    long        *pr                                 // データの右側Ptr
){
    long        *pi;                                // 内部Ptr:  左
    long        *pj;                                // 内部Ptr:  右
    int         key;                                // 中央の値
    int         w;                                  // 交換用の場所

    pi  = pl;                                       // KeyDataの左側Set
    pj  = pr;                                       // KeyDataの右側Set
    key = *( pi + ( (int)pj - (int)pi )             // 右左の中央値を
                        / ( 2 * sizeof(long) ) );   // セット
    do{                                             // 以下繰り返し
        while( *pi > key ){                         // 左側が大きい間
            pi++;                                   // 左側を中に進める
        }                                           //
        while( key > *pj ){                         // 右側が小さい間
            pj--;                                   // 右側を中に進める
        }                                           //
        if( pi <= pj ){                             // 左 ≦ 右 なら
            w   = *pi;                              // 左右のキーデータ
            *pi = *pj;                              // を交換
            *pj = w;                                // し
            pi++;                                   // 左側を中に進める
            pj--;                                   // 右側を中に進める
        }                                           //
    }while( pi <= pj );                             // 左≦右なら繰返し
    if( pl < pj ){                                  // 外左 < 中右 なら
        sort_long_1( pl, pj );                      // この間をソート
    }                                               //
    if( pi < pr ){                                  // 中左 < 外右 なら
        sort_long_1( pi, pr );                      // この間をソート
    }                                               //
}

☆備考☆この関数はファイル「CopyClear100.cpp」に存在!
★注意★この関数は「private:属性」ですのでライブラリの
外から使用不能です!

(A)関数「sort_long_1();」の【関数名】

「Sort」は、勿論、英単語「sort」、カタカナ語ソート・
ソーティング、詰り並び替えです!
「long」は、4バイト符号有り「long型」データを意味し
ます!
「1」は、降順にソートする事を意味します!
この関数は、データ配列を降順≪大きい方からへ小さい方に
整列≫にソートする関数
★備考★「_」で区切って居るのは、極初期に作成された
ので区切りに「_」を使用するか、単語先頭「英大文字」と
色々迷って居た時期です!

(B)関数「void sort_long_1();」の【返値】

返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!

(C)関数「sort_long_1()」の【仮引数】

void            CopyClear::sort_long_1(
    long        *pl,                                // データの左側Ptr
    long        *pr                                 // データの右側Ptr
){

「long* pl,」は、データ配列左端「l=left省略」
「long* pr」は、データ配列右端「r=right省略」

(D)関数「sort_long_1()」の【アルゴリズム】

){
    long        *pi;                                // 内部Ptr:  左
    long        *pj;                                // 内部Ptr:  右
    int         key;                                // 中央の値
    int         w;                                  // 交換用の場所

    pi  = pl;                                       // KeyDataの左側Set
    pj  = pr;                                       // KeyDataの右側Set
    key = *( pi + ( (int)pj - (int)pi )             // 右左の中央値を
                        / ( 2 * sizeof(long) ) );   // セット
    do{                                             // 以下繰り返し
        while( *pi > key ){                         // 左側が大きい間
            pi++;                                   // 左側を中に進める
        }                                           //
        while( key > *pj ){                         // 右側が小さい間
            pj--;                                   // 右側を中に進める
        }                                           //
        if( pi <= pj ){                             // 左 ≦ 右 なら
            w   = *pi;                              // 左右のキーデータ
            *pi = *pj;                              // を交換
            *pj = w;                                // し
            pi++;                                   // 左側を中に進める
            pj--;                                   // 右側を中に進める
        }                                           //
    }while( pi <= pj );                             // 左≦右なら繰返し
    if( pl < pj ){                                  // 外左 < 中右 なら
        sort_long_1( pl, pj );                      // この間をソート
    }                                               //
    if( pi < pr ){                                  // 中左 < 外右 なら
        sort_long_1( pi, pr );                      // この間をソート
    }                                               //
}

(D-1)ローカル変数

){
    long        *pi;                                // 内部Ptr:  左
    long        *pj;                                // 内部Ptr:  右
    int         key;                                // 中央の値
    int         w;                                  // 交換用の場所

「long* pi;」は、内部ポインタ(左側用)
「long* pj;」は、内部ポインタ(右側用)
「int key;」は、中央の値(キー比較用)
「int w;」は、データ交換用の場所

(D―2)アルゴリズムコード

    pi  = pl;                                       // KeyDataの左側Set
    pj  = pr;                                       // KeyDataの右側Set
    key = *( pi + ( (int)pj - (int)pi )             // 右左の中央値を
                        / ( 2 * sizeof(long) ) );   // セット
    do{                                             // 以下繰り返し
        while( *pi > key ){                         // 左側が大きい間
            pi++;                                   // 左側を中に進める
        }                                           //
        while( key > *pj ){                         // 右側が小さい間
            pj--;                                   // 右側を中に進める
        }                                           //
        if( pi <= pj ){                             // 左 ≦ 右 なら
            w   = *pi;                              // 左右のキーデータ
            *pi = *pj;                              // を交換
            *pj = w;                                // し
            pi++;                                   // 左側を中に進める
            pj--;                                   // 右側を中に進める
        }                                           //
    }while( pi <= pj );                             // 左≦右なら繰返し
    if( pl < pj ){                                  // 外左 < 中右 なら
        sort_long_1( pl, pj );                      // この間をソート
    }                                               //
    if( pi < pr ){                                  // 中左 < 外右 なら
        sort_long_1( pi, pr );                      // この間をソート
    }                                               //
}

「pi=pl;pj=pr;」は、ローカルな左側・右側をセット
「key=*(pi+((int)pj-(int)pi)/(2*sizeof(long)))」は、
左右の中央の場所(ポインタの中央)の値を取り出す!
二重ループで外側の
do構文「・・外側ループ本体・・}while(pi<=pj);」と
後置ループ条件「pi<=pj」と内部のポインタの左右関係が
保たれている間繰り返す!そして最初の内側のループ
「while(*pi>key){pi++;}」は、while構文で
ループ条件「*pi>key」は、「左側の値が、
比較用の値越え」の間「pi++;」ポインタを右側に移動を
繰り返すと、即ち、「左側がキーの値以下に成るまで繰り
返す」、次の内側ループ
「while(key>*pj){pj--;}」は、「右」側の
値が、比較用の値未満」の間「pj--;」ポインタを左側に
移動を繰り返すと、即ち、「右側がキーの値以上に成るまで
繰り返す」、そしてif構文
「if(pi<=pj){w=*pi;*pi=*pj;*pj=w;pi++;
pj--;}」は、条件「pi<=pj」と左右関係が保たれていたら
「w=*pi;*pi=*pj;*pj=w;pi++;pj--;}」で先ず
「w=*pi;*pi=*pj;*pj=w;」で左右を入れ替え、
「pi++;pj--;」とローカル左右ポインタを進める!
そして「if(pl<pj){sort_long_1(pl,pj);}」で再帰呼び出し
を自分自身「sort_long_1()」関数をサブルーチン関数とし
て条件「pl<pj」=「元々の左側が内部の右側と左右関係が
保たれて居る」なら、再帰呼び出し
「sort_long_1(pl,pj);」を行う事で数学の
「帰納的定義法」と考えて再帰呼び出しを行った部分
「plからpjのポインタの示す左右範囲」が降順にソート済
みと見なして処理する方法です!★備考★これが再帰呼び出
しを行う事で実現する「クイックソート」と呼ばれる通常の
データでは最速と言われているアルゴリズムです同じ様に
「if(pi<pr){sort_long_1(pi,pr);}」で範囲「piからpr」の
ポインタの示す左右範囲」が降順にソート済みと見なして
処理します!★備考★これが、再帰呼び出しを行う事で
実現する「クイックソート」と呼ばれる通常のデータでは
最速と言われているアルゴリズムですコレは、多くの画像
処理以外のプログラミングで使用されて居ますので数学的
帰納法をアルゴリズムに応用した事を理解して下さい!
C言語的には「再帰呼び出し」との文言で平気で多用しま
す!

(4-15-126)関数「void sort_long_0_key(long* pl,
long* pr,short* plx,short* prx){・・・}」

/************************************************************************/
/*****  QUIC-SORT:昇順ソート:キー=32、添字=16          *****/
/************************************************************************/

void            CopyClear::sort_long_0_key(
    long        *pl,                                // KeyDataの左側Ptr
    long        *pr,                                // KeyDataの右側Ptr
    short       *plx,                               // 添字Data左側Ptr
    short       *prx                                // 添字Data右側Ptr
){
    long        *pi;                                // 内部KeyPtr:  左
    long        *pj;                                // 内部KeyPtr:  右
    short       *pix;                               // 内部添字Ptr:左
    short       *pjx;                               // 内部添字Ptr:右
    int         key;                                // 中央の値
    int         w;                                  // 交換用の場所:キー
    short       wx;                                 // 交換用の場所:添字

    pi  = pl;                                       // KeyDataの左側Set
    pj  = pr;                                       // KeyDataの右側Set
    pix = plx;                                      // 添字左側をSet
    pjx = prx;                                      // 添字右側をSet
    key = *( pi + ( (int)pj - (int)pi )             // 右左の中央値を
                        / ( 2 * sizeof(long) ) );   // セット
    do{                                             // 以下繰り返し
        while( *pi < key ){                         // 左側が小さい間
            pi++;                                   // 左側を中に進める
            pix++;                                  // 添字部も進める
        }                                           //
        while( key < *pj ){                         // 右側が大きい間
            pj--;                                   // 右側を中に進める
            pjx--;                                  // 添字部も進める
        }                                           //
        if( pi <= pj ){                             // 左 ≦ 右 なら
            w   = *pi;                              // 左右のキーデータ
            *pi = *pj;                              // を交換
            *pj = w;                                // し
            pi++;                                   // 左側を中に進める
            pj--;                                   // 右側を中に進める
            wx   = *pix;                            // 左右の添字データ
            *pix = *pjx;                            // を交換
            *pjx = wx;                              // し
            pix++;                                  // 左側を中に進める
            pjx--;                                  // 右側を中に進める
        }                                           //
    }while( pi <= pj );                             // 左≦右なら繰返し
    if( pl < pj ){                                  // 外左 < 中右 なら
        sort_long_0_key( pl, pj, plx, pjx );        // この間をソート
    }                                               //
    if( pi < pr ){                                  // 中左 < 外右 なら
        sort_long_0_key( pi, pr, pix, prx );        // この間をソート
    }                                               //
}

☆備考☆この関数はファイル「CopyClear100.cpp」に存在!
★注意★この関数は「private:属性」ですのでライブラリの
外から使用不能です!

(A)関数「sort_long_0_key();」の【関数名】

「Sort」は、勿論、英単語「sort」、カタカナ語ソート・
ソーティング、詰り並び替えです!
「long」は、4バイト符号有り「long型」データを意味し
ます!
「0」は、昇順にソートする事を意味します!
「key」は、キー付きを意味し、連動して連動配列も中身の
入れ替えを行う事を意味します!
この関数は、データ配列を昇順≪小さい方から大きい方へ
整列≫にソートする関数でインデックス配列も連動して作成
★備考★「_」で区切って居るのは、極初期に作成された
ので区切りに「_」を使用するか、単語先頭「英大文字」と
色々迷って居た時期です!

(B)関数「void sort_long_0_key();」の【返値】

返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!

(C)関数「sort_long_0_key()」の【仮引数】

void            CopyClear::sort_long_0_key(
    long        *pl,                                // KeyDataの左側Ptr
    long        *pr,                                // KeyDataの右側Ptr
    short       *plx,                               // 添字Data左側Ptr
    short       *prx                                // 添字Data右側Ptr
){

「long* pl,」は、データ配列左端「l=left省略」
「long* pr」は、データ配列右端「r=right省略」
「short* plx,」は、連動配列配列左端
「short* prx」は、連動配列配列左端
★備考★上記「long* pl,long* pr」をソート対象キー配列
として、ここ「short* plx,short* prx」は、連動して入れ
替えられる配列

(D)関数「sort_long_0_key()」の【アルゴリズム】

){
    long        *pi;                                // 内部KeyPtr:  左
    long        *pj;                                // 内部KeyPtr:  右
    short       *pix;                               // 内部添字Ptr:左
    short       *pjx;                               // 内部添字Ptr:右
    int         key;                                // 中央の値
    int         w;                                  // 交換用の場所:キー
    short       wx;                                 // 交換用の場所:添字

    pi  = pl;                                       // KeyDataの左側Set
    pj  = pr;                                       // KeyDataの右側Set
    pix = plx;                                      // 添字左側をSet
    pjx = prx;                                      // 添字右側をSet
    key = *( pi + ( (int)pj - (int)pi )             // 右左の中央値を
                        / ( 2 * sizeof(long) ) );   // セット
    do{                                             // 以下繰り返し
        while( *pi < key ){                         // 左側が小さい間
            pi++;                                   // 左側を中に進める
            pix++;                                  // 添字部も進める
        }                                           //
        while( key < *pj ){                         // 右側が大きい間
            pj--;                                   // 右側を中に進める
            pjx--;                                  // 添字部も進める
        }                                           //
        if( pi <= pj ){                             // 左 ≦ 右 なら
            w   = *pi;                              // 左右のキーデータ
            *pi = *pj;                              // を交換
            *pj = w;                                // し
            pi++;                                   // 左側を中に進める
            pj--;                                   // 右側を中に進める
            wx   = *pix;                            // 左右の添字データ
            *pix = *pjx;                            // を交換
            *pjx = wx;                              // し
            pix++;                                  // 左側を中に進める
            pjx--;                                  // 右側を中に進める
        }                                           //
    }while( pi <= pj );                             // 左≦右なら繰返し
    if( pl < pj ){                                  // 外左 < 中右 なら
        sort_long_0_key( pl, pj, plx, pjx );        // この間をソート
    }                                               //
    if( pi < pr ){                                  // 中左 < 外右 なら
        sort_long_0_key( pi, pr, pix, prx );        // この間をソート
    }                                               //
}

(D-1)ローカル変数

){
    long        *pi;                                // 内部KeyPtr:  左
    long        *pj;                                // 内部KeyPtr:  右
    short       *pix;                               // 内部添字Ptr:左
    short       *pjx;                               // 内部添字Ptr:右
    int         key;                                // 中央の値
    int         w;                                  // 交換用の場所:キー
    short       wx;                                 // 交換用の場所:添字

「long* pi;」は、内部ポインタ(左側用)キー
「long* pj;」は、内部ポインタ(右側用)キー
「short* pix;」は、内部ポインタ(左側用)連動
「short* pjx;」は、内部ポインタ(右側用)連動
「int key;」は、中央の値(キー比較用)
「int w;」は、データ交換用の場所
「short wx;」は、データ交換用の場所連動

(D―2)アルゴリズムコード

    pi  = pl;                                       // KeyDataの左側Set
    pj  = pr;                                       // KeyDataの右側Set
    pix = plx;                                      // 添字左側をSet
    pjx = prx;                                      // 添字右側をSet
    key = *( pi + ( (int)pj - (int)pi )             // 右左の中央値を
                        / ( 2 * sizeof(long) ) );   // セット
    do{                                             // 以下繰り返し
        while( *pi < key ){                         // 左側が小さい間
            pi++;                                   // 左側を中に進める
            pix++;                                  // 添字部も進める
        }                                           //
        while( key < *pj ){                         // 右側が大きい間
            pj--;                                   // 右側を中に進める
            pjx--;                                  // 添字部も進める
        }                                           //
        if( pi <= pj ){                             // 左 ≦ 右 なら
            w   = *pi;                              // 左右のキーデータ
            *pi = *pj;                              // を交換
            *pj = w;                                // し
            pi++;                                   // 左側を中に進める
            pj--;                                   // 右側を中に進める
            wx   = *pix;                            // 左右の添字データ
            *pix = *pjx;                            // を交換
            *pjx = wx;                              // し
            pix++;                                  // 左側を中に進める
            pjx--;                                  // 右側を中に進める
        }                                           //
    }while( pi <= pj );                             // 左≦右なら繰返し
    if( pl < pj ){                                  // 外左 < 中右 なら
        sort_long_0_key( pl, pj, plx, pjx );        // この間をソート
    }                                               //
    if( pi < pr ){                                  // 中左 < 外右 なら
        sort_long_0_key( pi, pr, pix, prx );        // この間をソート
    }                                               //
}

「pi=pl;pj=pr;」は、ローカルな左側・右側をセット
「pix=plx;pjx=prx;」は、ローカルな左側・右側をセット
「key=*(pi+((int)pj-(int)pi)/(2*sizeof(long)))」は、
左右の中央の場所(ポインタの中央)の値を取り出す!
二重ループで外側の
do構文「・・外側ループ本体・・}while(pi<=pj);」と
後置ループ条件「pi<=pj」と内部のポインタの左右関係が
保たれている間繰り返す!そして最初の内側のループ
「while(*pi<key){pi++;pix++;}」は、while構文で
ループ条件「*pi<key」は、「左側の値が、比較用の値
未満」の間「pi++;pix++;」ポインタを右側に移動を
繰り返すと、即ち、「左側がキーの値以上に成るまで繰り
返す」、
次の内側ループ
「while(key<*pj){pj--;pjx--;}」は、「右」側の値が、
比較用の値越え」の間「pj--;pjx--;」ポインタを左側に
移動を繰り返すと、即ち、「右側がキーの値以下に成るまで
繰り返す」、そしてif構文
「if(pi<=pj){w=*pi;*pi=*pj;*pj=w;pi++;
pj--;wx=*pix;*pix=*pjx;*pjx=wx;pix++;pjx--;}」は、
条件「pi<=pj」と左右関係が保たれていたら
「w=*pi;*pi=*pj;*pj=w;pi++;pj--;wx=*pix;
*pix=*pjx;*pjx=wx;pix++;pjx--;
wx=*pix;*pix=*pjx;*pjx=wx;pix++;pjx--;}」で先ず
「w=*pi;*pi=*pj;*pj=w;」でキーデータ左右を入れ替え、
「pi++;pj--;」とローカル左右ポインタを進める!
そして連動配列の入れ替えとして
「wx=*pix;*pix=*pjx;*pjx=wx;pix++;pjx--;」と配列入れ
替えを行い!「do構文」を終えると!
そして「if(pl<pj){sort_long_0_key(pl,pj,plx,pjx);}」
で再帰呼び出しを自分自身「sort_long_0_key()」関数を
サブルーチン関数として条件「pl<pj」=「元々の左側が
内部の右側と左右関係が保たれて居る」なら、再帰呼び出し
「sort_long_0_key(pl,pj,plx,pjx);」を行う事で数学の
「帰納的定義法」と考えて再帰呼び出しを行った部分
「plからpjのポインタの示す左右範囲」が昇順にソート済
みと見なして処理する方法です!★備考★これが再帰呼び出
しを行う事で実現する「クイックソート」と呼ばれる通常の
データでは最速と言われているアルゴリズムです同じ様に
「if(pi<pr){sort_long_0_key(pi,pr,pix,prx);}」で範囲
「piからpr」のポインタの示す左右範囲」が昇順にソート
済みと見なして処理します!★備考★これが、再帰呼び出し
を行う事で実現する「クイックソート」と呼ばれる通常の
データでは最速と言われているアルゴリズムですコレは、
多くの画像処理以外のプログラミングで使用されて居ますの
で数学的帰納法をアルゴリズムに応用した事を理解して下さ
い!C言語的には「再帰呼び出し」との文言で平気で多用し
ます!

(4-15-127)関数「void sort_long_1_key(long* pl,
long* pr,short* plx,short* prx){・・・}」

/************************************************************************/
/*****  QUIC-SORT:降順ソート:キー=32、添字1=16        *****/
/************************************************************************/

void            CopyClear::sort_long_1_key(
    long        *pl,                                // KeyDataの左側Ptr
    long        *pr,                                // KeyDataの右側Ptr
    short       *plx,                               // 添字Data左側Ptr
    short       *prx                                // 添字Data右側Ptr
){
    long        *pi;                                // 内部KeyPtr:  左
    long        *pj;                                // 内部KeyPtr:  右
    short       *pix;                               // 内部添字Ptr:左
    short       *pjx;                               // 内部添字Ptr:右
    int         key;                                // 中央の値
    int         w;                                  // 交換用の場所:キー
    short       wx;                                 // 交換用の場所:添字

    pi  = pl;                                       // KeyDataの左側Set
    pj  = pr;                                       // KeyDataの右側Set
    pix = plx;                                      // 添字左側をSet
    pjx = prx;                                      // 添字右側をSet
    key = *( pi + ( (int)pj - (int)pi )             // 右左の中央値を
                        / ( 2 * sizeof(long) ) );   // セット
    do{                                             // 以下繰り返し
        while( *pi > key ){                         // 左側が大きい間
            pi++;                                   // 左側を中に進める
            pix++;                                  // 添字部も進める
        }                                           //
        while( key > *pj ){                         // 右側が小さい間
            pj--;                                   // 右側を中に進める
            pjx--;                                  // 添字部も進める
        }                                           //
        if( pi <= pj ){                             // 左 ≦ 右 なら
            w   = *pi;                              // 左右のキーデータ
            *pi = *pj;                              // を交換
            *pj = w;                                // し
            pi++;                                   // 左側を中に進める
            pj--;                                   // 右側を中に進める
            wx   = *pix;                            // 左右の添字データ
            *pix = *pjx;                            // を交換
            *pjx = wx;                              // し
            pix++;                                  // 左側を中に進める
            pjx--;                                  // 右側を中に進める
        }                                           //
    }while( pi <= pj );                             // 左≦右なら繰返し
    if( pl < pj ){                                  // 外左 < 中右 なら
        sort_long_1_key( pl, pj, plx, pjx );        // この間をソート
    }                                               //
    if( pi < pr ){                                  // 中左 < 外右 なら
        sort_long_1_key( pi, pr, pix, prx );        // この間をソート
    }                                               //
}

☆備考☆この関数はファイル「CopyClear100.cpp」に存在!
★注意★この関数は「private:属性」ですのでライブラリの
外から使用不能です!

(A)関数「sort_long_1_key();」の【関数名】

「Sort」は、勿論、英単語「sort」、カタカナ語ソート・
ソーティング、詰り並び替えです!
「long」は、4バイト符号有り「long型」データを意味し
ます!
「1」は、降順にソートする事を意味します!
この関数は、データ配列を降順≪大きい方からへ小さい方に
整列≫にソートする関数
「key」は、キー付きを意味し、連動して連動配列も中身の
入れ替えを行う事を意味します!
この関数は、データ配列を降順≪大きい方からへ小さい方に
整列≫にソートする関数でインデックス配列も連動して作成
★備考★「_」で区切って居るのは、極初期に作成された
ので区切りに「_」を使用するか、単語先頭「英大文字」と
色々迷って居た時期です!

(B)関数「void sort_long_1_key();」の【返値】

返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!

(C)関数「sort_long_1_key()」の【仮引数】

void            CopyClear::sort_long_1_key(
    long        *pl,                                // KeyDataの左側Ptr
    long        *pr,                                // KeyDataの右側Ptr
    short       *plx,                               // 添字Data左側Ptr
    short       *prx                                // 添字Data右側Ptr
){

「long* pl,」は、データ配列左端「l=left省略」
「long* pr」は、データ配列右端「r=right省略」
「short* plx,」は、連動配列配列左端
「short* prx」は、連動配列配列左端
★備考★上記「long* pl,long* pr」をソート対象キー配列
として、ここ「short* plx,short* prx」は、連動して入れ
替えられる配列

(D)関数「sort_long_1_key()」の【アルゴリズム】

){
    long        *pi;                                // 内部KeyPtr:  左
    long        *pj;                                // 内部KeyPtr:  右
    short       *pix;                               // 内部添字Ptr:左
    short       *pjx;                               // 内部添字Ptr:右
    int         key;                                // 中央の値
    int         w;                                  // 交換用の場所:キー
    short       wx;                                 // 交換用の場所:添字

    pi  = pl;                                       // KeyDataの左側Set
    pj  = pr;                                       // KeyDataの右側Set
    pix = plx;                                      // 添字左側をSet
    pjx = prx;                                      // 添字右側をSet
    key = *( pi + ( (int)pj - (int)pi )             // 右左の中央値を
                        / ( 2 * sizeof(long) ) );   // セット
    do{                                             // 以下繰り返し
        while( *pi > key ){                         // 左側が大きい間
            pi++;                                   // 左側を中に進める
            pix++;                                  // 添字部も進める
        }                                           //
        while( key > *pj ){                         // 右側が小さい間
            pj--;                                   // 右側を中に進める
            pjx--;                                  // 添字部も進める
        }                                           //
        if( pi <= pj ){                             // 左 ≦ 右 なら
            w   = *pi;                              // 左右のキーデータ
            *pi = *pj;                              // を交換
            *pj = w;                                // し
            pi++;                                   // 左側を中に進める
            pj--;                                   // 右側を中に進める
            wx   = *pix;                            // 左右の添字データ
            *pix = *pjx;                            // を交換
            *pjx = wx;                              // し
            pix++;                                  // 左側を中に進める
            pjx--;                                  // 右側を中に進める
        }                                           //
    }while( pi <= pj );                             // 左≦右なら繰返し
    if( pl < pj ){                                  // 外左 < 中右 なら
        sort_long_1_key( pl, pj, plx, pjx );        // この間をソート
    }                                               //
    if( pi < pr ){                                  // 中左 < 外右 なら
        sort_long_1_key( pi, pr, pix, prx );        // この間をソート
    }                                               //
}

(D-1)ローカル変数

){
    long        *pi;                                // 内部KeyPtr:  左
    long        *pj;                                // 内部KeyPtr:  右
    short       *pix;                               // 内部添字Ptr:左
    short       *pjx;                               // 内部添字Ptr:右
    int         key;                                // 中央の値
    int         w;                                  // 交換用の場所:キー
    short       wx;                                 // 交換用の場所:添字

「long* pi;」は、内部ポインタ(左側用)キー
「long* pj;」は、内部ポインタ(右側用)キー
「short* pix;」は、内部ポインタ(左側用)連動
「short* pjx;」は、内部ポインタ(右側用)連動
「int key;」は、中央の値(キー比較用)
「int w;」は、データ交換用の場所
「short wx;」は、データ交換用の場所連動

(D―2)アルゴリズムコード

    pi  = pl;                                       // KeyDataの左側Set
    pj  = pr;                                       // KeyDataの右側Set
    pix = plx;                                      // 添字左側をSet
    pjx = prx;                                      // 添字右側をSet
    key = *( pi + ( (int)pj - (int)pi )             // 右左の中央値を
                        / ( 2 * sizeof(long) ) );   // セット
    do{                                             // 以下繰り返し
        while( *pi > key ){                         // 左側が大きい間
            pi++;                                   // 左側を中に進める
            pix++;                                  // 添字部も進める
        }                                           //
        while( key > *pj ){                         // 右側が小さい間
            pj--;                                   // 右側を中に進める
            pjx--;                                  // 添字部も進める
        }                                           //
        if( pi <= pj ){                             // 左 ≦ 右 なら
            w   = *pi;                              // 左右のキーデータ
            *pi = *pj;                              // を交換
            *pj = w;                                // し
            pi++;                                   // 左側を中に進める
            pj--;                                   // 右側を中に進める
            wx   = *pix;                            // 左右の添字データ
            *pix = *pjx;                            // を交換
            *pjx = wx;                              // し
            pix++;                                  // 左側を中に進める
            pjx--;                                  // 右側を中に進める
        }                                           //
    }while( pi <= pj );                             // 左≦右なら繰返し
    if( pl < pj ){                                  // 外左 < 中右 なら
        sort_long_1_key( pl, pj, plx, pjx );        // この間をソート
    }                                               //
    if( pi < pr ){                                  // 中左 < 外右 なら
        sort_long_1_key( pi, pr, pix, prx );        // この間をソート
    }                                               //
}

「pi=pl;pj=pr;」は、ローカルな左側・右側をセット
「pix=plx;pjx=prx;」は、ローカルな左側・右側をセット
「key=*(pi+((int)pj-(int)pi)/(2*sizeof(long)))」は、
左右の中央の場所(ポインタの中央)の値を取り出す!
二重ループで外側の
do構文「・・外側ループ本体・・}while(pi<=pj);」と
後置ループ条件「pi<=pj」と内部のポインタの左右関係が
保たれている間繰り返す!そして最初の内側のループ
「while(*pi>key){pi++;pix++;}」は、while構文で
ループ条件「*pi>key」は、「左側の値が、比較用の値
未満」の間「pi++;pix++;」ポインタを右側に移動を繰り返
すと、即ち、「左側がキーの値以下に成るまで繰り返す」、
次の内側ループ
「while(key>*pj){pj--;pjx--;}」は、「右」側の値が、
比較用の値越え」の間「pj--;pjx--;」ポインタを左側に
移動を繰り返すと、即ち、「右側がキーの値以上に成るまで
繰り返す」、そしてif構文
「if(pi<=pj){w=*pi;*pi=*pj;*pj=w;pi++;
pj--;wx=*pix;*pix=*pjx;*pjx=wx;pix++;pjx--;}」は、
条件「pi<=pj」と左右関係が保たれていたら
「w=*pi;*pi=*pj;*pj=w;pi++;pj--;wx=*pix;
*pix=*pjx;*pjx=wx;pix++;pjx--;
wx=*pix;*pix=*pjx;*pjx=wx;pix++;pjx--;}」で先ず
「w=*pi;*pi=*pj;*pj=w;」でキーデータ左右を入れ替え、
「pi++;pj--;」とローカル左右ポインタを進める!
そして連動配列の入れ替えとして
「wx=*pix;*pix=*pjx;*pjx=wx;pix++;pjx--;」と配列入れ
替えを行い!「do構文」を終えると!
そして「if(pl<pj){sort_long_1_key(pl,pj,plx,pjx);}」
で再帰呼び出しを自分自身「sort_long_1_key()」関数を
サブルーチン関数として条件「pl<pj」=「元々の左側が
内部の右側と左右関係が保たれて居る」なら、再帰呼び出し
「sort_long_1_key(pl,pj,plx,pjx);」を行う事で数学の
「帰納的定義法」と考えて再帰呼び出しを行った部分
「plからpjのポインタの示す左右範囲」が降順にソート済
みと見なして処理する方法です!★備考★これが再帰呼び出
しを行う事で実現する「クイックソート」と呼ばれる通常の
データでは最速と言われているアルゴリズムです同じ様に
「if(pi<pr){sort_long_1_key(pi,pr,pix,prx);}」で範囲
「piからpr」のポインタの示す左右範囲」が降順にソート
済みと見なして処理します!★備考★これが、再帰呼び出し
を行う事で実現する「クイックソート」と呼ばれる通常の
データでは最速と言われているアルゴリズムですコレは、
多くの画像処理以外のプログラミングで使用されて居ますの
で数学的帰納法をアルゴリズムに応用した事を理解して下さ
い!C言語的には「再帰呼び出し」との文言で平気で多用し
ます!
★★特注「note編集機能不具合」★★
「key=*(pi+((int)pj-(int)pi)/(2*sizeof(long)))」と
コピペでテキストを記載したら、
「key=(pi+((int)pj-(int)pi)/(2sizeof(long)))」等と
主に「*」が消える事が多々ありますので注意して手作業で
修正して居るが、全て修正出来て無い部分が有る事に留意し
て読んで頂きたい!必ず、【<>code】機能で生のテキ
ストを必ず参考にして下さい!!

(4-15-128)関数「void sort_float_0(float* pl,float* pr){・・・}」

/************************************************************************/
/*****      QUIC-SORT:昇順ソート:データ=単精度実数      *****/
/************************************************************************/

void            CopyClear::sort_float_0(
    float       *pl,                                // データの左側Ptr
    float       *pr                                 // データの右側Ptr
){
    float       *pi;                                // 内部Ptr:  左
    float       *pj;                                // 内部Ptr:  右
    float       key;                                // 中央の値
    float       w;                                  // 交換用の場所

    pi  = pl;                                       // KeyDataの左側Set
    pj  = pr;                                       // KeyDataの右側Set
    key = *( pi + ( (int)pj - (int)pi )             // 右左の中央値を
                        / ( 2 * sizeof(float) ) );  // セット
    do{                                             // 以下繰り返し
        while( *pi < key ){                         // 左側が小さい間
            pi++;                                   // 左側を中に進める
        }                                           //
        while( key < *pj ){                         // 右側が大きい間
            pj--;                                   // 右側を中に進める
        }                                           //
        if( pi <= pj ){                             // 左 ≦ 右 なら
            w   = *pi;                              // 左右のキーデータ
            *pi = *pj;                              // を交換
            *pj = w;                                // し
            pi++;                                   // 左側を中に進める
            pj--;                                   // 右側を中に進める
        }                                           //
    }while( pi <= pj );                             // 左≦右なら繰返し
    if( pl < pj ){                                  // 外左 < 中右 なら
        sort_float_0( pl, pj );                     // この間をソート
    }                                               //
    if( pi < pr ){                                  // 中左 < 外右 なら
        sort_float_0( pi, pr );                     // この間をソート
    }                                               //
}

☆備考☆この関数はファイル「CopyClear100.cpp」に存在!
★注意★この関数は「private:属性」ですのでライブラリの
外から使用不能です!

(A)関数「sort_float_0();」の【関数名】

「Sort」は、勿論、英単語「sort」、カタカナ語ソート・
ソーティング、詰り並び替えです!
「float」は、単精度浮動小数型「float型」データを意味
します!
「0」は、昇順にソートする事を意味します!
この関数は、データ配列を昇順≪小さい方から大きい方へ
整列≫にソートする関数
★備考★「_」で区切って居るのは、極初期に作成された
ので区切りに「_」を使用するか、単語先頭「英大文字」と
色々迷って居た時期です!

(B)関数「void sort_float_0();」の【返値】

返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!

(C)関数「sort_float_0()」の【仮引数】

void            CopyClear::sort_float_0(
    float       *pl,                                // データの左側Ptr
    float       *pr                                 // データの右側Ptr
){

「float* pl,」は、データ配列左端「l=left省略」
「float* pr」は、データ配列右端「r=right省略」

(D)関数「sort_float_0()」の【アルゴリズム】

){
    float       *pi;                                // 内部Ptr:  左
    float       *pj;                                // 内部Ptr:  右
    float       key;                                // 中央の値
    float       w;                                  // 交換用の場所

    pi  = pl;                                       // KeyDataの左側Set
    pj  = pr;                                       // KeyDataの右側Set
    key = *( pi + ( (int)pj - (int)pi )             // 右左の中央値を
                        / ( 2 * sizeof(float) ) );  // セット
    do{                                             // 以下繰り返し
        while( *pi < key ){                         // 左側が小さい間
            pi++;                                   // 左側を中に進める
        }                                           //
        while( key < *pj ){                         // 右側が大きい間
            pj--;                                   // 右側を中に進める
        }                                           //
        if( pi <= pj ){                             // 左 ≦ 右 なら
            w   = *pi;                              // 左右のキーデータ
            *pi = *pj;                              // を交換
            *pj = w;                                // し
            pi++;                                   // 左側を中に進める
            pj--;                                   // 右側を中に進める
        }                                           //
    }while( pi <= pj );                             // 左≦右なら繰返し
    if( pl < pj ){                                  // 外左 < 中右 なら
        sort_float_0( pl, pj );                     // この間をソート
    }                                               //
    if( pi < pr ){                                  // 中左 < 外右 なら
        sort_float_0( pi, pr );                     // この間をソート
    }                                               //
}

(D-1)ローカル変数

){
    float       *pi;                                // 内部Ptr:  左
    float       *pj;                                // 内部Ptr:  右
    float       key;                                // 中央の値
    float       w;                                  // 交換用の場所

「float* pi;」は、内部ポインタ(左側用)
「float* pj;」は、内部ポインタ(右側用)
「float key;」は、中央の値(キー比較用)
「float w;」は、データ交換用の場所

(D―2)アルゴリズムコード

    pi  = pl;                                       // KeyDataの左側Set
    pj  = pr;                                       // KeyDataの右側Set
    key = *( pi + ( (int)pj - (int)pi )             // 右左の中央値を
                        / ( 2 * sizeof(float) ) );  // セット
    do{                                             // 以下繰り返し
        while( *pi < key ){                         // 左側が小さい間
            pi++;                                   // 左側を中に進める
        }                                           //
        while( key < *pj ){                         // 右側が大きい間
            pj--;                                   // 右側を中に進める
        }                                           //
        if( pi <= pj ){                             // 左 ≦ 右 なら
            w   = *pi;                              // 左右のキーデータ
            *pi = *pj;                              // を交換
            *pj = w;                                // し
            pi++;                                   // 左側を中に進める
            pj--;                                   // 右側を中に進める
        }                                           //
    }while( pi <= pj );                             // 左≦右なら繰返し
    if( pl < pj ){                                  // 外左 < 中右 なら
        sort_float_0( pl, pj );                     // この間をソート
    }                                               //
    if( pi < pr ){                                  // 中左 < 外右 なら
        sort_float_0( pi, pr );                     // この間をソート
    }                                               //
}

「pi=pl;pj=pr;」は、ローカルな左側・右側をセット
「key=*(pi+((int)pj-(int)pi)/(2*sizeof(float)))」は、
左右の中央の場所(ポインタの中央)の値を取り出す!
二重ループで外側の
do構文「・・外側ループ本体・・}while(pi<=pj);」と
後置ループ条件「pi<=pj」と内部のポインタの左右関係が
保たれている間繰り返す!そして最初の内側のループ
「while(*pi<key){pi++;}」は、while構文で
ループ条件「*pi<key」は、「左側の値が、
比較用の値未満」の間「pi++;」ポインタを右側に移動を
繰り返すと、即ち、「左側がキーの値以上に成るまで繰り
返す」、次の内側ループ
「while(key<*pj){pj--;}」は、「右」側の
値が、比較用の値越え」の間「pj--;」ポインタを左側に
移動を繰り返すと、即ち、「右側がキーの値以下に成るまで
繰り返す」、そしてif構文
「if(pi<=pj){w=*pi;*pi=*pj;*pj=w;pi++;
pj--;}」は、条件「pi<=pj」と左右関係が保たれていたら
「w=*pi;*pi=*pj;*pj=w;pi++;pj--;}」で先ず
「w=*pi;*pi=*pj;*pj=w;」で左右を入れ替え、
「pi++;pj--;」とローカル左右ポインタを進める!
そして「if(pl<pj){sort_float_0(pl,pj);}」で再帰呼び出し
を自分自身「sort_float_0()」関数をサブルーチン関数とし
て条件「pl<pj」=「元々の左側が内部の右側と左右関係が
保たれて居る」なら、再帰呼び出し
「sort_float_0(pl,pj);」を行う事で数学の
「帰納的定義法」と考えて再帰呼び出しを行った部分
「plからpjのポインタの示す左右範囲」が昇順にソート済
みと見なして処理する方法です!★備考★これが再帰呼び出
しを行う事で実現する「クイックソート」と呼ばれる通常の
データでは最速と言われているアルゴリズムです同じ様に
「if(pi<pr){sort_float_0(pi,pr);}」で範囲「piからpr」の
ポインタの示す左右範囲」が昇順にソート済みと見なして
処理します!★備考★これが、再帰呼び出しを行う事で
実現する「クイックソート」と呼ばれる通常のデータでは
最速と言われているアルゴリズムですコレは、多くの画像
処理以外のプログラミングで使用されて居ますので数学的
帰納法をアルゴリズムに応用した事を理解して下さい!
C言語的には「再帰呼び出し」との文言で平気で多用しま
す!

(4-15-129)関数「void sort_float_1(float* pl,float* pr){・・・}」

/************************************************************************/
/*****      QUIC-SORT:降順ソート:データ=単精度実数      *****/
/************************************************************************/

void            CopyClear::sort_float_1(
    float       *pl,                                // データの左側Ptr
    float       *pr                                 // データの右側Ptr
){
    float       *pi;                                // 内部Ptr:  左
    float       *pj;                                // 内部Ptr:  右
    float       key;                                // 中央の値
    float       w;                                  // 交換用の場所

    pi  = pl;                                       // KeyDataの左側Set
    pj  = pr;                                       // KeyDataの右側Set
    key = *( pi + ( (int)pj - (int)pi )             // 右左の中央値を
                        / ( 2 * sizeof(float) ) );  // セット
    do{                                             // 以下繰り返し
        while( *pi > key ){                         // 左側が大きい間
            pi++;                                   // 左側を中に進める
        }                                           //
        while( key > *pj ){                         // 右側が小さい間
            pj--;                                   // 右側を中に進める
        }                                           //
        if( pi <= pj ){                             // 左 ≦ 右 なら
            w   = *pi;                              // 左右のキーデータ
            *pi = *pj;                              // を交換
            *pj = w;                                // し
            pi++;                                   // 左側を中に進める
            pj--;                                   // 右側を中に進める
        }                                           //
    }while( pi <= pj );                             // 左≦右なら繰返し
    if( pl < pj ){                                  // 外左 < 中右 なら
        sort_float_1( pl, pj );                     // この間をソート
    }                                               //
    if( pi < pr ){                                  // 中左 < 外右 なら
        sort_float_1( pi, pr );                     // この間をソート
    }                                               //
}

☆備考☆この関数はファイル「CopyClear100.cpp」に存在!
★注意★この関数は「private:属性」ですのでライブラリの
外から使用不能です!

(A)関数「sort_float_1();」の【関数名】

「Sort」は、勿論、英単語「sort」、カタカナ語ソート・
ソーティング、詰り並び替えです!
「float」は、単精度浮動小数型「float型」データを意味
します!
「1」は、降順にソートする事を意味します!
この関数は、データ配列を降順≪大きい方からへ小さい方に
整列≫にソートする関数
★備考★「_」で区切って居るのは、極初期に作成された
ので区切りに「_」を使用するか、単語先頭「英大文字」と
色々迷って居た時期です!

(B)関数「void sort_float_1();」の【返値】

返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!

(C)関数「sort_float_1()」の【仮引数】

void            CopyClear::sort_float_1(
    float       *pl,                                // データの左側Ptr
    float       *pr                                 // データの右側Ptr
){

「float* pl,」は、データ配列左端「l=left省略」
「float* pr」は、データ配列右端「r=right省略」

(D)関数「sort_float_1()」の【アルゴリズム】

){
    float       *pi;                                // 内部Ptr:  左
    float       *pj;                                // 内部Ptr:  右
    float       key;                                // 中央の値
    float       w;                                  // 交換用の場所

    pi  = pl;                                       // KeyDataの左側Set
    pj  = pr;                                       // KeyDataの右側Set
    key = *( pi + ( (int)pj - (int)pi )             // 右左の中央値を
                        / ( 2 * sizeof(float) ) );  // セット
    do{                                             // 以下繰り返し
        while( *pi > key ){                         // 左側が大きい間
            pi++;                                   // 左側を中に進める
        }                                           //
        while( key > *pj ){                         // 右側が小さい間
            pj--;                                   // 右側を中に進める
        }                                           //
        if( pi <= pj ){                             // 左 ≦ 右 なら
            w   = *pi;                              // 左右のキーデータ
            *pi = *pj;                              // を交換
            *pj = w;                                // し
            pi++;                                   // 左側を中に進める
            pj--;                                   // 右側を中に進める
        }                                           //
    }while( pi <= pj );                             // 左≦右なら繰返し
    if( pl < pj ){                                  // 外左 < 中右 なら
        sort_float_1( pl, pj );                     // この間をソート
    }                                               //
    if( pi < pr ){                                  // 中左 < 外右 なら
        sort_float_1( pi, pr );                     // この間をソート
    }                                               //
}

(D-1)ローカル変数

){
    float       *pi;                                // 内部Ptr:  左
    float       *pj;                                // 内部Ptr:  右
    float       key;                                // 中央の値
    float       w;                                  // 交換用の場所

「float* pi;」は、内部ポインタ(左側用)
「float* pj;」は、内部ポインタ(右側用)
「float key;」は、中央の値(キー比較用)
「float w;」は、データ交換用の場所

(D―2)アルゴリズムコード

    pi  = pl;                                       // KeyDataの左側Set
    pj  = pr;                                       // KeyDataの右側Set
    key = *( pi + ( (int)pj - (int)pi )             // 右左の中央値を
                        / ( 2 * sizeof(float) ) );  // セット
    do{                                             // 以下繰り返し
        while( *pi > key ){                         // 左側が大きい間
            pi++;                                   // 左側を中に進める
        }                                           //
        while( key > *pj ){                         // 右側が小さい間
            pj--;                                   // 右側を中に進める
        }                                           //
        if( pi <= pj ){                             // 左 ≦ 右 なら
            w   = *pi;                              // 左右のキーデータ
            *pi = *pj;                              // を交換
            *pj = w;                                // し
            pi++;                                   // 左側を中に進める
            pj--;                                   // 右側を中に進める
        }                                           //
    }while( pi <= pj );                             // 左≦右なら繰返し
    if( pl < pj ){                                  // 外左 < 中右 なら
        sort_float_1( pl, pj );                     // この間をソート
    }                                               //
    if( pi < pr ){                                  // 中左 < 外右 なら
        sort_float_1( pi, pr );                     // この間をソート
    }                                               //
}

「pi=pl;pj=pr;」は、ローカルな左側・右側をセット
「key=*(pi+((int)pj-(int)pi)/(2*sizeof(float)))」は、
左右の中央の場所(ポインタの中央)の値を取り出す!
二重ループで外側の
do構文「・・外側ループ本体・・}while(pi<=pj);」と
後置ループ条件「pi<=pj」と内部のポインタの左右関係が
保たれている間繰り返す!そして最初の内側のループ
「while(*pi>key){pi++;}」は、while構文で
ループ条件「*pi>key」は、「左側の値が、
比較用の値越え」の間「pi++;」ポインタを右側に移動を
繰り返すと、即ち、「左側がキーの値以下に成るまで繰り
返す」、次の内側ループ
「while(key>*pj){pj--;}」は、「右」側の
値が、比較用の値未満」の間「pj--;」ポインタを左側に
移動を繰り返すと、即ち、「右側がキーの値以上に成るまで
繰り返す」、そしてif構文
「if(pi<=pj){w=*pi;*pi=*pj;*pj=w;pi++;
pj--;}」は、条件「pi<=pj」と左右関係が保たれていたら
「w=*pi;*pi=*pj;*pj=w;pi++;pj--;}」で先ず
「w=*pi;*pi=*pj;*pj=w;」で左右を入れ替え、
「pi++;pj--;」とローカル左右ポインタを進める!
そして「if(pl<pj){sort_float_1(pl,pj);}」で再帰呼び出し
を自分自身「sort_float_1()」関数をサブルーチン関数とし
て条件「pl<pj」=「元々の左側が内部の右側と左右関係が
保たれて居る」なら、再帰呼び出し
「sort_float_1(pl,pj);」を行う事で数学の
「帰納的定義法」と考えて再帰呼び出しを行った部分
「plからpjのポインタの示す左右範囲」が降順にソート済
みと見なして処理する方法です!★備考★これが再帰呼び出
しを行う事で実現する「クイックソート」と呼ばれる通常の
データでは最速と言われているアルゴリズムです同じ様に
「if(pi<pr){sort_float_1(pi,pr);}」で範囲「piからpr」の
ポインタの示す左右範囲」が降順にソート済みと見なして
処理します!★備考★これが、再帰呼び出しを行う事で
実現する「クイックソート」と呼ばれる通常のデータでは
最速と言われているアルゴリズムですコレは、多くの画像
処理以外のプログラミングで使用されて居ますので数学的
帰納法をアルゴリズムに応用した事を理解して下さい!
C言語的には「再帰呼び出し」との文言で平気で多用しま
す!
★★特注「note編集機能不具合」★★
「key=*(pi+((int)pj-(int)pi)/(2*sizeof(float)))」と
コピペでテキストを記載したら、
「key=(pi+((int)pj-(int)pi)/(2sizeof(float)))」等と
主に「*」が消える事が多々ありますので注意して手作業で
修正して居るが、全て修正出来て無い部分が有る事に留意し
て読んで頂きたい!必ず、【<>code】機能で生のテキ
ストを必ず参考にして下さい!!

(4-15-130)関数「void sort_float_0_key(float* pl,
float* pr,short* plx,short* prx){・・・}」

/************************************************************************/
/*****  QUIC-SORT:昇順ソート:キー=単精度、添字=16      *****/
/************************************************************************/

void            CopyClear::sort_float_0_key(
    float       *pl,                                // KeyDataの左側Ptr
    float       *pr,                                // KeyDataの右側Ptr
    short       *plx,                               // 添字Data左側Ptr
    short       *prx                                // 添字Data右側Ptr
){
    float       *pi;                                // 内部KeyPtr:  左
    float       *pj;                                // 内部KeyPtr:  右
    short       *pix;                               // 内部添字Ptr:左
    short       *pjx;                               // 内部添字Ptr:右
    float       key;                                // 中央の値
    float       w;                                  // 交換用の場所:キー
    short       wx;                                 // 交換用の場所:添字

    pi  = pl;                                       // KeyDataの左側Set
    pj  = pr;                                       // KeyDataの右側Set
    pix = plx;                                      // 添字左側をSet
    pjx = prx;                                      // 添字右側をSet
    key = *( pi + ( (int)pj - (int)pi )             // 右左の中央値を
                        / ( 2 * sizeof(float) ) );  // セット
    do{                                             // 以下繰り返し
        while( *pi < key ){                         // 左側が小さい間
            pi++;                                   // 左側を中に進める
            pix++;                                  // 添字部も進める
        }                                           //
        while( key < *pj ){                         // 右側が大きい間
            pj--;                                   // 右側を中に進める
            pjx--;                                  // 添字部も進める
        }                                           //
        if( pi <= pj ){                             // 左 ≦ 右 なら
            w   = *pi;                              // 左右のキーデータ
            *pi = *pj;                              // を交換
            *pj = w;                                // し
            pi++;                                   // 左側を中に進める
            pj--;                                   // 右側を中に進める
            wx   = *pix;                            // 左右の添字データ
            *pix = *pjx;                            // を交換
            *pjx = wx;                              // し
            pix++;                                  // 左側を中に進める
            pjx--;                                  // 右側を中に進める
        }                                           //
    }while( pi <= pj );                             // 左≦右なら繰返し
    if( pl < pj ){                                  // 外左 < 中右 なら
        sort_float_0_key( pl, pj, plx, pjx );       // この間をソート
    }                                               //
    if( pi < pr ){                                  // 中左 < 外右 なら
        sort_float_0_key( pi, pr, pix, prx );       // この間をソート
    }                                               //
}

☆備考☆この関数はファイル「CopyClear100.cpp」に存在!
★注意★この関数は「private:属性」ですのでライブラリの
外から使用不能です!

(A)関数「sort_float_0_key();」の【関数名】

「Sort」は、勿論、英単語「sort」、カタカナ語ソート・
ソーティング、詰り並び替えです!
「float」は、単精度浮動小数型「float型」データを意味
します!
「0」は、昇順にソートする事を意味します!
「key」は、キー付きを意味し、連動して連動配列も中身の
入れ替えを行う事を意味します!
この関数は、データ配列を昇順≪小さい方から大きい方へ
整列≫にソートする関数でインデックス配列も連動して作成
★備考★「_」で区切って居るのは、極初期に作成された
ので区切りに「_」を使用するか、単語先頭「英大文字」と
色々迷って居た時期です!

(B)関数「void sort_float_0_key();」の【返値】

返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!

(C)関数「sort_float_0_key()」の【仮引数】

void            CopyClear::sort_float_0_key(
    float       *pl,                                // KeyDataの左側Ptr
    float       *pr,                                // KeyDataの右側Ptr
    short       *plx,                               // 添字Data左側Ptr
    short       *prx                                // 添字Data右側Ptr
){

「float* pl,」は、データ配列左端「l=left省略」
「float* pr」は、データ配列右端「r=right省略」
「short* plx,」は、連動配列配列左端
「short* prx」は、連動配列配列左端
★備考★上記「float* pl,float* pr」をソート対象キー配列
として、ここ「short* plx,short* prx」は、連動して入れ
替えられる配列

(D)関数「sort_float_0_key()」の【アルゴリズム】

){
    float       *pi;                                // 内部KeyPtr:  左
    float       *pj;                                // 内部KeyPtr:  右
    short       *pix;                               // 内部添字Ptr:左
    short       *pjx;                               // 内部添字Ptr:右
    float       key;                                // 中央の値
    float       w;                                  // 交換用の場所:キー
    short       wx;                                 // 交換用の場所:添字

    pi  = pl;                                       // KeyDataの左側Set
    pj  = pr;                                       // KeyDataの右側Set
    pix = plx;                                      // 添字左側をSet
    pjx = prx;                                      // 添字右側をSet
    key = *( pi + ( (int)pj - (int)pi )             // 右左の中央値を
                        / ( 2 * sizeof(float) ) );  // セット
    do{                                             // 以下繰り返し
        while( *pi < key ){                         // 左側が小さい間
            pi++;                                   // 左側を中に進める
            pix++;                                  // 添字部も進める
        }                                           //
        while( key < *pj ){                         // 右側が大きい間
            pj--;                                   // 右側を中に進める
            pjx--;                                  // 添字部も進める
        }                                           //
        if( pi <= pj ){                             // 左 ≦ 右 なら
            w   = *pi;                              // 左右のキーデータ
            *pi = *pj;                              // を交換
            *pj = w;                                // し
            pi++;                                   // 左側を中に進める
            pj--;                                   // 右側を中に進める
            wx   = *pix;                            // 左右の添字データ
            *pix = *pjx;                            // を交換
            *pjx = wx;                              // し
            pix++;                                  // 左側を中に進める
            pjx--;                                  // 右側を中に進める
        }                                           //
    }while( pi <= pj );                             // 左≦右なら繰返し
    if( pl < pj ){                                  // 外左 < 中右 なら
        sort_float_0_key( pl, pj, plx, pjx );       // この間をソート
    }                                               //
    if( pi < pr ){                                  // 中左 < 外右 なら
        sort_float_0_key( pi, pr, pix, prx );       // この間をソート
    }                                               //
}

(D-1)ローカル変数

){
    float       *pi;                                // 内部KeyPtr:  左
    float       *pj;                                // 内部KeyPtr:  右
    short       *pix;                               // 内部添字Ptr:左
    short       *pjx;                               // 内部添字Ptr:右
    float       key;                                // 中央の値
    float       w;                                  // 交換用の場所:キー
    short       wx;                                 // 交換用の場所:添字

「float* pi;」は、内部ポインタ(左側用)キー
「float* pj;」は、内部ポインタ(右側用)キー
「short* pix;」は、内部ポインタ(左側用)連動
「short* pjx;」は、内部ポインタ(右側用)連動
「float key;」は、中央の値(キー比較用)
「float w;」は、データ交換用の場所
「short wx;」は、データ交換用の場所連動

(D―2)アルゴリズムコード

    pi  = pl;                                       // KeyDataの左側Set
    pj  = pr;                                       // KeyDataの右側Set
    pix = plx;                                      // 添字左側をSet
    pjx = prx;                                      // 添字右側をSet
    key = *( pi + ( (int)pj - (int)pi )             // 右左の中央値を
                        / ( 2 * sizeof(float) ) );  // セット
    do{                                             // 以下繰り返し
        while( *pi < key ){                         // 左側が小さい間
            pi++;                                   // 左側を中に進める
            pix++;                                  // 添字部も進める
        }                                           //
        while( key < *pj ){                         // 右側が大きい間
            pj--;                                   // 右側を中に進める
            pjx--;                                  // 添字部も進める
        }                                           //
        if( pi <= pj ){                             // 左 ≦ 右 なら
            w   = *pi;                              // 左右のキーデータ
            *pi = *pj;                              // を交換
            *pj = w;                                // し
            pi++;                                   // 左側を中に進める
            pj--;                                   // 右側を中に進める
            wx   = *pix;                            // 左右の添字データ
            *pix = *pjx;                            // を交換
            *pjx = wx;                              // し
            pix++;                                  // 左側を中に進める
            pjx--;                                  // 右側を中に進める
        }                                           //
    }while( pi <= pj );                             // 左≦右なら繰返し
    if( pl < pj ){                                  // 外左 < 中右 なら
        sort_float_0_key( pl, pj, plx, pjx );       // この間をソート
    }                                               //
    if( pi < pr ){                                  // 中左 < 外右 なら
        sort_float_0_key( pi, pr, pix, prx );       // この間をソート
    }                                               //
}

「pi=pl;pj=pr;」は、ローカルな左側・右側をセット
「pix=plx;pjx=prx;」は、ローカルな左側・右側をセット
「key=*(pi+((int)pj-(int)pi)/(2*sizeof(float)))」は、
左右の中央の場所(ポインタの中央)の値を取り出す!
二重ループで外側の
do構文「・・外側ループ本体・・}while(pi<=pj);」と
後置ループ条件「pi<=pj」と内部のポインタの左右関係が
保たれている間繰り返す!そして最初の内側のループ
「while(*pi<key){pi++;}」は、while構文で
ループ条件「*pi<key」は、「左側の値が、
比較用の値未満」の間「pi++;」ポインタを右側に移動を
繰り返すと、即ち、「左側がキーの値以上に成るまで繰り
返す」、次の内側ループ
「while(key<*pj){pj--;}」は、「右」側の
値が、比較用の値越え」の間「pj--;」ポインタを左側に
移動を繰り返すと、即ち、「右側がキーの値以下に成るまで
繰り返す」、そしてif構文
「if(pi<=pj){w=*pi;*pi=*pj;*pj=w;pi++;
pj--;wx=*pix;*pix=*pjx;*pjx=wx;pix++;pjx--;}」は、
条件「pi<=pj」と左右関係が保たれていたら
「w=*pi;*pi=*pj;*pj=w;pi++;pj--;wx=*pix;
*pix=*pjx;*pjx=wx;pix++;pjx--;
wx=*pix;*pix=*pjx;*pjx=wx;pix++;pjx--;}」で先ず
「w=*pi;*pi=*pj;*pj=w;」でキーデータ左右を入れ替え、
「pi++;pj--;」とローカル左右ポインタを進める!
そして連動配列の入れ替えとして
「wx=*pix;*pix=*pjx;*pjx=wx;pix++;pjx--;」と配列入れ
替えを行い!「do構文」を終えると!
そして「if(pl<pj){sort_float_0_key(pl,pj,plx,pjx);}」
で再帰呼び出しを自分自身「sort_float_0_key()」関数を
サブルーチン関数として条件「pl<pj」=「元々の左側が
内部の右側と左右関係が保たれて居る」なら、再帰呼び出し
「sort_float_0_key(pl,pj,plx,pjx);」を行う事で数学の
「帰納的定義法」と考えて再帰呼び出しを行った部分
「plからpjのポインタの示す左右範囲」が昇順にソート済
みと見なして処理する方法です!★備考★これが再帰呼び出
しを行う事で実現する「クイックソート」と呼ばれる通常の
データでは最速と言われているアルゴリズムです同じ様に
「if(pi<pr){sort_float_0_key(pi,pr,pix,prx);}」で範囲
「piからpr」のポインタの示す左右範囲」が昇順にソート
済みと見なして処理します!★備考★これが、再帰呼び出し
を行う事で実現する「クイックソート」と呼ばれる通常の
データでは最速と言われているアルゴリズムですコレは、
多くの画像処理以外のプログラミングで使用されて居ますの
で数学的帰納法をアルゴリズムに応用した事を理解して下さ
い!C言語的には「再帰呼び出し」との文言で平気で多用し
ます!

(4-15-131)関数「void sort_float_1_key(float* pl,
float* pr,short* plx,short* prx){・・・}」

/************************************************************************/
/*****  QUIC-SORT:降順ソート:キー=単精度、添字1=16    *****/
/************************************************************************/

void            CopyClear::sort_float_1_key(
    float       *pl,                                // KeyDataの左側Ptr
    float       *pr,                                // KeyDataの右側Ptr
    short       *plx,                               // 添字Data左側Ptr
    short       *prx                                // 添字Data右側Ptr
){
    float       *pi;                                // 内部KeyPtr:  左
    float       *pj;                                // 内部KeyPtr:  右
    short       *pix;                               // 内部添字Ptr:左
    short       *pjx;                               // 内部添字Ptr:右
    float       key;                                // 中央の値
    float       w;                                  // 交換用の場所:キー
    short       wx;                                 // 交換用の場所:添字

    pi  = pl;                                       // KeyDataの左側Set
    pj  = pr;                                       // KeyDataの右側Set
    pix = plx;                                      // 添字左側をSet
    pjx = prx;                                      // 添字右側をSet
    key = *( pi + ( (int)pj - (int)pi )             // 右左の中央値を
                        / ( 2 * sizeof(float) ) );  // セット
    do{                                             // 以下繰り返し
        while( *pi > key ){                         // 左側が大きい間
            pi++;                                   // 左側を中に進める
            pix++;                                  // 添字部も進める
        }                                           //
        while( key > *pj ){                         // 右側が小さい間
            pj--;                                   // 右側を中に進める
            pjx--;                                  // 添字部も進める
        }                                           //
        if( pi <= pj ){                             // 左 ≦ 右 なら
            w   = *pi;                              // 左右のキーデータ
            *pi = *pj;                              // を交換
            *pj = w;                                // し
            pi++;                                   // 左側を中に進める
            pj--;                                   // 右側を中に進める
            wx   = *pix;                            // 左右の添字データ
            *pix = *pjx;                            // を交換
            *pjx = wx;                              // し
            pix++;                                  // 左側を中に進める
            pjx--;                                  // 右側を中に進める
        }                                           //
    }while( pi <= pj );                             // 左≦右なら繰返し
    if( pl < pj ){                                  // 外左 < 中右 なら
        sort_float_1_key( pl, pj, plx, pjx );       // この間をソート
    }                                               //
    if( pi < pr ){                                  // 中左 < 外右 なら
        sort_float_1_key( pi, pr, pix, prx );       // この間をソート
    }                                               //
}

☆備考☆この関数はファイル「CopyClear100.cpp」に存在!
★注意★この関数は「private:属性」ですのでライブラリの
外から使用不能です!

(A)関数「sort_float_1_key();」の【関数名】

「Sort」は、勿論、英単語「sort」、カタカナ語ソート・
ソーティング、詰り並び替えです!
「float」は、単精度浮動小数型「float型」データを意味
します!
「1」は、降順にソートする事を意味します!
この関数は、データ配列を降順≪大きい方からへ小さい方に
整列≫にソートする関数
「key」は、キー付きを意味し、連動して連動配列も中身の
入れ替えを行う事を意味します!
この関数は、データ配列を降順≪大きい方からへ小さい方に
整列≫にソートする関数でインデックス配列も連動して作成
★備考★「_」で区切って居るのは、極初期に作成された
ので区切りに「_」を使用するか、単語先頭「英大文字」と
色々迷って居た時期です!

(B)関数「void sort_float_1_key();」の【返値】

返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!

(C)関数「sort_float_1_key()」の【仮引数】

void            CopyClear::sort_float_1_key(
    float       *pl,                                // KeyDataの左側Ptr
    float       *pr,                                // KeyDataの右側Ptr
    short       *plx,                               // 添字Data左側Ptr
    short       *prx                                // 添字Data右側Ptr
){

「float* pl,」は、データ配列左端「l=left省略」
「float* pr」は、データ配列右端「r=right省略」
「short* plx,」は、連動配列配列左端
「short* prx」は、連動配列配列左端
★備考★上記「float* pl,float* pr」をソート対象キー配列
として、ここ「short* plx,short* prx」は、連動して入れ
替えられる配列

(D)関数「sort_float_1_key()」の【アルゴリズム】

){
    float       *pi;                                // 内部KeyPtr:  左
    float       *pj;                                // 内部KeyPtr:  右
    short       *pix;                               // 内部添字Ptr:左
    short       *pjx;                               // 内部添字Ptr:右
    float       key;                                // 中央の値
    float       w;                                  // 交換用の場所:キー
    short       wx;                                 // 交換用の場所:添字

    pi  = pl;                                       // KeyDataの左側Set
    pj  = pr;                                       // KeyDataの右側Set
    pix = plx;                                      // 添字左側をSet
    pjx = prx;                                      // 添字右側をSet
    key = *( pi + ( (int)pj - (int)pi )             // 右左の中央値を
                        / ( 2 * sizeof(float) ) );  // セット
    do{                                             // 以下繰り返し
        while( *pi > key ){                         // 左側が大きい間
            pi++;                                   // 左側を中に進める
            pix++;                                  // 添字部も進める
        }                                           //
        while( key > *pj ){                         // 右側が小さい間
            pj--;                                   // 右側を中に進める
            pjx--;                                  // 添字部も進める
        }                                           //
        if( pi <= pj ){                             // 左 ≦ 右 なら
            w   = *pi;                              // 左右のキーデータ
            *pi = *pj;                              // を交換
            *pj = w;                                // し
            pi++;                                   // 左側を中に進める
            pj--;                                   // 右側を中に進める
            wx   = *pix;                            // 左右の添字データ
            *pix = *pjx;                            // を交換
            *pjx = wx;                              // し
            pix++;                                  // 左側を中に進める
            pjx--;                                  // 右側を中に進める
        }                                           //
    }while( pi <= pj );                             // 左≦右なら繰返し
    if( pl < pj ){                                  // 外左 < 中右 なら
        sort_float_1_key( pl, pj, plx, pjx );       // この間をソート
    }                                               //
    if( pi < pr ){                                  // 中左 < 外右 なら
        sort_float_1_key( pi, pr, pix, prx );       // この間をソート
    }                                               //
}

(D-1)ローカル変数

){
    float       *pi;                                // 内部KeyPtr:  左
    float       *pj;                                // 内部KeyPtr:  右
    short       *pix;                               // 内部添字Ptr:左
    short       *pjx;                               // 内部添字Ptr:右
    float       key;                                // 中央の値
    float       w;                                  // 交換用の場所:キー
    short       wx;                                 // 交換用の場所:添字

「float* pi;」は、内部ポインタ(左側用)キー
「float* pj;」は、内部ポインタ(右側用)キー
「short* pix;」は、内部ポインタ(左側用)連動
「short* pjx;」は、内部ポインタ(右側用)連動
「float key;」は、中央の値(キー比較用)
「float w;」は、データ交換用の場所
「short wx;」は、データ交換用の場所連動

(D―2)アルゴリズムコード

    pi  = pl;                                       // KeyDataの左側Set
    pj  = pr;                                       // KeyDataの右側Set
    pix = plx;                                      // 添字左側をSet
    pjx = prx;                                      // 添字右側をSet
    key = *( pi + ( (int)pj - (int)pi )             // 右左の中央値を
                        / ( 2 * sizeof(float) ) );  // セット
    do{                                             // 以下繰り返し
        while( *pi > key ){                         // 左側が大きい間
            pi++;                                   // 左側を中に進める
            pix++;                                  // 添字部も進める
        }                                           //
        while( key > *pj ){                         // 右側が小さい間
            pj--;                                   // 右側を中に進める
            pjx--;                                  // 添字部も進める
        }                                           //
        if( pi <= pj ){                             // 左 ≦ 右 なら
            w   = *pi;                              // 左右のキーデータ
            *pi = *pj;                              // を交換
            *pj = w;                                // し
            pi++;                                   // 左側を中に進める
            pj--;                                   // 右側を中に進める
            wx   = *pix;                            // 左右の添字データ
            *pix = *pjx;                            // を交換
            *pjx = wx;                              // し
            pix++;                                  // 左側を中に進める
            pjx--;                                  // 右側を中に進める
        }                                           //
    }while( pi <= pj );                             // 左≦右なら繰返し
    if( pl < pj ){                                  // 外左 < 中右 なら
        sort_float_1_key( pl, pj, plx, pjx );       // この間をソート
    }                                               //
    if( pi < pr ){                                  // 中左 < 外右 なら
        sort_float_1_key( pi, pr, pix, prx );       // この間をソート
    }                                               //
}

「pi=pl;pj=pr;」は、ローカルな左側・右側をセット
「pix=plx;pjx=prx;」は、ローカルな左側・右側をセット
「key=*(pi+((int)pj-(int)pi)/(2*sizeof(float)))」は、
左右の中央の場所(ポインタの中央)の値を取り出す!
二重ループで外側の
do構文「・・外側ループ本体・・}while(pi<=pj);」と
後置ループ条件「pi<=pj」と内部のポインタの左右関係が
保たれている間繰り返す!そして最初の内側のループ
「while(*pi>key){pi++;pix++;}」は、while構文で
ループ条件「*pi>key」は、「左側の値が、比較用の値
未満」の間「pi++;pix++;」ポインタを右側に移動を
繰り返すと、即ち、「左側がキーの値以上に成るまで繰り
返す」、
次の内側ループ
「while(key>*pj){pj--;pjx--;}」は、「右」側の値が、
比較用の値未満」の間「pj--;pjx--;」ポインタを左側に
移動を繰り返すと、即ち、「右側がキーの値以上に成るまで
繰り返す」、そしてif構文
「if(pi<=pj){w=*pi;*pi=*pj;*pj=w;pi++;
pj--;wx=*pix;*pix=*pjx;*pjx=wx;pix++;pjx--;}」は、
条件「pi<=pj」と左右関係が保たれていたら
「w=*pi;*pi=*pj;*pj=w;pi++;pj--;wx=*pix;
*pix=*pjx;*pjx=wx;pix++;pjx--;
wx=*pix;*pix=*pjx;*pjx=wx;pix++;pjx--;}」で先ず
「w=*pi;*pi=*pj;*pj=w;」でキーデータ左右を入れ替え、
「pi++;pj--;」とローカル左右ポインタを進める!
そして連動配列の入れ替えとして
「wx=*pix;*pix=*pjx;*pjx=wx;pix++;pjx--;」と配列入れ
替えを行い!「do構文」を終えると!
そして「if(pl<pj){sort_float_1_key(pl,pj,plx,pjx);}」
で再帰呼び出しを自分自身「sort_float_1_key()」関数を
サブルーチン関数として条件「pl<pj」=「元々の左側が
内部の右側と左右関係が保たれて居る」なら、再帰呼び出し
「sort_float_1_key(pl,pj,plx,pjx);」を行う事で数学の
「帰納的定義法」と考えて再帰呼び出しを行った部分
「plからpjのポインタの示す左右範囲」が降順にソート済
みと見なして処理する方法です!★備考★これが再帰呼び出
しを行う事で実現する「クイックソート」と呼ばれる通常の
データでは最速と言われているアルゴリズムです同じ様に
「if(pi<pr){sort_float_1_key(pi,pr,pix,prx);}」で範囲
「piからpr」のポインタの示す左右範囲」が降順にソート
済みと見なして処理します!★備考★これが、再帰呼び出し
を行う事で実現する「クイックソート」と呼ばれる通常の
データでは最速と言われているアルゴリズムですコレは、
多くの画像処理以外のプログラミングで使用されて居ますの
で数学的帰納法をアルゴリズムに応用した事を理解して下さ
い!C言語的には「再帰呼び出し」との文言で平気で多用し
ます!

(4-15-132)関数「void sort_double_0(double* pl,
double* pr){・・・}」

/************************************************************************/
/*****      QUIC-SORT:昇順ソート:データ=倍精度実数      *****/
/************************************************************************/

void            CopyClear::sort_double_0(
    double      *pl,                                // データの左側Ptr
    double      *pr                                 // データの右側Ptr
){
    double      *pi;                                // 内部Ptr:  左
    double      *pj;                                // 内部Ptr:  右
    double      key;                                // 中央の値
    double      w;                                  // 交換用の場所

    pi  = pl;                                       // KeyDataの左側Set
    pj  = pr;                                       // KeyDataの右側Set
    key = *( pi + ( (int)pj - (int)pi )             // 右左の中央値を
                        / ( 2 * sizeof(double) ) ); // セット
    do{                                             // 以下繰り返し
        while( *pi < key ){                         // 左側が小さい間
            pi++;                                   // 左側を中に進める
        }                                           //
        while( key < *pj ){                         // 右側が大きい間
            pj--;                                   // 右側を中に進める
        }                                           //
        if( pi <= pj ){                             // 左 ≦ 右 なら
            w   = *pi;                              // 左右のキーデータ
            *pi = *pj;                              // を交換
            *pj = w;                                // し
            pi++;                                   // 左側を中に進める
            pj--;                                   // 右側を中に進める
        }                                           //
    }while( pi <= pj );                             // 左≦右なら繰返し
    if( pl < pj ){                                  // 外左 < 中右 なら
        sort_double_0( pl, pj );                    // この間をソート
    }                                               //
    if( pi < pr ){                                  // 中左 < 外右 なら
        sort_double_0( pi, pr );                    // この間をソート
    }                                               //
}

☆備考☆この関数はファイル「CopyClear100.cpp」に存在!
★注意★この関数は「private:属性」ですのでライブラリの
外から使用不能です!

(A)関数「sort_double_0();」の【関数名】

「Sort」は、勿論、英単語「sort」、カタカナ語ソート・
ソーティング、詰り並び替えです!
「double」は、倍精度浮動小数型「double型」データを意味
します!
「0」は、昇順にソートする事を意味します!
この関数は、データ配列を昇順≪小さい方から大きい方へ
整列≫にソートする関数
★備考★「_」で区切って居るのは、極初期に作成された
ので区切りに「_」を使用するか、単語先頭「英大文字」と
色々迷って居た時期です!

(B)関数「void sort_double_0();」の【返値】

返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!

(C)関数「sort_double_0()」の【仮引数】

void            CopyClear::sort_double_0(
    double      *pl,                                // データの左側Ptr
    double      *pr                                 // データの右側Ptr
){

「double* pl,」は、データ配列左端「l=left省略」
「double* pr」は、データ配列右端「r=right省略」

(D)関数「sort_double_0()」の【アルゴリズム】

){
    double      *pi;                                // 内部Ptr:  左
    double      *pj;                                // 内部Ptr:  右
    double      key;                                // 中央の値
    double      w;                                  // 交換用の場所

    pi  = pl;                                       // KeyDataの左側Set
    pj  = pr;                                       // KeyDataの右側Set
    key = *( pi + ( (int)pj - (int)pi )             // 右左の中央値を
                        / ( 2 * sizeof(double) ) ); // セット
    do{                                             // 以下繰り返し
        while( *pi < key ){                         // 左側が小さい間
            pi++;                                   // 左側を中に進める
        }                                           //
        while( key < *pj ){                         // 右側が大きい間
            pj--;                                   // 右側を中に進める
        }                                           //
        if( pi <= pj ){                             // 左 ≦ 右 なら
            w   = *pi;                              // 左右のキーデータ
            *pi = *pj;                              // を交換
            *pj = w;                                // し
            pi++;                                   // 左側を中に進める
            pj--;                                   // 右側を中に進める
        }                                           //
    }while( pi <= pj );                             // 左≦右なら繰返し
    if( pl < pj ){                                  // 外左 < 中右 なら
        sort_double_0( pl, pj );                    // この間をソート
    }                                               //
    if( pi < pr ){                                  // 中左 < 外右 なら
        sort_double_0( pi, pr );                    // この間をソート
    }                                               //
}

(D-1)ローカル変数

){
    double      *pi;                                // 内部Ptr:  左
    double      *pj;                                // 内部Ptr:  右
    double      key;                                // 中央の値
    double      w;                                  // 交換用の場所

「double* pi;」は、内部ポインタ(左側用)
「double* pj;」は、内部ポインタ(右側用)
「double key;」は、中央の値(キー比較用)
「double w;」は、データ交換用の場所

(D―2)アルゴリズムコード

    pi  = pl;                                       // KeyDataの左側Set
    pj  = pr;                                       // KeyDataの右側Set
    key = *( pi + ( (int)pj - (int)pi )             // 右左の中央値を
                        / ( 2 * sizeof(double) ) ); // セット
    do{                                             // 以下繰り返し
        while( *pi < key ){                         // 左側が小さい間
            pi++;                                   // 左側を中に進める
        }                                           //
        while( key < *pj ){                         // 右側が大きい間
            pj--;                                   // 右側を中に進める
        }                                           //
        if( pi <= pj ){                             // 左 ≦ 右 なら
            w   = *pi;                              // 左右のキーデータ
            *pi = *pj;                              // を交換
            *pj = w;                                // し
            pi++;                                   // 左側を中に進める
            pj--;                                   // 右側を中に進める
        }                                           //
    }while( pi <= pj );                             // 左≦右なら繰返し
    if( pl < pj ){                                  // 外左 < 中右 なら
        sort_double_0( pl, pj );                    // この間をソート
    }                                               //
    if( pi < pr ){                                  // 中左 < 外右 なら
        sort_double_0( pi, pr );                    // この間をソート
    }                                               //
}

「pi=pl;pj=pr;」は、ローカルな左側・右側をセット
「key=*(pi+((int)pj-(int)pi)/(2*sizeof(double)))」は、
左右の中央の場所(ポインタの中央)の値を取り出す!
二重ループで外側の
do構文「・・外側ループ本体・・}while(pi<=pj);」と
後置ループ条件「pi<=pj」と内部のポインタの左右関係が
保たれている間繰り返す!そして最初の内側のループ
「while(*pi<key){pi++;}」は、while構文で
ループ条件「*pi<key」は、「左側の値が、
比較用の値未満」の間「pi++;」ポインタを右側に移動を
繰り返すと、即ち、「左側がキーの値以上に成るまで繰り
返す」、次の内側ループ
「while(key<*pj){pj--;}」は、「右」側の
値が、比較用の値越え」の間「pj--;」ポインタを左側に
移動を繰り返すと、即ち、「右側がキーの値以下に成るまで
繰り返す」、そしてif構文
「if(pi<=pj){w=*pi;*pi=*pj;*pj=w;pi++;
pj--;}」は、条件「pi<=pj」と左右関係が保たれていたら
「w=*pi;*pi=*pj;*pj=w;pi++;pj--;}」で先ず
「w=*pi;*pi=*pj;*pj=w;」で左右を入れ替え、
「pi++;pj--;」とローカル左右ポインタを進める!
そして「if(pl<pj){sort_double_0(pl,pj);}」で再帰呼び出し
を自分自身「sort_double_0()」関数をサブルーチン関数とし
て条件「pl<pj」=「元々の左側が内部の右側と左右関係が
保たれて居る」なら、再帰呼び出し
「sort_double_0(pl,pj);」を行う事で数学の
「帰納的定義法」と考えて再帰呼び出しを行った部分
「plからpjのポインタの示す左右範囲」が昇順にソート済
みと見なして処理する方法です!★備考★これが再帰呼び出
しを行う事で実現する「クイックソート」と呼ばれる通常の
データでは最速と言われているアルゴリズムです同じ様に
「if(pi<pr){sort_double_0(pi,pr);}」で範囲「piからpr」の
ポインタの示す左右範囲」が昇順にソート済みと見なして
処理します!★備考★これが、再帰呼び出しを行う事で
実現する「クイックソート」と呼ばれる通常のデータでは
最速と言われているアルゴリズムですコレは、多くの画像
処理以外のプログラミングで使用されて居ますので数学的
帰納法をアルゴリズムに応用した事を理解して下さい!
C言語的には「再帰呼び出し」との文言で平気で多用しま
す!

(4-15-133)関数「void sort_double_1(double* pl,
double* pr){・・・}」

/************************************************************************/
/*****      QUIC-SORT:降順ソート:データ=倍精度実数      *****/
/************************************************************************/

void            CopyClear::sort_double_1(
    double      *pl,                                // データの左側Ptr
    double      *pr                                 // データの右側Ptr
){
    double      *pi;                                // 内部Ptr:  左
    double      *pj;                                // 内部Ptr:  右
    double      key;                                // 中央の値
    double      w;                                  // 交換用の場所

    pi  = pl;                                       // KeyDataの左側Set
    pj  = pr;                                       // KeyDataの右側Set
    key = *( pi + ( (int)pj - (int)pi )             // 右左の中央値を
                        / ( 2 * sizeof(double) ) ); // セット
    do{                                             // 以下繰り返し
        while( *pi > key ){                         // 左側が大きい間
            pi++;                                   // 左側を中に進める
        }                                           //
        while( key > *pj ){                         // 右側が小さい間
            pj--;                                   // 右側を中に進める
        }                                           //
        if( pi <= pj ){                             // 左 ≦ 右 なら
            w   = *pi;                              // 左右のキーデータ
            *pi = *pj;                              // を交換
            *pj = w;                                // し
            pi++;                                   // 左側を中に進める
            pj--;                                   // 右側を中に進める
        }                                           //
    }while( pi <= pj );                             // 左≦右なら繰返し
    if( pl < pj ){                                  // 外左 < 中右 なら
        sort_double_1( pl, pj );                    // この間をソート
    }                                               //
    if( pi < pr ){                                  // 中左 < 外右 なら
        sort_double_1( pi, pr );                    // この間をソート
    }                                               //
}

☆備考☆この関数はファイル「CopyClear100.cpp」に存在!
★注意★この関数は「private:属性」ですのでライブラリの
外から使用不能です!

(A)関数「sort_double_1();」の【関数名】

「Sort」は、勿論、英単語「sort」、カタカナ語ソート・
ソーティング、詰り並び替えです!
「double」は、倍精度浮動小数型「double型」データを意味
します!
「1」は、降順にソートする事を意味します!
この関数は、データ配列を降順≪大きい方からへ小さい方に
整列≫にソートする関数
★備考★「_」で区切って居るのは、極初期に作成された
ので区切りに「_」を使用するか、単語先頭「英大文字」と
色々迷って居た時期です!

(B)関数「void sort_double_1();」の【返値】

返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!

(C)関数「sort_double_1()」の【仮引数】

void            CopyClear::sort_double_1(
    double      *pl,                                // データの左側Ptr
    double      *pr                                 // データの右側Ptr
){

「double* pl,」は、データ配列左端「l=left省略」
「double* pr」は、データ配列右端「r=right省略」

(D)関数「sort_double_1()」の【アルゴリズム】

){
    double      *pi;                                // 内部Ptr:  左
    double      *pj;                                // 内部Ptr:  右
    double      key;                                // 中央の値
    double      w;                                  // 交換用の場所

    pi  = pl;                                       // KeyDataの左側Set
    pj  = pr;                                       // KeyDataの右側Set
    key = *( pi + ( (int)pj - (int)pi )             // 右左の中央値を
                        / ( 2 * sizeof(double) ) ); // セット
    do{                                             // 以下繰り返し
        while( *pi > key ){                         // 左側が大きい間
            pi++;                                   // 左側を中に進める
        }                                           //
        while( key > *pj ){                         // 右側が小さい間
            pj--;                                   // 右側を中に進める
        }                                           //
        if( pi <= pj ){                             // 左 ≦ 右 なら
            w   = *pi;                              // 左右のキーデータ
            *pi = *pj;                              // を交換
            *pj = w;                                // し
            pi++;                                   // 左側を中に進める
            pj--;                                   // 右側を中に進める
        }                                           //
    }while( pi <= pj );                             // 左≦右なら繰返し
    if( pl < pj ){                                  // 外左 < 中右 なら
        sort_double_1( pl, pj );                    // この間をソート
    }                                               //
    if( pi < pr ){                                  // 中左 < 外右 なら
        sort_double_1( pi, pr );                    // この間をソート
    }                                               //
}

(D-1)ローカル変数

){
    double      *pi;                                // 内部Ptr:  左
    double      *pj;                                // 内部Ptr:  右
    double      key;                                // 中央の値
    double      w;                                  // 交換用の場所

「double* pi;」は、内部ポインタ(左側用)
「double* pj;」は、内部ポインタ(右側用)
「double key;」は、中央の値(キー比較用)
「double w;」は、データ交換用の場所

(D―2)アルゴリズムコード

    pi  = pl;                                       // KeyDataの左側Set
    pj  = pr;                                       // KeyDataの右側Set
    key = *( pi + ( (int)pj - (int)pi )             // 右左の中央値を
                        / ( 2 * sizeof(double) ) ); // セット
    do{                                             // 以下繰り返し
        while( *pi > key ){                         // 左側が大きい間
            pi++;                                   // 左側を中に進める
        }                                           //
        while( key > *pj ){                         // 右側が小さい間
            pj--;                                   // 右側を中に進める
        }                                           //
        if( pi <= pj ){                             // 左 ≦ 右 なら
            w   = *pi;                              // 左右のキーデータ
            *pi = *pj;                              // を交換
            *pj = w;                                // し
            pi++;                                   // 左側を中に進める
            pj--;                                   // 右側を中に進める
        }                                           //
    }while( pi <= pj );                             // 左≦右なら繰返し
    if( pl < pj ){                                  // 外左 < 中右 なら
        sort_double_1( pl, pj );                    // この間をソート
    }                                               //
    if( pi < pr ){                                  // 中左 < 外右 なら
        sort_double_1( pi, pr );                    // この間をソート
    }                                               //
}

「pi=pl;pj=pr;」は、ローカルな左側・右側をセット
「key=*(pi+((int)pj-(int)pi)/(2*sizeof(double)))」は、
左右の中央の場所(ポインタの中央)の値を取り出す!
二重ループで外側の
do構文「・・外側ループ本体・・}while(pi<=pj);」と
後置ループ条件「pi<=pj」と内部のポインタの左右関係が
保たれている間繰り返す!そして最初の内側のループ
「while(*pi>key){pi++;}」は、while構文で
ループ条件「*pi>key」は、「左側の値が、
比較用の値越え」の間「pi++;」ポインタを右側に移動を
繰り返すと、即ち、「左側がキーの値以下に成るまで繰り
返す」、次の内側ループ
「while(key>*pj){pj--;}」は、「右」側の
値が、比較用の値未満」の間「pj--;」ポインタを左側に
移動を繰り返すと、即ち、「右側がキーの値以上に成るまで
繰り返す」、そしてif構文
「if(pi<=pj){w=*pi;*pi=*pj;*pj=w;pi++;
pj--;}」は、条件「pi<=pj」と左右関係が保たれていたら
「w=*pi;*pi=*pj;*pj=w;pi++;pj--;}」で先ず
「w=*pi;*pi=*pj;*pj=w;」で左右を入れ替え、
「pi++;pj--;」とローカル左右ポインタを進める!
そして「if(pl<pj){sort_double_1(pl,pj);}」で再帰呼び出し
を自分自身「sort_double_1()」関数をサブルーチン関数とし
て条件「pl<pj」=「元々の左側が内部の右側と左右関係が
保たれて居る」なら、再帰呼び出し
「sort_double_1(pl,pj);」を行う事で数学の
「帰納的定義法」と考えて再帰呼び出しを行った部分
「plからpjのポインタの示す左右範囲」が降順にソート済
みと見なして処理する方法です!★備考★これが再帰呼び出
しを行う事で実現する「クイックソート」と呼ばれる通常の
データでは最速と言われているアルゴリズムです同じ様に
「if(pi<pr){sort_double_1(pi,pr);}」で範囲「piからpr」の
ポインタの示す左右範囲」が降順にソート済みと見なして
処理します!★備考★これが、再帰呼び出しを行う事で
実現する「クイックソート」と呼ばれる通常のデータでは
最速と言われているアルゴリズムですコレは、多くの画像
処理以外のプログラミングで使用されて居ますので数学的
帰納法をアルゴリズムに応用した事を理解して下さい!
C言語的には「再帰呼び出し」との文言で平気で多用しま
す!

(4-15-134)関数「void sort_double_0_key(
double* pl,double* pr,
short* plx,short* prx){・・・}」

/************************************************************************/
/*****  QUIC-SORT:昇順ソート:キー=倍精度、添字=16      *****/
/************************************************************************/

void            CopyClear::sort_double_0_key(
    double      *pl,                                // KeyDataの左側Ptr
    double      *pr,                                // KeyDataの右側Ptr
    short       *plx,                               // 添字Data左側Ptr
    short       *prx                                // 添字Data右側Ptr
){
    double      *pi;                                // 内部KeyPtr:  左
    double      *pj;                                // 内部KeyPtr:  右
    short       *pix;                               // 内部添字Ptr:左
    short       *pjx;                               // 内部添字Ptr:右
    double      key;                                // 中央の値
    double      w;                                  // 交換用の場所:キー
    short       wx;                                 // 交換用の場所:添字

    pi  = pl;                                       // KeyDataの左側Set
    pj  = pr;                                       // KeyDataの右側Set
    pix = plx;                                      // 添字左側をSet
    pjx = prx;                                      // 添字右側をSet
    key = *( pi + ( (int)pj - (int)pi )             // 右左の中央値を
                        / ( 2 * sizeof(double) ) ); // セット
    do{                                             // 以下繰り返し
        while( *pi < key ){                         // 左側が小さい間
            pi++;                                   // 左側を中に進める
            pix++;                                  // 添字部も進める
        }                                           //
        while( key < *pj ){                         // 右側が大きい間
            pj--;                                   // 右側を中に進める
            pjx--;                                  // 添字部も進める
        }                                           //
        if( pi <= pj ){                             // 左 ≦ 右 なら
            w   = *pi;                              // 左右のキーデータ
            *pi = *pj;                              // を交換
            *pj = w;                                // し
            pi++;                                   // 左側を中に進める
            pj--;                                   // 右側を中に進める
            wx   = *pix;                            // 左右の添字データ
            *pix = *pjx;                            // を交換
            *pjx = wx;                              // し
            pix++;                                  // 左側を中に進める
            pjx--;                                  // 右側を中に進める
        }                                           //
    }while( pi <= pj );                             // 左≦右なら繰返し
    if( pl < pj ){                                  // 外左 < 中右 なら
        sort_double_0_key( pl, pj, plx, pjx );      // この間をソート
    }                                               //
    if( pi < pr ){                                  // 中左 < 外右 なら
        sort_double_0_key( pi, pr, pix, prx );      // この間をソート
    }                                               //
}

☆備考☆この関数はファイル「CopyClear100.cpp」に存在!
★注意★この関数は「private:属性」ですのでライブラリの
外から使用不能です!

(A)関数「sort_double_0_key();」の【関数名】

「Sort」は、勿論、英単語「sort」、カタカナ語ソート・
ソーティング、詰り並び替えです!
「double」は、倍精度浮動小数型「double型」データを意味
します!
「0」は、昇順にソートする事を意味します!
「key」は、キー付きを意味し、連動して連動配列も中身の
入れ替えを行う事を意味します!
この関数は、データ配列を昇順≪小さい方から大きい方へ
整列≫にソートする関数でインデックス配列も連動して作成
★備考★「_」で区切って居るのは、極初期に作成された
ので区切りに「_」を使用するか、単語先頭「英大文字」と
色々迷って居た時期です!

(B)関数「void sort_double_0_key();」の【返値】

返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!

(C)関数「sort_double_0_key()」の【仮引数】

void            CopyClear::sort_double_0_key(
    double      *pl,                                // KeyDataの左側Ptr
    double      *pr,                                // KeyDataの右側Ptr
    short       *plx,                               // 添字Data左側Ptr
    short       *prx                                // 添字Data右側Ptr
){

「double* pl,」は、データ配列左端「l=left省略」
「double* pr」は、データ配列右端「r=right省略」
「short* plx,」は、連動配列配列左端
「short* prx」は、連動配列配列左端
★備考★上記「double* pl,double* pr」をソート対象キー配列
として、ここ「short* plx,short* prx」は、連動して入れ
替えられる配列

(D)関数「sort_double_0_key()」の【アルゴリズム】

){
    double      *pi;                                // 内部KeyPtr:  左
    double      *pj;                                // 内部KeyPtr:  右
    short       *pix;                               // 内部添字Ptr:左
    short       *pjx;                               // 内部添字Ptr:右
    double      key;                                // 中央の値
    double      w;                                  // 交換用の場所:キー
    short       wx;                                 // 交換用の場所:添字

    pi  = pl;                                       // KeyDataの左側Set
    pj  = pr;                                       // KeyDataの右側Set
    pix = plx;                                      // 添字左側をSet
    pjx = prx;                                      // 添字右側をSet
    key = *( pi + ( (int)pj - (int)pi )             // 右左の中央値を
                        / ( 2 * sizeof(double) ) ); // セット
    do{                                             // 以下繰り返し
        while( *pi < key ){                         // 左側が小さい間
            pi++;                                   // 左側を中に進める
            pix++;                                  // 添字部も進める
        }                                           //
        while( key < *pj ){                         // 右側が大きい間
            pj--;                                   // 右側を中に進める
            pjx--;                                  // 添字部も進める
        }                                           //
        if( pi <= pj ){                             // 左 ≦ 右 なら
            w   = *pi;                              // 左右のキーデータ
            *pi = *pj;                              // を交換
            *pj = w;                                // し
            pi++;                                   // 左側を中に進める
            pj--;                                   // 右側を中に進める
            wx   = *pix;                            // 左右の添字データ
            *pix = *pjx;                            // を交換
            *pjx = wx;                              // し
            pix++;                                  // 左側を中に進める
            pjx--;                                  // 右側を中に進める
        }                                           //
    }while( pi <= pj );                             // 左≦右なら繰返し
    if( pl < pj ){                                  // 外左 < 中右 なら
        sort_double_0_key( pl, pj, plx, pjx );      // この間をソート
    }                                               //
    if( pi < pr ){                                  // 中左 < 外右 なら
        sort_double_0_key( pi, pr, pix, prx );      // この間をソート
    }                                               //
}

(D-1)ローカル変数

){
    double      *pi;                                // 内部KeyPtr:  左
    double      *pj;                                // 内部KeyPtr:  右
    short       *pix;                               // 内部添字Ptr:左
    short       *pjx;                               // 内部添字Ptr:右
    double      key;                                // 中央の値
    double      w;                                  // 交換用の場所:キー
    short       wx;                                 // 交換用の場所:添字

「double* pi;」は、内部ポインタ(左側用)キー
「double* pj;」は、内部ポインタ(右側用)キー
「short* pix;」は、内部ポインタ(左側用)連動
「short* pjx;」は、内部ポインタ(右側用)連動
「double key;」は、中央の値(キー比較用)
「double w;」は、データ交換用の場所
「short wx;」は、データ交換用の場所連動

(D―2)アルゴリズムコード

    pi  = pl;                                       // KeyDataの左側Set
    pj  = pr;                                       // KeyDataの右側Set
    pix = plx;                                      // 添字左側をSet
    pjx = prx;                                      // 添字右側をSet
    key = *( pi + ( (int)pj - (int)pi )             // 右左の中央値を
                        / ( 2 * sizeof(double) ) ); // セット
    do{                                             // 以下繰り返し
        while( *pi < key ){                         // 左側が小さい間
            pi++;                                   // 左側を中に進める
            pix++;                                  // 添字部も進める
        }                                           //
        while( key < *pj ){                         // 右側が大きい間
            pj--;                                   // 右側を中に進める
            pjx--;                                  // 添字部も進める
        }                                           //
        if( pi <= pj ){                             // 左 ≦ 右 なら
            w   = *pi;                              // 左右のキーデータ
            *pi = *pj;                              // を交換
            *pj = w;                                // し
            pi++;                                   // 左側を中に進める
            pj--;                                   // 右側を中に進める
            wx   = *pix;                            // 左右の添字データ
            *pix = *pjx;                            // を交換
            *pjx = wx;                              // し
            pix++;                                  // 左側を中に進める
            pjx--;                                  // 右側を中に進める
        }                                           //
    }while( pi <= pj );                             // 左≦右なら繰返し
    if( pl < pj ){                                  // 外左 < 中右 なら
        sort_double_0_key( pl, pj, plx, pjx );      // この間をソート
    }                                               //
    if( pi < pr ){                                  // 中左 < 外右 なら
        sort_double_0_key( pi, pr, pix, prx );      // この間をソート
    }                                               //
}

「pi=pl;pj=pr;」は、ローカルな左側・右側をセット
「pix=plx;pjx=prx;」は、ローカルな左側・右側をセット
「key=*(pi+((int)pj-(int)pi)/(2*sizeof(double)))」は、
左右の中央の場所(ポインタの中央)の値を取り出す!
二重ループで外側の
do構文「・・外側ループ本体・・}while(pi<=pj);」と
後置ループ条件「pi<=pj」と内部のポインタの左右関係が
保たれている間繰り返す!そして最初の内側のループ
「while(*pi<key){pi++;pix++;}」は、while構文で
ループ条件「*pi<key」は、「左側の値が、比較用の値未満
」の間「pi++;pix++;」ポインタを右側に移動を繰り返すと
即ち、「左側がキーの値以上に成るまで繰り返す」、
次の内側ループ
「while(key<*pj){pj--;pjx--;}」は、「右」側の値が、
比較用の値越え」の間「pj--;pjx--;」ポインタを左側に
移動を繰り返すと、即ち、「右側がキーの値以下に成るまで
繰り返す」、そしてif構文
「if(pi<=pj){w=*pi;*pi=*pj;*pj=w;pi++;
pj--;wx=*pix;*pix=*pjx;*pjx=wx;pix++;pjx--;}」は、
条件「pi<=pj」と左右関係が保たれていたら
「w=*pi;*pi=*pj;*pj=w;pi++;pj--;wx=*pix;
*pix=*pjx;*pjx=wx;pix++;pjx--;
wx=*pix;*pix=*pjx;*pjx=wx;pix++;pjx--;}」で先ず
「w=*pi;*pi=*pj;*pj=w;」でキーデータ左右を入れ替え、
「pi++;pj--;」とローカル左右ポインタを進める!
そして連動配列の入れ替えとして
「wx=*pix;*pix=*pjx;*pjx=wx;pix++;pjx--;」と配列入れ
替えを行い!「do構文」を終えると!
そして「if(pl<pj){sort_double_0_key(pl,pj,plx,pjx);}」
で再帰呼び出しを自分自身「sort_double_0_key()」関数を
サブルーチン関数として条件「pl<pj」=「元々の左側が
内部の右側と左右関係が保たれて居る」なら、再帰呼び出し
「sort_double_0_key(pl,pj,plx,pjx);」を行う事で数学の
「帰納的定義法」と考えて再帰呼び出しを行った部分
「plからpjのポインタの示す左右範囲」が昇順にソート済
みと見なして処理する方法です!★備考★これが再帰呼び出
しを行う事で実現する「クイックソート」と呼ばれる通常の
データでは最速と言われているアルゴリズムです同じ様に
「if(pi<pr){sort_double_0_key(pi,pr,pix,prx);}」で範囲
「piからpr」のポインタの示す左右範囲」が昇順にソート
済みと見なして処理します!★備考★これが、再帰呼び出し
を行う事で実現する「クイックソート」と呼ばれる通常の
データでは最速と言われているアルゴリズムですコレは、
多くの画像処理以外のプログラミングで使用されて居ますの
で数学的帰納法をアルゴリズムに応用した事を理解して下さ
い!C言語的には「再帰呼び出し」との文言で平気で多用し
ます!

(4-15-135)関数「void sort_double_1_key(
double* pl,double* pr,
short* plx,short* prx){・・・}」

/************************************************************************/
/*****  QUIC-SORT:降順ソート:キー=倍精度、添字1=16    *****/
/************************************************************************/

void            CopyClear::sort_double_1_key(
    double      *pl,                                // KeyDataの左側Ptr
    double      *pr,                                // KeyDataの右側Ptr
    short       *plx,                               // 添字Data左側Ptr
    short       *prx                                // 添字Data右側Ptr
){
    double      *pi;                                // 内部KeyPtr:  左
    double      *pj;                                // 内部KeyPtr:  右
    short       *pix;                               // 内部添字Ptr:左
    short       *pjx;                               // 内部添字Ptr:右
    double      key;                                // 中央の値
    double      w;                                  // 交換用の場所:キー
    short       wx;                                 // 交換用の場所:添字

    pi  = pl;                                       // KeyDataの左側Set
    pj  = pr;                                       // KeyDataの右側Set
    pix = plx;                                      // 添字左側をSet
    pjx = prx;                                      // 添字右側をSet
    key = *( pi + ( (int)pj - (int)pi )             // 右左の中央値を
                        / ( 2 * sizeof(double) ) ); // セット
    do{                                             // 以下繰り返し
        while( *pi > key ){                         // 左側が大きい間
            pi++;                                   // 左側を中に進める
            pix++;                                  // 添字部も進める
        }                                           //
        while( key > *pj ){                         // 右側が小さい間
            pj--;                                   // 右側を中に進める
            pjx--;                                  // 添字部も進める
        }                                           //
        if( pi <= pj ){                             // 左 ≦ 右 なら
            w   = *pi;                              // 左右のキーデータ
            *pi = *pj;                              // を交換
            *pj = w;                                // し
            pi++;                                   // 左側を中に進める
            pj--;                                   // 右側を中に進める
            wx   = *pix;                            // 左右の添字データ
            *pix = *pjx;                            // を交換
            *pjx = wx;                              // し
            pix++;                                  // 左側を中に進める
            pjx--;                                  // 右側を中に進める
        }                                           //
    }while( pi <= pj );                             // 左≦右なら繰返し
    if( pl < pj ){                                  // 外左 < 中右 なら
        sort_double_1_key( pl, pj, plx, pjx );      // この間をソート
    }                                               //
    if( pi < pr ){                                  // 中左 < 外右 なら
        sort_double_1_key( pi, pr, pix, prx );      // この間をソート
    }                                               //
}

☆備考☆この関数はファイル「CopyClear100.cpp」に存在!
★注意★この関数は「private:属性」ですのでライブラリの
外から使用不能です!

(A)関数「sort_double_1_key();」の【関数名】

「Sort」は、勿論、英単語「sort」、カタカナ語ソート・
ソーティング、詰り並び替えです!
「double」は、倍精度浮動小数型「double型」データを意味
します!
「1」は、降順にソートする事を意味します!
この関数は、データ配列を降順≪大きい方からへ小さい方に
整列≫にソートする関数
「key」は、キー付きを意味し、連動して連動配列も中身の
入れ替えを行う事を意味します!
この関数は、データ配列を降順≪大きい方からへ小さい方に
整列≫にソートする関数でインデックス配列も連動して作成
★備考★「_」で区切って居るのは、極初期に作成された
ので区切りに「_」を使用するか、単語先頭「英大文字」と
色々迷って居た時期です!

(B)関数「void sort_double_1_key();」の【返値】

返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!

(C)関数「sort_double_1_key()」の【仮引数】

void            CopyClear::sort_double_1_key(
    double      *pl,                                // KeyDataの左側Ptr
    double      *pr,                                // KeyDataの右側Ptr
    short       *plx,                               // 添字Data左側Ptr
    short       *prx                                // 添字Data右側Ptr
){

「double* pl,」は、データ配列左端「l=left省略」
「double* pr」は、データ配列右端「r=right省略」
「short* plx,」は、連動配列配列左端
「short* prx」は、連動配列配列左端
★備考★上記「double* pl,double* pr」をソート対象キー配列
として、ここ「short* plx,short* prx」は、連動して入れ
替えられる配列

(D)関数「sort_double_1_key()」の【アルゴリズム】

){
    double      *pi;                                // 内部KeyPtr:  左
    double      *pj;                                // 内部KeyPtr:  右
    short       *pix;                               // 内部添字Ptr:左
    short       *pjx;                               // 内部添字Ptr:右
    double      key;                                // 中央の値
    double      w;                                  // 交換用の場所:キー
    short       wx;                                 // 交換用の場所:添字

    pi  = pl;                                       // KeyDataの左側Set
    pj  = pr;                                       // KeyDataの右側Set
    pix = plx;                                      // 添字左側をSet
    pjx = prx;                                      // 添字右側をSet
    key = *( pi + ( (int)pj - (int)pi )             // 右左の中央値を
                        / ( 2 * sizeof(double) ) ); // セット
    do{                                             // 以下繰り返し
        while( *pi > key ){                         // 左側が大きい間
            pi++;                                   // 左側を中に進める
            pix++;                                  // 添字部も進める
        }                                           //
        while( key > *pj ){                         // 右側が小さい間
            pj--;                                   // 右側を中に進める
            pjx--;                                  // 添字部も進める
        }                                           //
        if( pi <= pj ){                             // 左 ≦ 右 なら
            w   = *pi;                              // 左右のキーデータ
            *pi = *pj;                              // を交換
            *pj = w;                                // し
            pi++;                                   // 左側を中に進める
            pj--;                                   // 右側を中に進める
            wx   = *pix;                            // 左右の添字データ
            *pix = *pjx;                            // を交換
            *pjx = wx;                              // し
            pix++;                                  // 左側を中に進める
            pjx--;                                  // 右側を中に進める
        }                                           //
    }while( pi <= pj );                             // 左≦右なら繰返し
    if( pl < pj ){                                  // 外左 < 中右 なら
        sort_double_1_key( pl, pj, plx, pjx );      // この間をソート
    }                                               //
    if( pi < pr ){                                  // 中左 < 外右 なら
        sort_double_1_key( pi, pr, pix, prx );      // この間をソート
    }                                               //
}

(D-1)ローカル変数

){
    double      *pi;                                // 内部KeyPtr:  左
    double      *pj;                                // 内部KeyPtr:  右
    short       *pix;                               // 内部添字Ptr:左
    short       *pjx;                               // 内部添字Ptr:右
    double      key;                                // 中央の値
    double      w;                                  // 交換用の場所:キー
    short       wx;                                 // 交換用の場所:添字

「double* pi;」は、内部ポインタ(左側用)キー
「double* pj;」は、内部ポインタ(右側用)キー
「short* pix;」は、内部ポインタ(左側用)連動
「short* pjx;」は、内部ポインタ(右側用)連動
「double key;」は、中央の値(キー比較用)
「double w;」は、データ交換用の場所
「short wx;」は、データ交換用の場所連動

(D―2)アルゴリズムコード

    pi  = pl;                                       // KeyDataの左側Set
    pj  = pr;                                       // KeyDataの右側Set
    pix = plx;                                      // 添字左側をSet
    pjx = prx;                                      // 添字右側をSet
    key = *( pi + ( (int)pj - (int)pi )             // 右左の中央値を
                        / ( 2 * sizeof(double) ) ); // セット
    do{                                             // 以下繰り返し
        while( *pi > key ){                         // 左側が大きい間
            pi++;                                   // 左側を中に進める
            pix++;                                  // 添字部も進める
        }                                           //
        while( key > *pj ){                         // 右側が小さい間
            pj--;                                   // 右側を中に進める
            pjx--;                                  // 添字部も進める
        }                                           //
        if( pi <= pj ){                             // 左 ≦ 右 なら
            w   = *pi;                              // 左右のキーデータ
            *pi = *pj;                              // を交換
            *pj = w;                                // し
            pi++;                                   // 左側を中に進める
            pj--;                                   // 右側を中に進める
            wx   = *pix;                            // 左右の添字データ
            *pix = *pjx;                            // を交換
            *pjx = wx;                              // し
            pix++;                                  // 左側を中に進める
            pjx--;                                  // 右側を中に進める
        }                                           //
    }while( pi <= pj );                             // 左≦右なら繰返し
    if( pl < pj ){                                  // 外左 < 中右 なら
        sort_double_1_key( pl, pj, plx, pjx );      // この間をソート
    }                                               //
    if( pi < pr ){                                  // 中左 < 外右 なら
        sort_double_1_key( pi, pr, pix, prx );      // この間をソート
    }                                               //
}

「pi=pl;pj=pr;」は、ローカルな左側・右側をセット
「pix=plx;pjx=prx;」は、ローカルな左側・右側をセット
「key=*(pi+((int)pj-(int)pi)/(2*sizeof(double)))」は、
左右の中央の場所(ポインタの中央)の値を取り出す!
二重ループで外側の
do構文「・・外側ループ本体・・}while(pi<=pj);」と
後置ループ条件「pi<=pj」と内部のポインタの左右関係が
保たれている間繰り返す!そして最初の内側のループ
「while(*pi>key){pi++;pix++;}」は、while構文で
ループ条件「*pi>key」は、「左側の値が、比較用の値未満
」の間「pi++;pix++;」ポインタを右側に移動を繰り返すと
即ち、「左側がキーの値以上に成るまで繰り返す」、
次の内側ループ
「while(key>*pj){pj--;pjx--;}」は、「右」側の値が、
比較用の値未満」の間「pj--;pjx--;」ポインタを左側に
移動を繰り返すと、即ち、「右側がキーの値以上に成るまで
繰り返す」、
そしてif構文
「if(pi<=pj){w=*pi;*pi=*pj;*pj=w;pi++;
pj--;wx=*pix;*pix=*pjx;*pjx=wx;pix++;pjx--;}」は、
条件「pi<=pj」と左右関係が保たれていたら
「w=*pi;*pi=*pj;*pj=w;pi++;pj--;wx=*pix;
*pix=*pjx;*pjx=wx;pix++;pjx--;
wx=*pix;*pix=*pjx;*pjx=wx;pix++;pjx--;}」で先ず
「w=*pi;*pi=*pj;*pj=w;」でキーデータ左右を入れ替え、
「pi++;pj--;」とローカル左右ポインタを進める!
そして連動配列の入れ替えとして
「wx=*pix;*pix=*pjx;*pjx=wx;pix++;pjx--;」と配列入れ
替えを行い!「do構文」を終えると!
そして「if(pl<pj){sort_double_1_key(pl,pj,plx,pjx);}」
で再帰呼び出しを自分自身「sort_double_1_key()」関数を
サブルーチン関数として条件「pl<pj」=「元々の左側が
内部の右側と左右関係が保たれて居る」なら、再帰呼び出し
「sort_double_1_key(pl,pj,plx,pjx);」を行う事で数学の
「帰納的定義法」と考えて再帰呼び出しを行った部分
「plからpjのポインタの示す左右範囲」が降順にソート済
みと見なして処理する方法です!★備考★これが再帰呼び出
しを行う事で実現する「クイックソート」と呼ばれる通常の
データでは最速と言われているアルゴリズムです同じ様に
「if(pi<pr){sort_double_1_key(pi,pr,pix,prx);}」で範囲
「piからpr」のポインタの示す左右範囲」が降順にソート
済みと見なして処理します!★備考★これが、再帰呼び出し
を行う事で実現する「クイックソート」と呼ばれる通常の
データでは最速と言われているアルゴリズムですコレは、
多くの画像処理以外のプログラミングで使用されて居ますの
で数学的帰納法をアルゴリズムに応用した事を理解して下さ
い!C言語的には「再帰呼び出し」との文言で平気で多用し
ます!

(4-15-136)関数「void sort_int64_0(__int64* pl,
__int64* pr){・・・}」

/************************************************************************/
/*****      QUIC-SORT:昇順ソート:データ=64Bit整数       *****/
/************************************************************************/

void            CopyClear::sort_int64_0(
    __int64     *pl,                                // データの左側Ptr
    __int64     *pr                                 // データの右側Ptr
){
    __int64     *pi;                                // 内部Ptr:  左
    __int64     *pj;                                // 内部Ptr:  右
    __int64     key;                                // 中央の値
    __int64     w;                                  // 交換用の場所

    pi  = pl;                                       // KeyDataの左側Set
    pj  = pr;                                       // KeyDataの右側Set
    key = *( pi + ( (int)pj - (int)pi )             // 右左の中央値を
                    / ( 2 * sizeof(__int64) ) );    // セット
    do{                                             // 以下繰り返し
        while( *pi < key ){                         // 左側が小さい間
            pi++;                                   // 左側を中に進める
        }                                           //
        while( key < *pj ){                         // 右側が大きい間
            pj--;                                   // 右側を中に進める
        }                                           //
        if( pi <= pj ){                             // 左 ≦ 右 なら
            w   = *pi;                              // 左右のキーデータ
            *pi = *pj;                              // を交換
            *pj = w;                                // し
            pi++;                                   // 左側を中に進める
            pj--;                                   // 右側を中に進める
        }                                           //
    }while( pi <= pj );                             // 左≦右なら繰返し
    if( pl < pj ){                                  // 外左 < 中右 なら
        sort_int64_0( pl, pj );                     // この間をソート
    }                                               //
    if( pi < pr ){                                  // 中左 < 外右 なら
        sort_int64_0( pi, pr );                     // この間をソート
    }                                               //
}

☆備考☆この関数はファイル「CopyClear100.cpp」に存在!
★注意★この関数は「private:属性」ですのでライブラリの
外から使用不能です!

(A)関数「sort_int64_0();」の【関数名】

「Sort」は、勿論、英単語「sort」、カタカナ語ソート・
ソーティング、詰り並び替えです!
「__int64」は、8バイト整数型「__int64型」データを意味
します!
「0」は、昇順にソートする事を意味します!
この関数は、データ配列を昇順≪小さい方から大きい方へ
整列≫にソートする関数
★備考★「_」で区切って居るのは、極初期に作成された
ので区切りに「_」を使用するか、単語先頭「英大文字」と
色々迷って居た時期です!

(B)関数「void sort_int64_0();」の【返値】

返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!

(C)関数「sort_int64_0()」の【仮引数】

void            CopyClear::sort_int64_0(
    __int64     *pl,                                // データの左側Ptr
    __int64     *pr                                 // データの右側Ptr
){

「__int64* pl,」は、データ配列左端「l=left省略」
「__int64* pr」は、データ配列右端「r=right省略」

(D)関数「sort_int64_0()」の【アルゴリズム】

){
    __int64     *pi;                                // 内部Ptr:  左
    __int64     *pj;                                // 内部Ptr:  右
    __int64     key;                                // 中央の値
    __int64     w;                                  // 交換用の場所

    pi  = pl;                                       // KeyDataの左側Set
    pj  = pr;                                       // KeyDataの右側Set
    key = *( pi + ( (int)pj - (int)pi )             // 右左の中央値を
                    / ( 2 * sizeof(__int64) ) );    // セット
    do{                                             // 以下繰り返し
        while( *pi < key ){                         // 左側が小さい間
            pi++;                                   // 左側を中に進める
        }                                           //
        while( key < *pj ){                         // 右側が大きい間
            pj--;                                   // 右側を中に進める
        }                                           //
        if( pi <= pj ){                             // 左 ≦ 右 なら
            w   = *pi;                              // 左右のキーデータ
            *pi = *pj;                              // を交換
            *pj = w;                                // し
            pi++;                                   // 左側を中に進める
            pj--;                                   // 右側を中に進める
        }                                           //
    }while( pi <= pj );                             // 左≦右なら繰返し
    if( pl < pj ){                                  // 外左 < 中右 なら
        sort_int64_0( pl, pj );                     // この間をソート
    }                                               //
    if( pi < pr ){                                  // 中左 < 外右 なら
        sort_int64_0( pi, pr );                     // この間をソート
    }                                               //
}

(D-1)ローカル変数

){
    __int64     *pi;                                // 内部Ptr:  左
    __int64     *pj;                                // 内部Ptr:  右
    __int64     key;                                // 中央の値
    __int64     w;                                  // 交換用の場所

「__int64* pi;」は、内部ポインタ(左側用)
「__int64* pj;」は、内部ポインタ(右側用)
「__int64 key;」は、中央の値(キー比較用)
「__int64 w;」は、データ交換用の場所

(D―2)アルゴリズムコード

    pi  = pl;                                       // KeyDataの左側Set
    pj  = pr;                                       // KeyDataの右側Set
    key = *( pi + ( (int)pj - (int)pi )             // 右左の中央値を
                    / ( 2 * sizeof(__int64) ) );    // セット
    do{                                             // 以下繰り返し
        while( *pi < key ){                         // 左側が小さい間
            pi++;                                   // 左側を中に進める
        }                                           //
        while( key < *pj ){                         // 右側が大きい間
            pj--;                                   // 右側を中に進める
        }                                           //
        if( pi <= pj ){                             // 左 ≦ 右 なら
            w   = *pi;                              // 左右のキーデータ
            *pi = *pj;                              // を交換
            *pj = w;                                // し
            pi++;                                   // 左側を中に進める
            pj--;                                   // 右側を中に進める
        }                                           //
    }while( pi <= pj );                             // 左≦右なら繰返し
    if( pl < pj ){                                  // 外左 < 中右 なら
        sort_int64_0( pl, pj );                     // この間をソート
    }                                               //
    if( pi < pr ){                                  // 中左 < 外右 なら
        sort_int64_0( pi, pr );                     // この間をソート
    }                                               //
}

「pi=pl;pj=pr;」は、ローカルな左側・右側をセット
「key=*(pi+((int)pj-(int)pi)/(2*sizeof(__int64)))」は、
左右の中央の場所(ポインタの中央)の値を取り出す!
二重ループで外側の
do構文「・・外側ループ本体・・}while(pi<=pj);」と
後置ループ条件「pi<=pj」と内部のポインタの左右関係が
保たれている間繰り返す!そして最初の内側のループ
「while(*pi<key){pi++;}」は、while構文で
ループ条件「*pi<key」は、「左側の値が、
比較用の値未満」の間「pi++;」ポインタを右側に移動を
繰り返すと、即ち、「左側がキーの値以上に成るまで繰り
返す」、次の内側ループ
「while(key<*pj){pj--;}」は、「右」側の
値が、比較用の値越え」の間「pj--;」ポインタを左側に
移動を繰り返すと、即ち、「右側がキーの値以下に成るまで
繰り返す」、そしてif構文
「if(pi<=pj){w=*pi;*pi=*pj;*pj=w;pi++;
pj--;}」は、条件「pi<=pj」と左右関係が保たれていたら
「w=*pi;*pi=*pj;*pj=w;pi++;pj--;}」で先ず
「w=*pi;*pi=*pj;*pj=w;」で左右を入れ替え、
「pi++;pj--;」とローカル左右ポインタを進める!
そして「if(pl<pj){sort_int64_0(pl,pj);}」で再帰呼び出し
を自分自身「sort_int64_0()」関数をサブルーチン関数とし
て条件「pl<pj」=「元々の左側が内部の右側と左右関係が
保たれて居る」なら、再帰呼び出し
「sort_int64_0(pl,pj);」を行う事で数学の
「帰納的定義法」と考えて再帰呼び出しを行った部分
「plからpjのポインタの示す左右範囲」が昇順にソート済
みと見なして処理する方法です!★備考★これが再帰呼び出
しを行う事で実現する「クイックソート」と呼ばれる通常の
データでは最速と言われているアルゴリズムです同じ様に
「if(pi<pr){sort_int64_0(pi,pr);}」で範囲「piからpr」の
ポインタの示す左右範囲」が昇順にソート済みと見なして
処理します!★備考★これが、再帰呼び出しを行う事で
実現する「クイックソート」と呼ばれる通常のデータでは
最速と言われているアルゴリズムですコレは、多くの画像
処理以外のプログラミングで使用されて居ますので数学的
帰納法をアルゴリズムに応用した事を理解して下さい!
C言語的には「再帰呼び出し」との文言で平気で多用しま
す!

(4-15-137)関数「void sort_int64_1(__int64* pl,
__int64* pr){・・・}」

/************************************************************************/
/*****      QUIC-SORT:降順ソート:データ=64Bit整数       *****/
/************************************************************************/

void            CopyClear::sort_int64_1(
    __int64     *pl,                                // データの左側Ptr
    __int64     *pr                                 // データの右側Ptr
){
    __int64     *pi;                                // 内部Ptr:  左
    __int64     *pj;                                // 内部Ptr:  右
    __int64     key;                                // 中央の値
    __int64     w;                                  // 交換用の場所

    pi  = pl;                                       // KeyDataの左側Set
    pj  = pr;                                       // KeyDataの右側Set
    key = *( pi + ( (int)pj - (int)pi )             // 右左の中央値を
                    / ( 2 * sizeof(__int64) ) );    // セット
    do{                                             // 以下繰り返し
        while( *pi > key ){                         // 左側が大きい間
            pi++;                                   // 左側を中に進める
        }                                           //
        while( key > *pj ){                         // 右側が小さい間
            pj--;                                   // 右側を中に進める
        }                                           //
        if( pi <= pj ){                             // 左 ≦ 右 なら
            w   = *pi;                              // 左右のキーデータ
            *pi = *pj;                              // を交換
            *pj = w;                                // し
            pi++;                                   // 左側を中に進める
            pj--;                                   // 右側を中に進める
        }                                           //
    }while( pi <= pj );                             // 左≦右なら繰返し
    if( pl < pj ){                                  // 外左 < 中右 なら
        sort_int64_1( pl, pj );                     // この間をソート
    }                                               //
    if( pi < pr ){                                  // 中左 < 外右 なら
        sort_int64_1( pi, pr );                     // この間をソート
    }                                               //
}

☆備考☆この関数はファイル「CopyClear100.cpp」に存在!
★注意★この関数は「private:属性」ですのでライブラリの
外から使用不能です!

(A)関数「sort_int64_1();」の【関数名】

「Sort」は、勿論、英単語「sort」、カタカナ語ソート・
ソーティング、詰り並び替えです!
「__int64」は、8バイト整数型「__int64型」データを意味
します!
「1」は、降順にソートする事を意味します!
この関数は、データ配列を降順≪大きい方からへ小さい方に
整列≫にソートする関数
★備考★「_」で区切って居るのは、極初期に作成された
ので区切りに「_」を使用するか、単語先頭「英大文字」と
色々迷って居た時期です!

(B)関数「void sort_int64_1();」の【返値】

返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!

(C)関数「sort_int64_1()」の【仮引数】

void            CopyClear::sort_int64_1(
    __int64     *pl,                                // データの左側Ptr
    __int64     *pr                                 // データの右側Ptr
){

「__int64* pl,」は、データ配列左端「l=left省略」
「__int64* pr」は、データ配列右端「r=right省略」

(D)関数「sort_int64_1()」の【アルゴリズム】

){
    __int64     *pi;                                // 内部Ptr:  左
    __int64     *pj;                                // 内部Ptr:  右
    __int64     key;                                // 中央の値
    __int64     w;                                  // 交換用の場所

    pi  = pl;                                       // KeyDataの左側Set
    pj  = pr;                                       // KeyDataの右側Set
    key = *( pi + ( (int)pj - (int)pi )             // 右左の中央値を
                    / ( 2 * sizeof(__int64) ) );    // セット
    do{                                             // 以下繰り返し
        while( *pi > key ){                         // 左側が大きい間
            pi++;                                   // 左側を中に進める
        }                                           //
        while( key > *pj ){                         // 右側が小さい間
            pj--;                                   // 右側を中に進める
        }                                           //
        if( pi <= pj ){                             // 左 ≦ 右 なら
            w   = *pi;                              // 左右のキーデータ
            *pi = *pj;                              // を交換
            *pj = w;                                // し
            pi++;                                   // 左側を中に進める
            pj--;                                   // 右側を中に進める
        }                                           //
    }while( pi <= pj );                             // 左≦右なら繰返し
    if( pl < pj ){                                  // 外左 < 中右 なら
        sort_int64_1( pl, pj );                     // この間をソート
    }                                               //
    if( pi < pr ){                                  // 中左 < 外右 なら
        sort_int64_1( pi, pr );                     // この間をソート
    }                                               //
}

(D-1)ローカル変数

){
    __int64     *pi;                                // 内部Ptr:  左
    __int64     *pj;                                // 内部Ptr:  右
    __int64     key;                                // 中央の値
    __int64     w;                                  // 交換用の場所

「__int64* pi;」は、内部ポインタ(左側用)
「__int64* pj;」は、内部ポインタ(右側用)
「__int64 key;」は、中央の値(キー比較用)
「__int64 w;」は、データ交換用の場所

(D―2)アルゴリズムコード

    pi  = pl;                                       // KeyDataの左側Set
    pj  = pr;                                       // KeyDataの右側Set
    key = *( pi + ( (int)pj - (int)pi )             // 右左の中央値を
                    / ( 2 * sizeof(__int64) ) );    // セット
    do{                                             // 以下繰り返し
        while( *pi > key ){                         // 左側が大きい間
            pi++;                                   // 左側を中に進める
        }                                           //
        while( key > *pj ){                         // 右側が小さい間
            pj--;                                   // 右側を中に進める
        }                                           //
        if( pi <= pj ){                             // 左 ≦ 右 なら
            w   = *pi;                              // 左右のキーデータ
            *pi = *pj;                              // を交換
            *pj = w;                                // し
            pi++;                                   // 左側を中に進める
            pj--;                                   // 右側を中に進める
        }                                           //
    }while( pi <= pj );                             // 左≦右なら繰返し
    if( pl < pj ){                                  // 外左 < 中右 なら
        sort_int64_1( pl, pj );                     // この間をソート
    }                                               //
    if( pi < pr ){                                  // 中左 < 外右 なら
        sort_int64_1( pi, pr );                     // この間をソート
    }                                               //
}

「pi=pl;pj=pr;」は、ローカルな左側・右側をセット
「key=*(pi+((int)pj-(int)pi)/(2*sizeof(__int64)))」は、
左右の中央の場所(ポインタの中央)の値を取り出す!
二重ループで外側の
do構文「・・外側ループ本体・・}while(pi<=pj);」と
後置ループ条件「pi<=pj」と内部のポインタの左右関係が
保たれている間繰り返す!そして最初の内側のループ
「while(*pi>key){pi++;}」は、while構文で
ループ条件「*pi>key」は、「左側の値が、
比較用の値越え」の間「pi++;」ポインタを右側に移動を
繰り返すと、即ち、「左側がキーの値に成るまで繰り
返す」、次の内側ループ
「while(key>*pj){pj--;}」は、「右」側の
値が、比較用の値未満」の間「pj--;」ポインタを左側に
移動を繰り返すと、即ち、「右側がキーの値以下に成るまで
繰り返す」、そしてif構文
「if(pi<=pj){w=*pi;*pi=*pj;*pj=w;pi++;
pj--;}」は、条件「pi<=pj」と左右関係が保たれていたら
「w=*pi;*pi=*pj;*pj=w;pi++;pj--;}」で先ず
「w=*pi;*pi=*pj;*pj=w;」で左右を入れ替え、
「pi++;pj--;」とローカル左右ポインタを進める!
そして「if(pl<pj){sort_int64_1(pl,pj);}」で再帰呼び出し
を自分自身「sort_int64_1()」関数をサブルーチン関数とし
て条件「pl<pj」=「元々の左側が内部の右側と左右関係が
保たれて居る」なら、再帰呼び出し
「sort_int64_1(pl,pj);」を行う事で数学の
「帰納的定義法」と考えて再帰呼び出しを行った部分
「plからpjのポインタの示す左右範囲」が降順にソート済
みと見なして処理する方法です!★備考★これが再帰呼び出
しを行う事で実現する「クイックソート」と呼ばれる通常の
データでは最速と言われているアルゴリズムです同じ様に
「if(pi<pr){sort_int64_1(pi,pr);}」で範囲「piからpr」の
ポインタの示す左右範囲」が降順にソート済みと見なして
処理します!★備考★これが、再帰呼び出しを行う事で
実現する「クイックソート」と呼ばれる通常のデータでは
最速と言われているアルゴリズムですコレは、多くの画像
処理以外のプログラミングで使用されて居ますので数学的
帰納法をアルゴリズムに応用した事を理解して下さい!
C言語的には「再帰呼び出し」との文言で平気で多用しま
す!

(4-15-138)関数「void sort_int64_0_key(
__int64* pl,__int64* pr,
short* plx,short* prx){・・・}」

/************************************************************************/
/*****  QUIC-SORT:昇順ソート:キー=64Bit整数、添字=16   *****/
/************************************************************************/

void            CopyClear::sort_int64_0_key(
    __int64     *pl,                                // KeyDataの左側Ptr
    __int64     *pr,                                // KeyDataの右側Ptr
    short       *plx,                               // 添字Data左側Ptr
    short       *prx                                // 添字Data右側Ptr
){
    __int64     *pi;                                // 内部KeyPtr:  左
    __int64     *pj;                                // 内部KeyPtr:  右
    short       *pix;                               // 内部添字Ptr:左
    short       *pjx;                               // 内部添字Ptr:右
    __int64     key;                                // 中央の値
    __int64     w;                                  // 交換用の場所:キー
    short       wx;                                 // 交換用の場所:添字

    pi  = pl;                                       // KeyDataの左側Set
    pj  = pr;                                       // KeyDataの右側Set
    pix = plx;                                      // 添字左側をSet
    pjx = prx;                                      // 添字右側をSet
    key = *( pi + ( (int)pj - (int)pi )             // 右左の中央値を
                    / ( 2 * sizeof(__int64) ) );    // セット
    do{                                             // 以下繰り返し
        while( *pi < key ){                         // 左側が小さい間
            pi++;                                   // 左側を中に進める
            pix++;                                  // 添字部も進める
        }                                           //
        while( key < *pj ){                         // 右側が大きい間
            pj--;                                   // 右側を中に進める
            pjx--;                                  // 添字部も進める
        }                                           //
        if( pi <= pj ){                             // 左 ≦ 右 なら
            w   = *pi;                              // 左右のキーデータ
            *pi = *pj;                              // を交換
            *pj = w;                                // し
            pi++;                                   // 左側を中に進める
            pj--;                                   // 右側を中に進める
            wx   = *pix;                            // 左右の添字データ
            *pix = *pjx;                            // を交換
            *pjx = wx;                              // し
            pix++;                                  // 左側を中に進める
            pjx--;                                  // 右側を中に進める
        }                                           //
    }while( pi <= pj );                             // 左≦右なら繰返し
    if( pl < pj ){                                  // 外左 < 中右 なら
        sort_int64_0_key( pl, pj, plx, pjx );       // この間をソート
    }                                               //
    if( pi < pr ){                                  // 中左 < 外右 なら
        sort_int64_0_key( pi, pr, pix, prx );       // この間をソート
    }                                               //
}

☆備考☆この関数はファイル「CopyClear100.cpp」に存在!
★注意★この関数は「private:属性」ですのでライブラリの
外から使用不能です!

(A)関数「sort_int64_0_key();」の【関数名】

「Sort」は、勿論、英単語「sort」、カタカナ語ソート・
ソーティング、詰り並び替えです!
「__int64」は、8バイト整数型「__int64型」データを意味
します!
「0」は、昇順にソートする事を意味します!
「key」は、キー付きを意味し、連動して連動配列も中身の
入れ替えを行う事を意味します!
この関数は、データ配列を昇順≪小さい方から大きい方へ
整列≫にソートする関数でインデックス配列も連動して作成
★備考★「_」で区切って居るのは、極初期に作成された
ので区切りに「_」を使用するか、単語先頭「英大文字」と
色々迷って居た時期です!

(B)関数「void sort_int64_0_key();」の【返値】

返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!

(C)関数「sort_int64_0_key()」の【仮引数】

void            CopyClear::sort_int64_0_key(
    __int64     *pl,                                // KeyDataの左側Ptr
    __int64     *pr,                                // KeyDataの右側Ptr
    short       *plx,                               // 添字Data左側Ptr
    short       *prx                                // 添字Data右側Ptr
){

「__int64* pl,」は、データ配列左端「l=left省略」
「__int64* pr」は、データ配列右端「r=right省略」
「short* plx,」は、連動配列配列左端
「short* prx」は、連動配列配列左端
★備考★上記「__int64* pl,__int64* pr」をソート対象キー配列
として、ここ「short* plx,short* prx」は、連動して入れ
替えられる配列

(D)関数「sort_int64_0_key()」の【アルゴリズム】

){
    __int64     *pi;                                // 内部KeyPtr:  左
    __int64     *pj;                                // 内部KeyPtr:  右
    short       *pix;                               // 内部添字Ptr:左
    short       *pjx;                               // 内部添字Ptr:右
    __int64     key;                                // 中央の値
    __int64     w;                                  // 交換用の場所:キー
    short       wx;                                 // 交換用の場所:添字

    pi  = pl;                                       // KeyDataの左側Set
    pj  = pr;                                       // KeyDataの右側Set
    pix = plx;                                      // 添字左側をSet
    pjx = prx;                                      // 添字右側をSet
    key = *( pi + ( (int)pj - (int)pi )             // 右左の中央値を
                    / ( 2 * sizeof(__int64) ) );    // セット
    do{                                             // 以下繰り返し
        while( *pi < key ){                         // 左側が小さい間
            pi++;                                   // 左側を中に進める
            pix++;                                  // 添字部も進める
        }                                           //
        while( key < *pj ){                         // 右側が大きい間
            pj--;                                   // 右側を中に進める
            pjx--;                                  // 添字部も進める
        }                                           //
        if( pi <= pj ){                             // 左 ≦ 右 なら
            w   = *pi;                              // 左右のキーデータ
            *pi = *pj;                              // を交換
            *pj = w;                                // し
            pi++;                                   // 左側を中に進める
            pj--;                                   // 右側を中に進める
            wx   = *pix;                            // 左右の添字データ
            *pix = *pjx;                            // を交換
            *pjx = wx;                              // し
            pix++;                                  // 左側を中に進める
            pjx--;                                  // 右側を中に進める
        }                                           //
    }while( pi <= pj );                             // 左≦右なら繰返し
    if( pl < pj ){                                  // 外左 < 中右 なら
        sort_int64_0_key( pl, pj, plx, pjx );       // この間をソート
    }                                               //
    if( pi < pr ){                                  // 中左 < 外右 なら
        sort_int64_0_key( pi, pr, pix, prx );       // この間をソート
    }                                               //
}

(D-1)ローカル変数

){
    __int64     *pi;                                // 内部KeyPtr:  左
    __int64     *pj;                                // 内部KeyPtr:  右
    short       *pix;                               // 内部添字Ptr:左
    short       *pjx;                               // 内部添字Ptr:右
    __int64     key;                                // 中央の値
    __int64     w;                                  // 交換用の場所:キー
    short       wx;                                 // 交換用の場所:添字

「__int64* pi;」は、内部ポインタ(左側用)キー
「__int64* pj;」は、内部ポインタ(右側用)キー
「short* pix;」は、内部ポインタ(左側用)連動
「short* pjx;」は、内部ポインタ(右側用)連動
「__int64 key;」は、中央の値(キー比較用)
「__int64 w;」は、データ交換用の場所
「short wx;」は、データ交換用の場所連動

(D―2)アルゴリズムコード

    pi  = pl;                                       // KeyDataの左側Set
    pj  = pr;                                       // KeyDataの右側Set
    pix = plx;                                      // 添字左側をSet
    pjx = prx;                                      // 添字右側をSet
    key = *( pi + ( (int)pj - (int)pi )             // 右左の中央値を
                    / ( 2 * sizeof(__int64) ) );    // セット
    do{                                             // 以下繰り返し
        while( *pi < key ){                         // 左側が小さい間
            pi++;                                   // 左側を中に進める
            pix++;                                  // 添字部も進める
        }                                           //
        while( key < *pj ){                         // 右側が大きい間
            pj--;                                   // 右側を中に進める
            pjx--;                                  // 添字部も進める
        }                                           //
        if( pi <= pj ){                             // 左 ≦ 右 なら
            w   = *pi;                              // 左右のキーデータ
            *pi = *pj;                              // を交換
            *pj = w;                                // し
            pi++;                                   // 左側を中に進める
            pj--;                                   // 右側を中に進める
            wx   = *pix;                            // 左右の添字データ
            *pix = *pjx;                            // を交換
            *pjx = wx;                              // し
            pix++;                                  // 左側を中に進める
            pjx--;                                  // 右側を中に進める
        }                                           //
    }while( pi <= pj );                             // 左≦右なら繰返し
    if( pl < pj ){                                  // 外左 < 中右 なら
        sort_int64_0_key( pl, pj, plx, pjx );       // この間をソート
    }                                               //
    if( pi < pr ){                                  // 中左 < 外右 なら
        sort_int64_0_key( pi, pr, pix, prx );       // この間をソート
    }                                               //
}

「pi=pl;pj=pr;」は、ローカルな左側・右側をセット
「pix=plx;pjx=prx;」は、ローカルな左側・右側をセット
「key=*(pi+((int)pj-(int)pi)/(2*sizeof(__int64)))」は、
左右の中央の場所(ポインタの中央)の値を取り出す!
二重ループで外側の
do構文「・・外側ループ本体・・}while(pi<=pj);」と
後置ループ条件「pi<=pj」と内部のポインタの左右関係が
保たれている間繰り返す!そして最初の内側のループ
「while(*pi<key){pi++;pix++;}」は、while構文で
ループ条件「*pi<key」は、「左側の値が、比較用の値未満
」の間「pi++;pix++;」ポインタを右側に移動を繰り返すと
即ち、「左側がキーの値以上に成るまで繰り返す」、
次の内側ループ
「while(key<*pj){pj--;pjx--;}」は、「右」側の値が、
比較用の値越え」の間「pj--;pjx--;」ポインタを左側に
移動を繰り返すと、即ち、「右側がキーの値以下に成るまで
繰り返す」、
そしてif構文
「if(pi<=pj){w=*pi;*pi=*pj;*pj=w;pi++;
pj--;wx=*pix;*pix=*pjx;*pjx=wx;pix++;pjx--;}」は、
条件「pi<=pj」と左右関係が保たれていたら
「w=*pi;*pi=*pj;*pj=w;pi++;pj--;wx=*pix;
*pix=*pjx;*pjx=wx;pix++;pjx--;
wx=*pix;*pix=*pjx;*pjx=wx;pix++;pjx--;}」で先ず
「w=*pi;*pi=*pj;*pj=w;」でキーデータ左右を入れ替え、
「pi++;pj--;」とローカル左右ポインタを進める!
そして連動配列の入れ替えとして
「wx=*pix;*pix=*pjx;*pjx=wx;pix++;pjx--;」と配列入れ
替えを行い!「do構文」を終えると!
そして「if(pl<pj){sort_int64_0_key(pl,pj,plx,pjx);}」
で再帰呼び出しを自分自身「sort_int64_0_key()」関数を
サブルーチン関数として条件「pl<pj」=「元々の左側が
内部の右側と左右関係が保たれて居る」なら、再帰呼び出し
「sort_int64_0_key(pl,pj,plx,pjx);」を行う事で数学の
「帰納的定義法」と考えて再帰呼び出しを行った部分
「plからpjのポインタの示す左右範囲」が昇順にソート済
みと見なして処理する方法です!★備考★これが再帰呼び出
しを行う事で実現する「クイックソート」と呼ばれる通常の
データでは最速と言われているアルゴリズムです同じ様に
「if(pi<pr){sort_int64_0_key(pi,pr,pix,prx);}」で範囲
「piからpr」のポインタの示す左右範囲」が昇順にソート
済みと見なして処理します!★備考★これが、再帰呼び出し
を行う事で実現する「クイックソート」と呼ばれる通常の
データでは最速と言われているアルゴリズムですコレは、
多くの画像処理以外のプログラミングで使用されて居ますの
で数学的帰納法をアルゴリズムに応用した事を理解して下さ
い!C言語的には「再帰呼び出し」との文言で平気で多用し
ます!

(4-15-139)関数「void sort_int64_1_key(
__int64* pl,__int64* pr,
short* plx,short* prx){・・・}」

/************************************************************************/
/*****  QUIC-SORT:降順ソート:キー=64Bit整数、添字1=16 *****/
/************************************************************************/

void            CopyClear::sort_int64_1_key(
    __int64     *pl,                                // KeyDataの左側Ptr
    __int64     *pr,                                // KeyDataの右側Ptr
    short       *plx,                               // 添字Data左側Ptr
    short       *prx                                // 添字Data右側Ptr
){
    __int64     *pi;                                // 内部KeyPtr:  左
    __int64     *pj;                                // 内部KeyPtr:  右
    short       *pix;                               // 内部添字Ptr:左
    short       *pjx;                               // 内部添字Ptr:右
    __int64     key;                                // 中央の値
    __int64     w;                                  // 交換用の場所:キー
    short       wx;                                 // 交換用の場所:添字

    pi  = pl;                                       // KeyDataの左側Set
    pj  = pr;                                       // KeyDataの右側Set
    pix = plx;                                      // 添字左側をSet
    pjx = prx;                                      // 添字右側をSet
    key = *( pi + ( (int)pj - (int)pi )             // 右左の中央値を
                    / ( 2 * sizeof(__int64) ) );    // セット
    do{                                             // 以下繰り返し
        while( *pi > key ){                         // 左側が大きい間
            pi++;                                   // 左側を中に進める
            pix++;                                  // 添字部も進める
        }                                           //
        while( key > *pj ){                         // 右側が小さい間
            pj--;                                   // 右側を中に進める
            pjx--;                                  // 添字部も進める
        }                                           //
        if( pi <= pj ){                             // 左 ≦ 右 なら
            w   = *pi;                              // 左右のキーデータ
            *pi = *pj;                              // を交換
            *pj = w;                                // し
            pi++;                                   // 左側を中に進める
            pj--;                                   // 右側を中に進める
            wx   = *pix;                            // 左右の添字データ
            *pix = *pjx;                            // を交換
            *pjx = wx;                              // し
            pix++;                                  // 左側を中に進める
            pjx--;                                  // 右側を中に進める
        }                                           //
    }while( pi <= pj );                             // 左≦右なら繰返し
    if( pl < pj ){                                  // 外左 < 中右 なら
        sort_int64_1_key( pl, pj, plx, pjx );       // この間をソート
    }                                               //
    if( pi < pr ){                                  // 中左 < 外右 なら
        sort_int64_1_key( pi, pr, pix, prx );       // この間をソート
    }                                               //
}

☆備考☆この関数はファイル「CopyClear100.cpp」に存在!
★注意★この関数は「private:属性」ですのでライブラリの
外から使用不能です!

(A)関数「sort_int64_1_key();」の【関数名】

「Sort」は、勿論、英単語「sort」、カタカナ語ソート・
ソーティング、詰り並び替えです!
「__int64」は、8バイト整数型「__int64型」データを意味
します!
「1」は、降順にソートする事を意味します!
この関数は、データ配列を降順≪大きい方からへ小さい方に
整列≫にソートする関数
「key」は、キー付きを意味し、連動して連動配列も中身の
入れ替えを行う事を意味します!
この関数は、データ配列を降順≪大きい方からへ小さい方に
整列≫にソートする関数でインデックス配列も連動して作成
★備考★「_」で区切って居るのは、極初期に作成された
ので区切りに「_」を使用するか、単語先頭「英大文字」と
色々迷って居た時期です!

(B)関数「void sort_int64_1_key();」の【返値】

返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!

(C)関数「sort_int64_1_key()」の【仮引数】

void            CopyClear::sort_int64_1_key(
    __int64     *pl,                                // KeyDataの左側Ptr
    __int64     *pr,                                // KeyDataの右側Ptr
    short       *plx,                               // 添字Data左側Ptr
    short       *prx                                // 添字Data右側Ptr
){

「__int64* pl,」は、データ配列左端「l=left省略」
「__int64* pr」は、データ配列右端「r=right省略」
「short* plx,」は、連動配列配列左端
「short* prx」は、連動配列配列左端
★備考★上記「__int64* pl,__int64* pr」をソート対象キー配列
として、ここ「short* plx,short* prx」は、連動して入れ
替えられる配列

(D)関数「sort_int64_1_key()」の【アルゴリズム】

){
    __int64     *pi;                                // 内部KeyPtr:  左
    __int64     *pj;                                // 内部KeyPtr:  右
    short       *pix;                               // 内部添字Ptr:左
    short       *pjx;                               // 内部添字Ptr:右
    __int64     key;                                // 中央の値
    __int64     w;                                  // 交換用の場所:キー
    short       wx;                                 // 交換用の場所:添字

    pi  = pl;                                       // KeyDataの左側Set
    pj  = pr;                                       // KeyDataの右側Set
    pix = plx;                                      // 添字左側をSet
    pjx = prx;                                      // 添字右側をSet
    key = *( pi + ( (int)pj - (int)pi )             // 右左の中央値を
                    / ( 2 * sizeof(__int64) ) );    // セット
    do{                                             // 以下繰り返し
        while( *pi > key ){                         // 左側が大きい間
            pi++;                                   // 左側を中に進める
            pix++;                                  // 添字部も進める
        }                                           //
        while( key > *pj ){                         // 右側が小さい間
            pj--;                                   // 右側を中に進める
            pjx--;                                  // 添字部も進める
        }                                           //
        if( pi <= pj ){                             // 左 ≦ 右 なら
            w   = *pi;                              // 左右のキーデータ
            *pi = *pj;                              // を交換
            *pj = w;                                // し
            pi++;                                   // 左側を中に進める
            pj--;                                   // 右側を中に進める
            wx   = *pix;                            // 左右の添字データ
            *pix = *pjx;                            // を交換
            *pjx = wx;                              // し
            pix++;                                  // 左側を中に進める
            pjx--;                                  // 右側を中に進める
        }                                           //
    }while( pi <= pj );                             // 左≦右なら繰返し
    if( pl < pj ){                                  // 外左 < 中右 なら
        sort_int64_1_key( pl, pj, plx, pjx );       // この間をソート
    }                                               //
    if( pi < pr ){                                  // 中左 < 外右 なら
        sort_int64_1_key( pi, pr, pix, prx );       // この間をソート
    }                                               //
}

(D-1)ローカル変数

){
    __int64     *pi;                                // 内部KeyPtr:  左
    __int64     *pj;                                // 内部KeyPtr:  右
    short       *pix;                               // 内部添字Ptr:左
    short       *pjx;                               // 内部添字Ptr:右
    __int64     key;                                // 中央の値
    __int64     w;                                  // 交換用の場所:キー
    short       wx;                                 // 交換用の場所:添字

「__int64* pi;」は、内部ポインタ(左側用)キー
「__int64* pj;」は、内部ポインタ(右側用)キー
「short* pix;」は、内部ポインタ(左側用)連動
「short* pjx;」は、内部ポインタ(右側用)連動
「__int64 key;」は、中央の値(キー比較用)
「__int64 w;」は、データ交換用の場所
「short wx;」は、データ交換用の場所連動

(D―2)アルゴリズムコード

    pi  = pl;                                       // KeyDataの左側Set
    pj  = pr;                                       // KeyDataの右側Set
    pix = plx;                                      // 添字左側をSet
    pjx = prx;                                      // 添字右側をSet
    key = *( pi + ( (int)pj - (int)pi )             // 右左の中央値を
                    / ( 2 * sizeof(__int64) ) );    // セット
    do{                                             // 以下繰り返し
        while( *pi > key ){                         // 左側が大きい間
            pi++;                                   // 左側を中に進める
            pix++;                                  // 添字部も進める
        }                                           //
        while( key > *pj ){                         // 右側が小さい間
            pj--;                                   // 右側を中に進める
            pjx--;                                  // 添字部も進める
        }                                           //
        if( pi <= pj ){                             // 左 ≦ 右 なら
            w   = *pi;                              // 左右のキーデータ
            *pi = *pj;                              // を交換
            *pj = w;                                // し
            pi++;                                   // 左側を中に進める
            pj--;                                   // 右側を中に進める
            wx   = *pix;                            // 左右の添字データ
            *pix = *pjx;                            // を交換
            *pjx = wx;                              // し
            pix++;                                  // 左側を中に進める
            pjx--;                                  // 右側を中に進める
        }                                           //
    }while( pi <= pj );                             // 左≦右なら繰返し
    if( pl < pj ){                                  // 外左 < 中右 なら
        sort_int64_1_key( pl, pj, plx, pjx );       // この間をソート
    }                                               //
    if( pi < pr ){                                  // 中左 < 外右 なら
        sort_int64_1_key( pi, pr, pix, prx );       // この間をソート
    }                                               //
}

「pi=pl;pj=pr;」は、ローカルな左側・右側をセット
「pix=plx;pjx=prx;」は、ローカルな左側・右側をセット
「key=*(pi+((int)pj-(int)pi)/(2*sizeof(__int64)))」は、
左右の中央の場所(ポインタの中央)の値を取り出す!
二重ループで外側の
do構文「・・外側ループ本体・・}while(pi<=pj);」と
後置ループ条件「pi<=pj」と内部のポインタの左右関係が
保たれている間繰り返す!そして最初の内側のループ
「while(*pi>key){pi++;pix++;}」は、while構文で
ループ条件「*pi>key」は、「左側の値が、比較用の値未満
」の間「pi++;pix++;」ポインタを右側に移動を繰り返すと
即ち、「左側がキーの値以上に成るまで繰り返す」、
次の内側ループ
「while(key>*pj){pj--;pjx--;}」は、「右」側の値が、
比較用の値未満」の間「pj--;pjx--;」ポインタを左側に
移動を繰り返すと、即ち、「右側がキーの値以上に成る
まで繰り返す」、
そしてif構文
「if(pi<=pj){w=*pi;*pi=*pj;*pj=w;pi++;
pj--;wx=*pix;*pix=*pjx;*pjx=wx;pix++;pjx--;}」は、
条件「pi<=pj」と左右関係が保たれていたら
「w=*pi;*pi=*pj;*pj=w;pi++;pj--;wx=*pix;
*pix=*pjx;*pjx=wx;pix++;pjx--;
wx=*pix;*pix=*pjx;*pjx=wx;pix++;pjx--;}」で先ず
「w=*pi;*pi=*pj;*pj=w;」でキーデータ左右を入れ替え、
「pi++;pj--;」とローカル左右ポインタを進める!
そして連動配列の入れ替えとして
「wx=*pix;*pix=*pjx;*pjx=wx;pix++;pjx--;」と配列入れ
替えを行い!「do構文」を終えると!
そして「if(pl<pj){sort_int64_1_key(pl,pj,plx,pjx);}」
で再帰呼び出しを自分自身「sort_int64_1_key()」関数を
サブルーチン関数として条件「pl<pj」=「元々の左側が
内部の右側と左右関係が保たれて居る」なら、再帰呼び出し
「sort_int64_1_key(pl,pj,plx,pjx);」を行う事で数学の
「帰納的定義法」と考えて再帰呼び出しを行った部分
「plからpjのポインタの示す左右範囲」が降順にソート済
みと見なして処理する方法です!★備考★これが再帰呼び出
しを行う事で実現する「クイックソート」と呼ばれる通常の
データでは最速と言われているアルゴリズムです同じ様に
「if(pi<pr){sort_int64_1_key(pi,pr,pix,prx);}」で範囲
「piからpr」のポインタの示す左右範囲」が降順にソート
済みと見なして処理します!★備考★これが、再帰呼び出し
を行う事で実現する「クイックソート」と呼ばれる通常の
データでは最速と言われているアルゴリズムですコレは、
多くの画像処理以外のプログラミングで使用されて居ますの
で数学的帰納法をアルゴリズムに応用した事を理解して下さ
い!C言語的には「再帰呼び出し」との文言で平気で多用し
ます!

(4-15-140)関数「void sortTypeCorr0(
TypeCorr* pl,TypeCorr* pr){・・・}」

/************************************************************************/
/*****      QUIC-SORT:昇順ソート:データ=TypeCorr        *****/
/************************************************************************/

void            CopyClear::sortTypeCorr0(
    TypeCorr    *pl,                                // データの左側Ptr
    TypeCorr    *pr                                 // データの右側Ptr
){
    TypeCorr    *p;                                 // 内部Ptr:中央
    TypeCorr    *pi;                                // 内部Ptr:  左
    TypeCorr    *pj;                                // 内部Ptr:  右
    double      key;                                // 中央の値
    TypeCorr    w;                                  // 交換用の場所

    pi  = pl;                                       // KeyDataの左側Set
    pj  = pr;                                       // KeyDataの右側Set
    p   = pi + ( (int)pj - (int)pi )                // 右左の中央値を
                        / ( 2 * sizeof(TypeCorr) ); // セット
    key = p->d;                                     // 相関値部を取り出す
    do{                                             // 以下繰り返し
        while( pi->d < key ){                       // 左側が小さい間
            pi++;                                   // 左側を中に進める
        }                                           //
        while( key < pj->d ){                       // 右側が大きい間
            pj--;                                   // 右側を中に進める
        }                                           //
        if( pi <= pj ){                             // 左 ≦ 右 なら
            w   = *pi;                              // 左右のキーデータ
            *pi = *pj;                              // を交換
            *pj = w;                                // し
            pi++;                                   // 左側を中に進める
            pj--;                                   // 右側を中に進める
        }                                           //
    }while( pi <= pj );                             // 左≦右なら繰返し
    if( pl < pj ){                                  // 外左 < 中右 なら
        sortTypeCorr0( pl, pj );                    // この間をソート
    }                                               //
    if( pi < pr ){                                  // 中左 < 外右 なら
        sortTypeCorr0( pi, pr );                    // この間をソート
    }                                               //
}

☆備考☆この関数はファイル「CopyClear100.cpp」に存在!
★注意★この関数は「private:属性」ですのでライブラリの
外から使用不能です!

(A)関数「sortTypeCorr0();」の【関数名】

「Sort」は、勿論、英単語「sort」、カタカナ語ソート・
ソーティング、詰り並び替えです!
★注意★構造体「TypeCorr」は、相関値関連です!この
データは、相関値の値でソーティングします!
「0」は、データ配列を昇順≪小さい方から大きい方へ整列
≫にソートする関数を意味!
この関数は、相関値の値でデータ配列を昇順≪小さい方から
大きい方へ整列≫にソートする関数

(B)関数「void sortTypeCorr0();」の【返値】

返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!

(C)関数「sortTypeCorr0()」の【仮引数】

void            CopyClear::sortTypeCorr0(
    TypeCorr    *pl,                                // データの左側Ptr
    TypeCorr    *pr                                 // データの右側Ptr
){

「TypeCorr* pl,」は、データ配列左端「l=left省略」
「TypeCorr* pr」は、データ配列右端「r=right省略」
ここで使用する専用の型「TypeCorr」≪
解説『解説クラスSupport』の「(2-6)
相関値+座標」で解説≫

(D)関数「sortTypeCorr0()」の【アルゴリズム】

){
    TypeCorr    *p;                                 // 内部Ptr:中央
    TypeCorr    *pi;                                // 内部Ptr:  左
    TypeCorr    *pj;                                // 内部Ptr:  右
    double      key;                                // 中央の値
    TypeCorr    w;                                  // 交換用の場所

    pi  = pl;                                       // KeyDataの左側Set
    pj  = pr;                                       // KeyDataの右側Set
    p   = pi + ( (int)pj - (int)pi )                // 右左の中央値を
                        / ( 2 * sizeof(TypeCorr) ); // セット
    key = p->d;                                     // 相関値部を取り出す
    do{                                             // 以下繰り返し
        while( pi->d < key ){                       // 左側が小さい間
            pi++;                                   // 左側を中に進める
        }                                           //
        while( key < pj->d ){                       // 右側が大きい間
            pj--;                                   // 右側を中に進める
        }                                           //
        if( pi <= pj ){                             // 左 ≦ 右 なら
            w   = *pi;                              // 左右のキーデータ
            *pi = *pj;                              // を交換
            *pj = w;                                // し
            pi++;                                   // 左側を中に進める
            pj--;                                   // 右側を中に進める
        }                                           //
    }while( pi <= pj );                             // 左≦右なら繰返し
    if( pl < pj ){                                  // 外左 < 中右 なら
        sortTypeCorr0( pl, pj );                    // この間をソート
    }                                               //
    if( pi < pr ){                                  // 中左 < 外右 なら
        sortTypeCorr0( pi, pr );                    // この間をソート
    }                                               //
}

(D-1)ローカル変数

){
    TypeCorr    *p;                                 // 内部Ptr:中央
    TypeCorr    *pi;                                // 内部Ptr:  左
    TypeCorr    *pj;                                // 内部Ptr:  右
    double      key;                                // 中央の値
    TypeCorr    w;                                  // 交換用の場所

「TypeCorr* p;」は、内部ポインタ(中央用)
「TypeCorr* pi;」は、内部ポインタ(左側用)
「TypeCorr* pj;」は、内部ポインタ(右側用)
「double key;」は、中央の値(キー比較用)
「TypeCorr w;」は、データ交換用の場所

(D―2)アルゴリズムコード

    pi  = pl;                                       // KeyDataの左側Set
    pj  = pr;                                       // KeyDataの右側Set
    p   = pi + ( (int)pj - (int)pi )                // 右左の中央値を
                        / ( 2 * sizeof(TypeCorr) ); // セット
    key = p->d;                                     // 相関値部を取り出す
    do{                                             // 以下繰り返し
        while( pi->d < key ){                       // 左側が小さい間
            pi++;                                   // 左側を中に進める
        }                                           //
        while( key < pj->d ){                       // 右側が大きい間
            pj--;                                   // 右側を中に進める
        }                                           //
        if( pi <= pj ){                             // 左 ≦ 右 なら
            w   = *pi;                              // 左右のキーデータ
            *pi = *pj;                              // を交換
            *pj = w;                                // し
            pi++;                                   // 左側を中に進める
            pj--;                                   // 右側を中に進める
        }                                           //
    }while( pi <= pj );                             // 左≦右なら繰返し
    if( pl < pj ){                                  // 外左 < 中右 なら
        sortTypeCorr0( pl, pj );                    // この間をソート
    }                                               //
    if( pi < pr ){                                  // 中左 < 外右 なら
        sortTypeCorr0( pi, pr );                    // この間をソート
    }                                               //
}

「pi=pl;pj=pr;」は、ローカルな左側・右側をセット
「p=pi+((int)pj-(int)pi)/(2*sizeof(TypeCorr));」は、
ローカルなデータ配列の中央へのポインタをセット
「key=p->d;」は、左右の中央の場所のキー値「p->d」、
詰り相関値を取り出す!★備考★他の関数では中央値への
ポインタを算出せずに直接、キーデータを取り出して居ます
が、「TypeCorr」と正規相関(XY座標と相関値)の
メンバーとして相関値を使用するので理解し易い様に中央
ポインタを先ず作成してから、メンバーの相関値を取り出す
事にしました!
二重ループで外側の
do構文「・・外側ループ本体・・}while(pi<=pj);」と
後置ループ条件「pi<=pj」と内部のポインタの左右関係が
保たれている間繰り返す!そして最初の内側のループ
「while(pi->d<key){pi++;}」は、while構文で
ループ条件「pi->d<key」は、「左側のキーの値が、
比較用の値未満」の間「pi++;」ポインタを右側に移動を
繰り返すと、即ち、「左側がキーの値以上に成るまで繰り
返す」、次の内側ループ
「while(key<pj->d){pj--;}」は、「右」側のキーの
値が、比較用の値越え」の間「pj--;」ポインタを左側に
移動を繰り返すと、即ち、「右側がキーの値以下に成るまで
繰り返す」、そしてif構文
「if(pi<=pj){w=*pi;*pi=*pj;*pj=w;pi++;pj--;}」は、
条件「pi<=pj」と左右関係が保たれていたら
「w=*pi;*pi=*pj;*pj=w;pi++;pj--;}」で先ず、
「w=*pi;*pi=*pj;*pj=w;」で左右を入れ替え、
「pi++;pj--;」とローカル左右ポインタを進める!
そして「if(pl<pj){sortTypeCorr0(pl,pj);}」で再帰呼び
出しを自分自身「sortTypeCorr0()」関数をサブルーチン
関数として行い!
条件「pl<pj」=「元々の左側が内部の右側と左右関係が保
たれて居る」なら、再帰呼び出し「sortTypeCorr0(pl,pj);」を
行う事で数学の「帰納的定義法」と考えて再帰呼び出しを
行った部分「plからpjのポインタの示す左右範囲」が昇順に
ソート済みと見なして処理する方法です!★備考★これが
再帰呼び出しを行う事で実現する「クイックソート」と呼ば
れる通常のデータでは最速と言われているアルゴリズムです
同じ様に「if(pi<pr){sortTypeCorr0(pi,pr);}」で範囲
「piからpr」のポインタの示す左右範囲」が昇順に
ソート済みと見なして処理します!★備考★これが、
再帰呼び出しを行う事で実現する「クイックソート」と呼ば
れる通常のデータでは最速と言われているアルゴリズムです
コレは、多くの画像処理以外のプログラミングで使用されて
居ますので数学的帰納法をアルゴリズムに応用した事を理解
して下さい!C言語的には「再帰呼び出し」との文言で平気
で多用します!

(4-15-141)関数「void sortTypeCorr1(
TypeCorr* pl,TypeCorr* pr){・・・}」

/************************************************************************/
/*****      QUIC-SORT:降順ソート:データ=TypeCorr        *****/
/************************************************************************/

void            CopyClear::sortTypeCorr1(
    TypeCorr    *pl,                                // データの左側Ptr
    TypeCorr    *pr                                 // データの右側Ptr
){
    TypeCorr    *p;                                 // 内部Ptr:中央
    TypeCorr    *pi;                                // 内部Ptr:  左
    TypeCorr    *pj;                                // 内部Ptr:  右
    double      key;                                // 中央の値
    TypeCorr    w;                                  // 交換用の場所

    pi  = pl;                                       // KeyDataの左側Set
    pj  = pr;                                       // KeyDataの右側Set
    p   = pi + ( (int)pj - (int)pi )                // 右左の中央値を
                        / ( 2 * sizeof(TypeCorr) ); // セット
    key = p->d;                                     // 相関値部を取り出す
    do{                                             // 以下繰り返し
        while( pi->d > key ){                       // 左側が大きい間
            pi++;                                   // 左側を中に進める
        }                                           //
        while( key > pj->d ){                       // 右側が小さい間
            pj--;                                   // 右側を中に進める
        }                                           //
        if( pi <= pj ){                             // 左 ≦ 右 なら
            w   = *pi;                              // 左右のキーデータ
            *pi = *pj;                              // を交換
            *pj = w;                                // し
            pi++;                                   // 左側を中に進める
            pj--;                                   // 右側を中に進める
        }                                           //
    }while( pi <= pj );                             // 左≦右なら繰返し
    if( pl < pj ){                                  // 外左 < 中右 なら
        sortTypeCorr1( pl, pj );                    // この間をソート
    }                                               //
    if( pi < pr ){                                  // 中左 < 外右 なら
        sortTypeCorr1( pi, pr );                    // この間をソート
    }                                               //
}

☆備考☆この関数はファイル「CopyClear100.cpp」に存在!
★注意★この関数は「private:属性」ですのでライブラリの
外から使用不能です!

(A)関数「sortTypeCorr1();」の【関数名】

「Sort」は、勿論、英単語「sort」、カタカナ語ソート・
ソーティング、詰り並び替えです!
★注意★構造体「TypeCorr」は、相関値関連です!この
データは、相関値の値でソーティングします!
「1」は、データ配列を相関値の値でデータ配列を降順≪
大きい方から小さい方へ整列≫にソートする関数

(B)関数「void sortTypeCorr1();」の【返値】

返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!

(C)関数「sortTypeCorr1()」の【仮引数】

void            CopyClear::sortTypeCorr1(
    TypeCorr    *pl,                                // データの左側Ptr
    TypeCorr    *pr                                 // データの右側Ptr
){

「TypeCorr* pl,」は、データ配列左端「l=left省略」
「TypeCorr* pr」は、データ配列右端「r=right省略」
ここで使用する専用の型「TypeCorr」≪
解説『解説クラスSupport』の「(2-6)
相関値+座標」で解説≫

(D)関数「sortTypeCorr1()」の【アルゴリズム】

){
    TypeCorr    *p;                                 // 内部Ptr:中央
    TypeCorr    *pi;                                // 内部Ptr:  左
    TypeCorr    *pj;                                // 内部Ptr:  右
    double      key;                                // 中央の値
    TypeCorr    w;                                  // 交換用の場所

    pi  = pl;                                       // KeyDataの左側Set
    pj  = pr;                                       // KeyDataの右側Set
    p   = pi + ( (int)pj - (int)pi )                // 右左の中央値を
                        / ( 2 * sizeof(TypeCorr) ); // セット
    key = p->d;                                     // 相関値部を取り出す
    do{                                             // 以下繰り返し
        while( pi->d > key ){                       // 左側が大きい間
            pi++;                                   // 左側を中に進める
        }                                           //
        while( key > pj->d ){                       // 右側が小さい間
            pj--;                                   // 右側を中に進める
        }                                           //
        if( pi <= pj ){                             // 左 ≦ 右 なら
            w   = *pi;                              // 左右のキーデータ
            *pi = *pj;                              // を交換
            *pj = w;                                // し
            pi++;                                   // 左側を中に進める
            pj--;                                   // 右側を中に進める
        }                                           //
    }while( pi <= pj );                             // 左≦右なら繰返し
    if( pl < pj ){                                  // 外左 < 中右 なら
        sortTypeCorr1( pl, pj );                    // この間をソート
    }                                               //
    if( pi < pr ){                                  // 中左 < 外右 なら
        sortTypeCorr1( pi, pr );                    // この間をソート
    }                                               //
}

(D-1)ローカル変数

){
    TypeCorr    *p;                                 // 内部Ptr:中央
    TypeCorr    *pi;                                // 内部Ptr:  左
    TypeCorr    *pj;                                // 内部Ptr:  右
    double      key;                                // 中央の値
    TypeCorr    w;                                  // 交換用の場所

「TypeCorr* p;」は、内部ポインタ(中央用)
「TypeCorr* pi;」は、内部ポインタ(左側用)
「TypeCorr* pj;」は、内部ポインタ(右側用)
「double key;」は、中央の値(キー比較用)
「TypeCorr w;」は、データ交換用の場所

(D―2)アルゴリズムコード

    pi  = pl;                                       // KeyDataの左側Set
    pj  = pr;                                       // KeyDataの右側Set
    p   = pi + ( (int)pj - (int)pi )                // 右左の中央値を
                        / ( 2 * sizeof(TypeCorr) ); // セット
    key = p->d;                                     // 相関値部を取り出す
    do{                                             // 以下繰り返し
        while( pi->d > key ){                       // 左側が大きい間
            pi++;                                   // 左側を中に進める
        }                                           //
        while( key > pj->d ){                       // 右側が小さい間
            pj--;                                   // 右側を中に進める
        }                                           //
        if( pi <= pj ){                             // 左 ≦ 右 なら
            w   = *pi;                              // 左右のキーデータ
            *pi = *pj;                              // を交換
            *pj = w;                                // し
            pi++;                                   // 左側を中に進める
            pj--;                                   // 右側を中に進める
        }                                           //
    }while( pi <= pj );                             // 左≦右なら繰返し
    if( pl < pj ){                                  // 外左 < 中右 なら
        sortTypeCorr1( pl, pj );                    // この間をソート
    }                                               //
    if( pi < pr ){                                  // 中左 < 外右 なら
        sortTypeCorr1( pi, pr );                    // この間をソート
    }                                               //
}



「pi=pl;pj=pr;」は、ローカルな左側・右側をセット
「p=pi+((int)pj-(int)pi)/(2*sizeof(TypeCorr));」は、
ローカルなデータ配列の中央へのポインタをセット
「key=p->d;」は、左右の中央の場所のキー値「p->d」、
詰り相関値を取り出す!★備考★他の関数では中央値への
ポインタを算出せずに直接、キーデータを取り出して居ます
が、「TypeCorr」と正規相関(XY座標と相関値)の
メンバーとして相関値を使用するので理解し易い様に中央
ポインタを先ず作成してから、メンバーの相関値を取り出す
事にしました!
二重ループで外側の
do構文「・・外側ループ本体・・}while(pi<=pj);」と
後置ループ条件「pi<=pj」と内部のポインタの左右関係が
保たれている間繰り返す!そして最初の内側のループ
「while(pi->d>key){pi++;}」は、while構文で
ループ条件「pi->d>key」は、「左側のキーの値が、
比較用の値越え」の間「pi++;」ポインタを右側に移動を
繰り返すと、即ち、「左側がキーの値以下に成るまで繰り
返す」、次の内側ループ
「while(key>pj->d){pj--;}」は、「右」側のキーの
値が、比較用の値未満」の間「pj--;」ポインタを左側に
移動を繰り返すと、即ち、「右側がキーの値以上に成るまで
繰り返す」、そしてif構文
「if(pi>=pj){w=*pi;*pi=*pj;*pj=w;pi++;pj--;}」は、
条件「pi>=pj」と左右関係が保たれていたら
「w=*pi;*pi=*pj;*pj=w;pi++;pj--;}」で先ず、
「w=*pi;*pi=*pj;*pj=w;」で左右を入れ替え、
「pi++;pj--;」とローカル左右ポインタを進める!
そして「if(pl<pj){sortTypeCorr0(pl,pj);}」で再帰呼び
出しを自分自身「sortTypeCorr0()」関数をサブルーチン
関数として行い!
条件「pl<pj」=「元々の左側が内部の右側と左右関係が保
たれて居る」なら、再帰呼び出し「sortTypeCorr0(pl,pj);」
を行う事で数学の「帰納的定義法」と考えて再帰呼び出しを
行った部分「plからpjのポインタの示す左右範囲」が昇順に
ソート済みと見なして処理する方法です!★備考★これが
再帰呼び出しを行う事で実現する「クイックソート」と呼ば
れる通常のデータでは最速と言われているアルゴリズムです
同じ様に「if(pi<pr){sortTypeCorr0(pi,pr);}」で範囲
「piからpr」のポインタの示す左右範囲」が昇順に
ソート済みと見なして処理します!★備考★これが、
再帰呼び出しを行う事で実現する「クイックソート」と呼ば
れる通常のデータでは最速と言われているアルゴリズムです
コレは、多くの画像処理以外のプログラミングで使用されて
居ますので数学的帰納法をアルゴリズムに応用した事を理解
して下さい!C言語的には「再帰呼び出し」との文言で平気
で多用します!

(4-15-142)関数「void sortTypeCorrIX0(
TypeCorrIX* pl,
TypeCorrIX* pr,short* plx,
short* prx){・・・}」

/************************************************************************/
/*****      QUIC-SORT:昇順ソート:データ=TypeCorrIX      *****/
/************************************************************************/

void                CopyClear::sortTypeCorrIX0(
    TypeCorrIX      *pl,                                // データの左側Ptr
    TypeCorrIX      *pr                                 // データの右側Ptr
){
    TypeCorrIX      *p;                                 // 内部Ptr:中央
    TypeCorrIX      *pi;                                // 内部Ptr:  左
    TypeCorrIX      *pj;                                // 内部Ptr:  右
    double          key;                                // 中央の値
    TypeCorrIX      w;                                  // 交換用の場所

    pi  = pl;                                           // KeyDataの左側Set
    pj  = pr;                                           // KeyDataの右側Set
    p   = pi + ( (int)pj - (int)pi )                    // 右左の中央値を
                        / ( 2 * sizeof(TypeCorrIX) );   // セット
    key = p->d;                                         // 相関値部を取り出す
    do{                                                 // 以下繰り返し
        while( pi->d < key ){                           // 左側が小さい間
            pi++;                                       // 左側を中に進める
        }                                               //
        while( key < pj->d ){                           // 右側が大きい間
            pj--;                                       // 右側を中に進める
        }                                               //
        if( pi <= pj ){                                 // 左 ≦ 右 なら
            w   = *pi;                                  // 左右のキーデータ
            *pi = *pj;                                  // を交換
            *pj = w;                                    // し
            pi++;                                       // 左側を中に進める
            pj--;                                       // 右側を中に進める
        }                                               //
    }while( pi <= pj );                                 // 左≦右なら繰返し
    if( pl < pj ){                                      // 外左 < 中右 なら
        sortTypeCorrIX0( pl, pj );                      // この間をソート
    }                                                   //
    if( pi < pr ){                                      // 中左 < 外右 なら
        sortTypeCorrIX0( pi, pr );                      // この間をソート
    }                                                   //
}

☆備考☆この関数はファイル「CopyClear100.cpp」に存在!
★注意★この関数は「private:属性」ですのでライブラリの
外から使用不能です!

(A)関数「sortTypeCorrIX0();」の【関数名】

「Sort」は、勿論、英単語「sort」、カタカナ語ソート・
ソーティング、詰り並び替えです!
★注意★構造体「TypeCorrIX」は、相関値関連です!
このデータは、相関値の値でソーティングします!
「0」は、データ配列を昇順≪小さい方から大きい方へ整列
≫にソートする関数を意味!
この関数は、相関値の値でデータ配列を昇順≪小さい方から
大きい方へ整列≫にソートする関数で型「TypeCorrIX」内部
にメンバー変数として連動配列へのインデックス内蔵!
「_0」は、昇順にソートする事を意味します!

(B)関数「void sortTypeCorrIX0();」の【返値】

返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!

(C)関数「sortTypeCorrIX0()」の【仮引数】

void                CopyClear::sortTypeCorrIX0(
    TypeCorrIX      *pl,                                // データの左側Ptr
    TypeCorrIX      *pr                                 // データの右側Ptr
){

「TypeCorrIX* pl,」は、データ配列左端「l=left省略」
「TypeCorrIX* pr」は、データ配列右端「r=right省略」
ここで使用する専用の型「TypeCorrIX」≪
解説『解説クラスSupport』の「(2-6)
相関値+座標」で解説≫

(D)関数「sortTypeCorrIX0()」の【アルゴリズム】

){
    TypeCorrIX      *p;                                 // 内部Ptr:中央
    TypeCorrIX      *pi;                                // 内部Ptr:  左
    TypeCorrIX      *pj;                                // 内部Ptr:  右
    double          key;                                // 中央の値
    TypeCorrIX      w;                                  // 交換用の場所

    pi  = pl;                                           // KeyDataの左側Set
    pj  = pr;                                           // KeyDataの右側Set
    p   = pi + ( (int)pj - (int)pi )                    // 右左の中央値を
                        / ( 2 * sizeof(TypeCorrIX) );   // セット
    key = p->d;                                         // 相関値部を取り出す
    do{                                                 // 以下繰り返し
        while( pi->d < key ){                           // 左側が小さい間
            pi++;                                       // 左側を中に進める
        }                                               //
        while( key < pj->d ){                           // 右側が大きい間
            pj--;                                       // 右側を中に進める
        }                                               //
        if( pi <= pj ){                                 // 左 ≦ 右 なら
            w   = *pi;                                  // 左右のキーデータ
            *pi = *pj;                                  // を交換
            *pj = w;                                    // し
            pi++;                                       // 左側を中に進める
            pj--;                                       // 右側を中に進める
        }                                               //
    }while( pi <= pj );                                 // 左≦右なら繰返し
    if( pl < pj ){                                      // 外左 < 中右 なら
        sortTypeCorrIX0( pl, pj );                      // この間をソート
    }                                                   //
    if( pi < pr ){                                      // 中左 < 外右 なら
        sortTypeCorrIX0( pi, pr );                      // この間をソート
    }                                                   //
}

(D-1)ローカル変数

){
    TypeCorrIX      *p;                                 // 内部Ptr:中央
    TypeCorrIX      *pi;                                // 内部Ptr:  左
    TypeCorrIX      *pj;                                // 内部Ptr:  右
    double          key;                                // 中央の値
    TypeCorrIX      w;                                  // 交換用の場所

「TypeCorrIX* p;」は、内部ポインタ(中央用)
「TypeCorrIX* pi;」は、内部ポインタ(左側用)
「TypeCorrIX* pj;」は、内部ポインタ(右側用)
「double key;」は、中央の値(キー比較用)
「TypeCorrIX w;」は、データ交換用の場所

(D―2)アルゴリズムコード

    pi  = pl;                                           // KeyDataの左側Set
    pj  = pr;                                           // KeyDataの右側Set
    p   = pi + ( (int)pj - (int)pi )                    // 右左の中央値を
                        / ( 2 * sizeof(TypeCorrIX) );   // セット
    key = p->d;                                         // 相関値部を取り出す
    do{                                                 // 以下繰り返し
        while( pi->d < key ){                           // 左側が小さい間
            pi++;                                       // 左側を中に進める
        }                                               //
        while( key < pj->d ){                           // 右側が大きい間
            pj--;                                       // 右側を中に進める
        }                                               //
        if( pi <= pj ){                                 // 左 ≦ 右 なら
            w   = *pi;                                  // 左右のキーデータ
            *pi = *pj;                                  // を交換
            *pj = w;                                    // し
            pi++;                                       // 左側を中に進める
            pj--;                                       // 右側を中に進める
        }                                               //
    }while( pi <= pj );                                 // 左≦右なら繰返し
    if( pl < pj ){                                      // 外左 < 中右 なら
        sortTypeCorrIX0( pl, pj );                      // この間をソート
    }                                                   //
    if( pi < pr ){                                      // 中左 < 外右 なら
        sortTypeCorrIX0( pi, pr );                      // この間をソート
    }                                                   //
}

「pi=pl;pj=pr;」は、ローカルな左側・右側をセット
「p=pi+((int)pj-(int)pi)/(2*sizeof(TypeCorrIX));」は、
ローカルなデータ配列の中央へのポインタをセット
「key=p->d;」は、左右の中央の場所のキー値「p->d」、
詰り相関値を取り出す!★備考★他の関数では中央値への
ポインタを算出せずに直接、キーデータを取り出して居ます
が、「TypeCorrIX」と正規相関(XY座標と相関値)の
メンバーとして相関値を使用するので理解し易い様に中央
ポインタを先ず作成してから、メンバーの相関値を取り出す
事にしました!
二重ループで外側の
do構文「・・外側ループ本体・・}while(pi<=pj);」と
後置ループ条件「pi<=pj」と内部のポインタの左右関係が
保たれている間繰り返す!そして最初の内側のループ
「while(*pi<key){pi++;}」は、while構文で
ループ条件「*pi<key」は、「左側の値が、比較用の値未満
」の間「pi++;」ポインタを右側に移動を繰り返すと
即ち、「左側がキーの値以上に成るまで繰り返す」、
次の内側ループ
「while(key<*pj){pj--;}」は、「右」側の値が、
比較用の値越え」の間「pj--;」ポインタを左側に
移動を繰り返すと、即ち、「右側がキーの値以下に成るまで
繰り返す」、
そしてif構文
「if(pi<=pj){w=*pi;*pi=*pj;*pj=w;pi++;pj--;}」は、
条件「pi<=pj」と左右関係が保たれていたら
「w=*pi;*pi=*pj;*pj=w;pi++;pj--;}」で先ず
「w=*pi;*pi=*pj;*pj=w;」でキーデータ左右を入れ替え、
「pi++;pj--;」とローカル左右ポインタを進める!
★備考★連動配列インデックスは「TypeCorrIX型」の
メンバー変数として内蔵されて居るのでアルゴリズム的に
入れ替える処理が無い事に留意!
「do構文」を終えると!
そして「if(pl<pj){sortTypeCorrIX0(pl,pj);}」
で再帰呼び出しを自分自身「sortTypeCorrIX0()」関数を
サブルーチン関数として条件「pl<pj」=「元々の左側が
内部の右側と左右関係が保たれて居る」なら、再帰呼び出し
「sortTypeCorrIX0(pl,pj);」を行う事で数学の
「帰納的定義法」と考えて再帰呼び出しを行った部分
「plからpjのポインタの示す左右範囲」が昇順にソート済
みと見なして処理する方法です!★備考★これが再帰呼び出
しを行う事で実現する「クイックソート」と呼ばれる通常の
データでは最速と言われているアルゴリズムです同じ様に
「if(pi<pr){sortTypeCorrIX0(pi,pr);}」で範囲
「piからpr」のポインタの示す左右範囲」が昇順にソート
済みと見なして処理します!★備考★これが、再帰呼び出し
を行う事で実現する「クイックソート」と呼ばれる通常の
データでは最速と言われているアルゴリズムですコレは、
多くの画像処理以外のプログラミングで使用されて居ますの
で数学的帰納法をアルゴリズムに応用した事を理解して下さ
い!C言語的には「再帰呼び出し」との文言で平気で多用し
ます!
★★特注「note編集機能不具合」★★
「key=(pi+((int)pj-(int)pi)/(2*sizeof(TypeCorrIX)))」
とコピペでテキストを記載したら、
「key=(pi+((int)pj-(int)pi)/(2sizeof(TypeCorrIX)))」
等と主に「*」が消える事が多々ありますので注意して手作業
で修正して居るが、全て修正出来て無い部分が有る事に留意
して読んで頂きたい!必ず、【<>code】機能で生の
テキストを必ず参考にして下さい!!

(4-15-143)関数「void sortTypeCorrIX1(
TypeCorrIX* pl,
TypeCorrIX* pr,short* plx,
short* prx){・・・}」

/************************************************************************/
/*****      QUIC-SORT:降順ソート:データ=TypeCorrIX      *****/
/************************************************************************/

void                CopyClear::sortTypeCorrIX1(
    TypeCorrIX      *pl,                                // データの左側Ptr
    TypeCorrIX      *pr                                 // データの右側Ptr
){
    TypeCorrIX      *p;                                 // 内部Ptr:中央
    TypeCorrIX      *pi;                                // 内部Ptr:  左
    TypeCorrIX      *pj;                                // 内部Ptr:  右
    double          key;                                // 中央の値
    TypeCorrIX      w;                                  // 交換用の場所

    pi  = pl;                                           // KeyDataの左側Set
    pj  = pr;                                           // KeyDataの右側Set
    p   = pi + ( (int)pj - (int)pi )                    // 右左の中央値を
                        / ( 2 * sizeof(TypeCorrIX) );   // セット
    key = p->d;                                         // 相関値部を取り出す
    do{                                                 // 以下繰り返し
        while( pi->d > key ){                           // 左側が大きい間
            pi++;                                       // 左側を中に進める
        }                                               //
        while( key > pj->d ){                           // 右側が小さい間
            pj--;                                       // 右側を中に進める
        }                                               //
        if( pi <= pj ){                                 // 左 ≦ 右 なら
            w   = *pi;                                  // 左右のキーデータ
            *pi = *pj;                                  // を交換
            *pj = w;                                    // し
            pi++;                                       // 左側を中に進める
            pj--;                                       // 右側を中に進める
        }                                               //
    }while( pi <= pj );                                 // 左≦右なら繰返し
    if( pl < pj ){                                      // 外左 < 中右 なら
        sortTypeCorrIX1( pl, pj );                      // この間をソート
    }                                                   //
    if( pi < pr ){                                      // 中左 < 外右 なら
        sortTypeCorrIX1( pi, pr );                      // この間をソート
    }                                                   //
}

☆備考☆この関数はファイル「CopyClear100.cpp」に存在!
★注意★この関数は「private:属性」ですのでライブラリの
外から使用不能です!

(A)関数「sortTypeCorrIX1();」の【関数名】

「Sort」は、勿論、英単語「sort」、カタカナ語ソート・
ソーティング、詰り並び替えです!
★注意★構造体「TypeCorrIX」は、相関値関連です!
このデータは、相関値の値でソーティングします!
「1」は、データ配列を降順≪大きい方から小さい方へ整列
≫にソートする関数を意味!
この関数は、相関値の値でデータ配列を降順≪大きい方から
小さい方へ整列≫にソートする関数で型「TypeCorrIX」内部
にメンバー変数として連動配列へのインデックス内蔵!

(B)関数「void sortTypeCorrIX1();」の【返値】

返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!

(C)関数「sortTypeCorrIX1()」の【仮引数】

void                CopyClear::sortTypeCorrIX1(
    TypeCorrIX      *pl,                                // データの左側Ptr
    TypeCorrIX      *pr                                 // データの右側Ptr
){

「TypeCorrIX* pl,」は、データ配列左端「l=left省略」
「TypeCorrIX* pr」は、データ配列右端「r=right省略」
ここで使用する専用の型「TypeCorr」≪
解説『解説クラスSupport』の「(2-6)
相関値+座標」で解説≫

(D)関数「sortTypeCorrIX1()」の【アルゴリズム】

){
    TypeCorrIX      *p;                                 // 内部Ptr:中央
    TypeCorrIX      *pi;                                // 内部Ptr:  左
    TypeCorrIX      *pj;                                // 内部Ptr:  右
    double          key;                                // 中央の値
    TypeCorrIX      w;                                  // 交換用の場所

    pi  = pl;                                           // KeyDataの左側Set
    pj  = pr;                                           // KeyDataの右側Set
    p   = pi + ( (int)pj - (int)pi )                    // 右左の中央値を
                        / ( 2 * sizeof(TypeCorrIX) );   // セット
    key = p->d;                                         // 相関値部を取り出す
    do{                                                 // 以下繰り返し
        while( pi->d > key ){                           // 左側が大きい間
            pi++;                                       // 左側を中に進める
        }                                               //
        while( key > pj->d ){                           // 右側が小さい間
            pj--;                                       // 右側を中に進める
        }                                               //
        if( pi <= pj ){                                 // 左 ≦ 右 なら
            w   = *pi;                                  // 左右のキーデータ
            *pi = *pj;                                  // を交換
            *pj = w;                                    // し
            pi++;                                       // 左側を中に進める
            pj--;                                       // 右側を中に進める
        }                                               //
    }while( pi <= pj );                                 // 左≦右なら繰返し
    if( pl < pj ){                                      // 外左 < 中右 なら
        sortTypeCorrIX1( pl, pj );                      // この間をソート
    }                                                   //
    if( pi < pr ){                                      // 中左 < 外右 なら
        sortTypeCorrIX1( pi, pr );                      // この間をソート
    }                                                   //
}

(D-1)ローカル変数

){
    TypeCorrIX      *p;                                 // 内部Ptr:中央
    TypeCorrIX      *pi;                                // 内部Ptr:  左
    TypeCorrIX      *pj;                                // 内部Ptr:  右
    double          key;                                // 中央の値
    TypeCorrIX      w;                                  // 交換用の場所

「TypeCorrIX* p;」は、内部ポインタ(中央用)
「TypeCorrIX* pi;」は、内部ポインタ(左側用)
「TypeCorrIX* pj;」は、内部ポインタ(右側用)
「double key;」は、中央の値(キー比較用)
「TypeCorrIX w;」は、データ交換用の場所

(D―2)アルゴリズムコード

    pi  = pl;                                           // KeyDataの左側Set
    pj  = pr;                                           // KeyDataの右側Set
    p   = pi + ( (int)pj - (int)pi )                    // 右左の中央値を
                        / ( 2 * sizeof(TypeCorrIX) );   // セット
    key = p->d;                                         // 相関値部を取り出す
    do{                                                 // 以下繰り返し
        while( pi->d > key ){                           // 左側が大きい間
            pi++;                                       // 左側を中に進める
        }                                               //
        while( key > pj->d ){                           // 右側が小さい間
            pj--;                                       // 右側を中に進める
        }                                               //
        if( pi <= pj ){                                 // 左 ≦ 右 なら
            w   = *pi;                                  // 左右のキーデータ
            *pi = *pj;                                  // を交換
            *pj = w;                                    // し
            pi++;                                       // 左側を中に進める
            pj--;                                       // 右側を中に進める
        }                                               //
    }while( pi <= pj );                                 // 左≦右なら繰返し
    if( pl < pj ){                                      // 外左 < 中右 なら
        sortTypeCorrIX1( pl, pj );                      // この間をソート
    }                                                   //
    if( pi < pr ){                                      // 中左 < 外右 なら
        sortTypeCorrIX1( pi, pr );                      // この間をソート
    }                                                   //
}

「pi=pl;pj=pr;」は、ローカルな左側・右側をセット
「p=pi+((int)pj-(int)pi)/(2*sizeof(TypeCorrIX));」は、
ローカルなデータ配列の中央へのポインタをセット
「key=p->d;」は、左右の中央の場所のキー値「p->d」、
詰り相関値を取り出す!★備考★他の関数では中央値への
ポインタを算出せずに直接、キーデータを取り出して居ます
が、「TypeCorrIX」と正規相関(XY座標と相関値)の
メンバーとして相関値を使用するので理解し易い様に中央
ポインタを先ず作成してから、メンバーの相関値を取り出す
事にしました!
二重ループで外側の
do構文「・・外側ループ本体・・}while(pi<=pj);」と
後置ループ条件「pi<=pj」と内部のポインタの左右関係が
保たれている間繰り返す!そして最初の内側のループ
「while(*pi>key){pi++;pix++;}」は、while構文で
ループ条件「*pi>key」は、「左側の値が、比較用の値越え
」の間「pi++;pix++;」ポインタを右側に移動を繰り返すと
即ち、「左側がキーの値以下に成るまで繰り返す」、
次の内側ループ
「while(key>*pj){pj--;pjx--;}」は、「右」側の値が、
比較用の値未満」の間「pj--;pjx--;」ポインタを左側に
移動を繰り返すと、即ち、「右側がキーの値以上に成るまで
繰り返す」、
そしてif構文
「if(pi<=pj){w=*pi;*pi=*pj;*pj=w;pi++;pj--;}」は、
条件「pi<=pj」と左右関係が保たれていたら
「w=*pi;*pi=*pj;*pj=w;pi++;pj--;}」で先ず
「w=*pi;*pi=*pj;*pj=w;」でキーデータ左右を入れ替え、
「pi++;pj--;」とローカル左右ポインタを進める!
★備考★連動配列インデックスは「TypeCorrIX型」の
メンバー変数として内蔵されて居るのでアルゴリズム的に
入れ替える処理が無い事に留意!
「do構文」を終えると!
そして「if(pl<pj){sortTypeCorrIX1(pl,pj);}」
で再帰呼び出しを自分自身「sortTypeCorrIX1()」関数を
サブルーチン関数として条件「pl<pj」=「元々の左側が
内部の右側と左右関係が保たれて居る」なら、再帰呼び出し
「sortTypeCorrIX1(pl,pj);」を行う事で数学の
「帰納的定義法」と考えて再帰呼び出しを行った部分
「plからpjのポインタの示す左右範囲」が昇順にソート済
みと見なして処理する方法です!★備考★これが再帰呼び出
しを行う事で実現する「クイックソート」と呼ばれる通常の
データでは最速と言われているアルゴリズムです同じ様に
「if(pi<pr){sortTypeCorrIX1(pi,pr);}」で範囲
「piからpr」のポインタの示す左右範囲」が昇順にソート
済みと見なして処理します!★備考★これが、再帰呼び出し
を行う事で実現する「クイックソート」と呼ばれる通常の
データでは最速と言われているアルゴリズムですコレは、
多くの画像処理以外のプログラミングで使用されて居ますの
で数学的帰納法をアルゴリズムに応用した事を理解して下さ
い!C言語的には「再帰呼び出し」との文言で平気で多用し
ます!

(4-15-144)関数「void sortXTypeXY0(TypeXY* pl,
TypeXY* pr){・・・}」

/************************************************************************/
/*****      QUIC-SORT:昇順ソート:データ=TypeXYでX座標  *****/
/*****      昇順ソート(X→Y)                                    *****/
/************************************************************************/

void            CopyClear::sortXTypeXY0(
    TypeXY      *pl,                                // データの左側Ptr
    TypeXY      *pr                                 // データの右側Ptr
){
    TypeXY      *p;                                 // 内部Ptr:中央
    TypeXY      *pi;                                // 内部Ptr:  左
    TypeXY      *pj;                                // 内部Ptr:  右
    int         keyX;                               // 中央の値:X
    int         keyY;                               // 中央の値:Y
    TypeXY      w;                                  // 交換用の場所

    pi = pl;                                        // KeyDataの左側Set
    pj = pr;                                        // KeyDataの右側Set
    p  = pi + ( (int)pj - (int)pi )                 // 右左の中央値を
                        / ( 2 * sizeof(TypeXY) );   // セット
    keyX = p->x;                                    // X座標を取り出す
    keyY = p->y;                                    // Y座標を取り出す
    do{                                             // 以下繰り返し
        for(;;){                                    // 以下繰り返し:内側
            if( pi->x < keyX ){                     // 左側が小さい間:X
                pi++;                               // 左側を中に進める
            }else if( pi->x == keyX ){              // X座標同値なら
                if( pi->y < keyY ){                 // 左側が小さい間:Y
                    pi++;                           // 左側を中に進める
                }else{                              // 大きい場合:Y
                    break;                          // 内側Loop終了
                }                                   // 
            }else{                                  // 大きい場合:X
                break;                              // 内側Loop終了
            }                                       // 
        }                                           //
        for(;;){                                    // 以下繰り返し:内側
            if( keyX < pj->x ){                     // 右側が大きい間:X
                pj--;                               // 右側を中に進める
            }else if( keyX == pj->x ){              // X座標同値なら
                if( keyY < pj->y ){                 // 右側が大きい間:Y
                    pj--;                           // 右側を中に進める
                }else{                              // 小さい場合:Y
                    break;                          // 内側Loop終了
                }                                   // 
            }else{                                  // 小さい場合:X
                break;                              // 内側Loop終了
            }                                       //
        }                                           //
        if( pi <= pj ){                             // 左 ≦ 右 なら
            w   = *pi;                              // 左右のキーデータ
            *pi = *pj;                              // を交換
            *pj = w;                                // し
            pi++;                                   // 左側を中に進める
            pj--;                                   // 右側を中に進める
        }                                           //
    }while( pi <= pj );                             // 左≦右なら繰返し
    if( pl < pj ){                                  // 外左 < 中右 なら
        sortXTypeXY0( pl, pj );                     // この間をソート
    }                                               //
    if( pi < pr ){                                  // 中左 < 外右 なら
        sortXTypeXY0( pi, pr );                     // この間をソート
    }                                               //
}

☆備考☆この関数はファイル「CopyClear100.cpp」に存在!
★注意★この関数は「private:属性」ですのでライブラリの
外から使用不能です!

(A)関数「sortXTypeXY0();」の【関数名】

「Sort」は、勿論、英単語「sort」、カタカナ語ソート・
ソーティング、詰り並び替えです!
★注意★構造体「TypeXY」は、XY座標関連です!
このデータは、XY座標の値でソーティングします!
「0」は、データ配列を昇順≪小さい方から大きい方へ整列
≫にソートする関数を意味!
この関数は、XY座標の値でデータ配列を昇順≪小さい方
から大きい方へ整列≫にソートする関数です!ここでの座標
比較は、X座標の大小を元に比較し、比較時にX座標が同値
ならば、Y座標の大小を比較します!

(B)関数「void sortXTypeXY0();」の【返値】

返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!

(C)関数「sortXTypeXY0()」の【仮引数】

void            CopyClear::sortXTypeXY0(
    TypeXY      *pl,                                // データの左側Ptr
    TypeXY      *pr                                 // データの右側Ptr
){

「TypeXY* pl,」は、データ配列左端「l=left省略」
「TypeXY* pr」は、データ配列右端「r=right省略」
ここで使用する専用の型「TypeXY」≪
解説『解説クラスSupport』の(2-1)
座標組用データ構造「座標」で解説≫

(D)関数「sortXTypeXY0()」の【アルゴリズム】

){
    TypeXY      *p;                                 // 内部Ptr:中央
    TypeXY      *pi;                                // 内部Ptr:  左
    TypeXY      *pj;                                // 内部Ptr:  右
    int         keyX;                               // 中央の値:X
    int         keyY;                               // 中央の値:Y
    TypeXY      w;                                  // 交換用の場所

    pi = pl;                                        // KeyDataの左側Set
    pj = pr;                                        // KeyDataの右側Set
    p  = pi + ( (int)pj - (int)pi )                 // 右左の中央値を
                        / ( 2 * sizeof(TypeXY) );   // セット
    keyX = p->x;                                    // X座標を取り出す
    keyY = p->y;                                    // Y座標を取り出す
    do{                                             // 以下繰り返し
        for(;;){                                    // 以下繰り返し:内側
            if( pi->x < keyX ){                     // 左側が小さい間:X
                pi++;                               // 左側を中に進める
            }else if( pi->x == keyX ){              // X座標同値なら
                if( pi->y < keyY ){                 // 左側が小さい間:Y
                    pi++;                           // 左側を中に進める
                }else{                              // 大きい場合:Y
                    break;                          // 内側Loop終了
                }                                   // 
            }else{                                  // 大きい場合:X
                break;                              // 内側Loop終了
            }                                       // 
        }                                           //
        for(;;){                                    // 以下繰り返し:内側
            if( keyX < pj->x ){                     // 右側が大きい間:X
                pj--;                               // 右側を中に進める
            }else if( keyX == pj->x ){              // X座標同値なら
                if( keyY < pj->y ){                 // 右側が大きい間:Y
                    pj--;                           // 右側を中に進める
                }else{                              // 小さい場合:Y
                    break;                          // 内側Loop終了
                }                                   // 
            }else{                                  // 小さい場合:X
                break;                              // 内側Loop終了
            }                                       //
        }                                           //
        if( pi <= pj ){                             // 左 ≦ 右 なら
            w   = *pi;                              // 左右のキーデータ
            *pi = *pj;                              // を交換
            *pj = w;                                // し
            pi++;                                   // 左側を中に進める
            pj--;                                   // 右側を中に進める
        }                                           //
    }while( pi <= pj );                             // 左≦右なら繰返し
    if( pl < pj ){                                  // 外左 < 中右 なら
        sortXTypeXY0( pl, pj );                     // この間をソート
    }                                               //
    if( pi < pr ){                                  // 中左 < 外右 なら
        sortXTypeXY0( pi, pr );                     // この間をソート
    }                                               //
}

(D-1)ローカル変数

){
    TypeXY      *p;                                 // 内部Ptr:中央
    TypeXY      *pi;                                // 内部Ptr:  左
    TypeXY      *pj;                                // 内部Ptr:  右
    int         keyX;                               // 中央の値:X
    int         keyY;                               // 中央の値:Y
    TypeXY      w;                                  // 交換用の場所

「TypeXY* p;」は、内部ポインタ(中央用)
「TypeXY* pi;」は、内部ポインタ(左側用)
「TypeXY* pj;」は、内部ポインタ(右側用)
「int keyX;」は、中央の値(キー比較用のX座標)
「int keyY;」は、中央の値(キー比較用のY座標)
「TypeXY w;」は、データ交換用の場所

(D―2)アルゴリズムコード

    pi = pl;                                        // KeyDataの左側Set
    pj = pr;                                        // KeyDataの右側Set
    p  = pi + ( (int)pj - (int)pi )                 // 右左の中央値を
                        / ( 2 * sizeof(TypeXY) );   // セット
    keyX = p->x;                                    // X座標を取り出す
    keyY = p->y;                                    // Y座標を取り出す
    do{                                             // 以下繰り返し
        for(;;){                                    // 以下繰り返し:内側
            if( pi->x < keyX ){                     // 左側が小さい間:X
                pi++;                               // 左側を中に進める
            }else if( pi->x == keyX ){              // X座標同値なら
                if( pi->y < keyY ){                 // 左側が小さい間:Y
                    pi++;                           // 左側を中に進める
                }else{                              // 大きい場合:Y
                    break;                          // 内側Loop終了
                }                                   // 
            }else{                                  // 大きい場合:X
                break;                              // 内側Loop終了
            }                                       // 
        }                                           //
        for(;;){                                    // 以下繰り返し:内側
            if( keyX < pj->x ){                     // 右側が大きい間:X
                pj--;                               // 右側を中に進める
            }else if( keyX == pj->x ){              // X座標同値なら
                if( keyY < pj->y ){                 // 右側が大きい間:Y
                    pj--;                           // 右側を中に進める
                }else{                              // 小さい場合:Y
                    break;                          // 内側Loop終了
                }                                   // 
            }else{                                  // 小さい場合:X
                break;                              // 内側Loop終了
            }                                       //
        }                                           //
        if( pi <= pj ){                             // 左 ≦ 右 なら
            w   = *pi;                              // 左右のキーデータ
            *pi = *pj;                              // を交換
            *pj = w;                                // し
            pi++;                                   // 左側を中に進める
            pj--;                                   // 右側を中に進める
        }                                           //
    }while( pi <= pj );                             // 左≦右なら繰返し
    if( pl < pj ){                                  // 外左 < 中右 なら
        sortXTypeXY0( pl, pj );                     // この間をソート
    }                                               //
    if( pi < pr ){                                  // 中左 < 外右 なら
        sortXTypeXY0( pi, pr );                     // この間をソート
    }                                               //
}

「pi=pl;pj=pr;」は、ローカルな左側・右側をセット
「p=pi+((int)pj-(int)pi)/(2*sizeof(TypeXY));」は、
ローカルなデータ配列の中央へのポインタをセット
「keyX=p->x;keyY=p->y;」は、左右の中央の場所の
キー値「p->x」とX座標、「p->y」とY座標、と今回は、
詰りXY座標値を取り出す!★備考★他の関数では中央値
へのポインタを算出せずに直接、キーデータを取り出して
居ますが、「TypeXY」と座標(X座標値Y座標値)のメン
バーとして使用するので理解し易い様に中央ポインタを先ず
作成してから、メンバーの値を取り出す事にしました!
二重ループで外側の
do構文「・・外側ループ本体・・}while(pi<=pj);」と
後置ループ条件「pi<=pj」と内部のポインタの左右関係が
保たれている間繰り返す!そして最初の内側のループ
「for(;;){・・無限ループ本体・・}」は、for無限ルー
プ構文「for(;;)」で無限ループ本体で「break;」でループ
から脱出する事でループを構築するが、無限ループ本体は、
先ず、「if(pi->x<keyX){pi++;}」で条件「pi->x<keyX」≪
詰り、左側X座標がキーの値未満≫の間「pi++;」ポインタ
を右側に移動を繰り返す、次に
「else if(pi->x==keyX){if(pi->y<keyY){pi++;}else{
break;}}」と条件「pi->x==keyX」とX座標が同値の時、
「if(pi->y<keyY){pi++;}else{break;}」と、更に条件
「pi->y<keyY」≪詰り、左側Y座標がキーの値未満≫の間
「pi++;」ポインタを右側に移動を繰り返す、そして条件
「pi->y<keyY」が不成立なら「break;」と無限ループ脱出
更に条件「pi->x==keyX」が不成立なら「break;」と無限
ループ脱出、
次の内側ループも「for(;;){・・無限ループ本体・・}」
は、for無限ループ構文「for(;;)」で無限ループ本体で
「break;」でループから脱出する事でループを構築するが、
無限ループ本体は、先ず、「if(keyX<pj->x){pj--;}」で
条件「keyX<pj->x」≪詰り、右側X座標がキーの値未満≫
の間「pj--;」ポインタを左側に移動を繰り返す、次に
「else if(keyX==pj->x){if(keyY<pj->y){pj--;}else{
break;}}」と条件「pi->x==keyX」とX座標が同値の時、
「if(keyY<pj->y){pj--;}else{break;}}」と、更に条件
「keyY<pj->y」≪詰り、右側Y座標がキーの値未満≫の
間「pj--;」ポインタを左側に移動を繰り返す、そして条件
「pi->y<keyY」が不成立なら「break;」と無限ループ脱出
更に条件「keyX==pj->x」が不成立なら「break;」と無限
ループ脱出、★備考★この関数「sortXTypeXY0()」では、
座標の比較をX座標を比較しますが、X座標とキーが同じ
場合は、Y座標で比較する事は理解していますね!
そしてif構文
「if(pi<=pj){w=*pi;*pi=*pj;*pj=w;pi++;pj--;}」は、
条件「pi<=pj」と左右関係が保たれていたら
「w=*pi;*pi=*pj;*pj=w;pi++;pj--;}」で先ず
「w=*pi;*pi=*pj;*pj=w;」でキーデータ左右を入れ替え、
「pi++;pj--;」とローカル左右ポインタを進める!
「do構文」を終えると!
そして「if(pl<pj){sortXTypeXY0(pl,pj);}」
で再帰呼び出しを自分自身「sortXTypeXY0()」関数を
サブルーチン関数として条件「pl<pj」=「元々の左側が
内部の右側と左右関係が保たれて居る」なら、再帰呼び出し
「sortXTypeXY0(pl,pj);」を行う事で数学の
「帰納的定義法」と考えて再帰呼び出しを行った部分
「plからpjのポインタの示す左右範囲」が昇順にソート済
みと見なして処理する方法です!★備考★これが再帰呼び出
しを行う事で実現する「クイックソート」と呼ばれる通常の
データでは最速と言われているアルゴリズムです同じ様に
「if(pi<pr){sortXTypeXY0(pi,pr);}」で範囲
「piからpr」のポインタの示す左右範囲」が昇順にソート
済みと見なして処理します!★備考★これが、再帰呼び出し
を行う事で実現する「クイックソート」と呼ばれる通常の
データでは最速と言われているアルゴリズムですコレは、
多くの画像処理以外のプログラミングで使用されて居ますの
で数学的帰納法をアルゴリズムに応用した事を理解して下さ
い!C言語的には「再帰呼び出し」との文言で平気で多用し
ます!

(4-15-145)関数「void sortXTypeXY1(TypeXY* pl,
TypeXY* pr){・・・}」

/************************************************************************/
/*****      QUIC-SORT:降順ソート:データ=TypeXYでX座標  *****/
/*****      降順ソート(X→Y)                                    *****/
/************************************************************************/

void            CopyClear::sortXTypeXY1(
    TypeXY      *pl,                                // データの左側Ptr
    TypeXY      *pr                                 // データの右側Ptr
){
    TypeXY      *p;                                 // 内部Ptr:中央
    TypeXY      *pi;                                // 内部Ptr:  左
    TypeXY      *pj;                                // 内部Ptr:  右
    int         keyX;                               // 中央の値:X
    int         keyY;                               // 中央の値:Y
    TypeXY      w;                                  // 交換用の場所

    pi = pl;                                        // KeyDataの左側Set
    pj = pr;                                        // KeyDataの右側Set
    p  = pi + ( (int)pj - (int)pi )                 // 右左の中央値を
                        / ( 2 * sizeof(TypeXY) );   // セット
    keyX = p->x;                                    // X座標を取り出す
    keyY = p->y;                                    // Y座標を取り出す
    do{                                             // 以下繰り返し
        for(;;){                                    // 以下繰り返し:内側
            if( pi->x > keyX ){                     // 左側が大きい間:X
                pi++;                               // 左側を中に進める
            }else if( pi->x == keyX ){              // X座標同値なら
                if( pi->y > keyY ){                 // 左側が大きい間:Y
                    pi++;                           // 左側を中に進める
                }else{                              // 小さい場合:Y
                    break;                          // 内側Loop終了
                }                                   // 
            }else{                                  // 小さい場合:X
                break;                              // 内側Loop終了
            }                                       // 
        }                                           //
        for(;;){                                    // 以下繰り返し:内側
            if( keyX > pj->x ){                     // 右側が小さい間:X
                pj--;                               // 右側を中に進める
            }else if( keyX == pj->x ){              // X座標同値なら
                if( keyY > pj->y ){                 // 右側が小さい間:Y
                    pj--;                           // 右側を中に進める
                }else{                              // 大きい場合:Y
                    break;                          // 内側Loop終了
                }                                   // 
            }else{                                  // 大きい場合:X
                break;                              // 内側Loop終了
            }                                       //
        }                                           //
        if( pi <= pj ){                             // 左 ≦ 右 なら
            w   = *pi;                              // 左右のキーデータ
            *pi = *pj;                              // を交換
            *pj = w;                                // し
            pi++;                                   // 左側を中に進める
            pj--;                                   // 右側を中に進める
        }                                           //
    }while( pi <= pj );                             // 左≦右なら繰返し
    if( pl < pj ){                                  // 外左 < 中右 なら
        sortXTypeXY1( pl, pj );                     // この間をソート
    }                                               //
    if( pi < pr ){                                  // 中左 < 外右 なら
        sortXTypeXY1( pi, pr );                     // この間をソート
    }                                               //
}

☆備考☆この関数はファイル「CopyClear100.cpp」に存在!
★注意★この関数は「private:属性」ですのでライブラリの
外から使用不能です!

(A)関数「sortXTypeXY1();」の【関数名】

「Sort」は、勿論、英単語「sort」、カタカナ語ソート・
ソーティング、詰り並び替えです!
★注意★構造体「TypeXY」は、XY座標関連です!
このデータは、XY座標の値でソーティングします!
「1」は、データ配列を降順≪大きい方から小さい方へ整列
≫にソートする関数を意味!
この関数は、XY座標の値でデータ配列を降順≪大きい方
から小さい方へ整列≫にソートする関数です!
ここでの座標比較は、X座標の大小を元に比較し、
比較時にX座標が同値ならば、Y座標の大小を比較します!

(B)関数「void sortXTypeXY1();」の【返値】

返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!

(C)関数「sortXTypeXY1()」の【仮引数】

void            CopyClear::sortXTypeXY1(
    TypeXY      *pl,                                // データの左側Ptr
    TypeXY      *pr                                 // データの右側Ptr
){

「TypeXY* pl,」は、データ配列左端「l=left省略」
「TypeXY* pr」は、データ配列右端「r=right省略」
ここで使用する専用の型「TypeXY」≪
解説『解説クラスSupport』の(2-1)
座標組用データ構造「座標」で解説≫

(D)関数「sortXTypeXY1()」の【アルゴリズム】

){
    TypeXY      *p;                                 // 内部Ptr:中央
    TypeXY      *pi;                                // 内部Ptr:  左
    TypeXY      *pj;                                // 内部Ptr:  右
    int         keyX;                               // 中央の値:X
    int         keyY;                               // 中央の値:Y
    TypeXY      w;                                  // 交換用の場所

    pi = pl;                                        // KeyDataの左側Set
    pj = pr;                                        // KeyDataの右側Set
    p  = pi + ( (int)pj - (int)pi )                 // 右左の中央値を
                        / ( 2 * sizeof(TypeXY) );   // セット
    keyX = p->x;                                    // X座標を取り出す
    keyY = p->y;                                    // Y座標を取り出す
    do{                                             // 以下繰り返し
        for(;;){                                    // 以下繰り返し:内側
            if( pi->x > keyX ){                     // 左側が大きい間:X
                pi++;                               // 左側を中に進める
            }else if( pi->x == keyX ){              // X座標同値なら
                if( pi->y > keyY ){                 // 左側が大きい間:Y
                    pi++;                           // 左側を中に進める
                }else{                              // 小さい場合:Y
                    break;                          // 内側Loop終了
                }                                   // 
            }else{                                  // 小さい場合:X
                break;                              // 内側Loop終了
            }                                       // 
        }                                           //
        for(;;){                                    // 以下繰り返し:内側
            if( keyX > pj->x ){                     // 右側が小さい間:X
                pj--;                               // 右側を中に進める
            }else if( keyX == pj->x ){              // X座標同値なら
                if( keyY > pj->y ){                 // 右側が小さい間:Y
                    pj--;                           // 右側を中に進める
                }else{                              // 大きい場合:Y
                    break;                          // 内側Loop終了
                }                                   // 
            }else{                                  // 大きい場合:X
                break;                              // 内側Loop終了
            }                                       //
        }                                           //
        if( pi <= pj ){                             // 左 ≦ 右 なら
            w   = *pi;                              // 左右のキーデータ
            *pi = *pj;                              // を交換
            *pj = w;                                // し
            pi++;                                   // 左側を中に進める
            pj--;                                   // 右側を中に進める
        }                                           //
    }while( pi <= pj );                             // 左≦右なら繰返し
    if( pl < pj ){                                  // 外左 < 中右 なら
        sortXTypeXY1( pl, pj );                     // この間をソート
    }                                               //
    if( pi < pr ){                                  // 中左 < 外右 なら
        sortXTypeXY1( pi, pr );                     // この間をソート
    }                                               //
}

(D-1)ローカル変数

){
    TypeXY      *p;                                 // 内部Ptr:中央
    TypeXY      *pi;                                // 内部Ptr:  左
    TypeXY      *pj;                                // 内部Ptr:  右
    int         keyX;                               // 中央の値:X
    int         keyY;                               // 中央の値:Y
    TypeXY      w;                                  // 交換用の場所

「TypeXY* p;」は、内部ポインタ(中央用)
「TypeXY* pi;」は、内部ポインタ(左側用)
「TypeXY* pj;」は、内部ポインタ(右側用)
「int keyX;」は、中央の値(キー比較用のX座標)
「int keyY;」は、中央の値(キー比較用のY座標)
「TypeXY w;」は、データ交換用の場所

(D―2)アルゴリズムコード

    pi = pl;                                        // KeyDataの左側Set
    pj = pr;                                        // KeyDataの右側Set
    p  = pi + ( (int)pj - (int)pi )                 // 右左の中央値を
                        / ( 2 * sizeof(TypeXY) );   // セット
    keyX = p->x;                                    // X座標を取り出す
    keyY = p->y;                                    // Y座標を取り出す
    do{                                             // 以下繰り返し
        for(;;){                                    // 以下繰り返し:内側
            if( pi->x > keyX ){                     // 左側が大きい間:X
                pi++;                               // 左側を中に進める
            }else if( pi->x == keyX ){              // X座標同値なら
                if( pi->y > keyY ){                 // 左側が大きい間:Y
                    pi++;                           // 左側を中に進める
                }else{                              // 小さい場合:Y
                    break;                          // 内側Loop終了
                }                                   // 
            }else{                                  // 小さい場合:X
                break;                              // 内側Loop終了
            }                                       // 
        }                                           //
        for(;;){                                    // 以下繰り返し:内側
            if( keyX > pj->x ){                     // 右側が小さい間:X
                pj--;                               // 右側を中に進める
            }else if( keyX == pj->x ){              // X座標同値なら
                if( keyY > pj->y ){                 // 右側が小さい間:Y
                    pj--;                           // 右側を中に進める
                }else{                              // 大きい場合:Y
                    break;                          // 内側Loop終了
                }                                   // 
            }else{                                  // 大きい場合:X
                break;                              // 内側Loop終了
            }                                       //
        }                                           //
        if( pi <= pj ){                             // 左 ≦ 右 なら
            w   = *pi;                              // 左右のキーデータ
            *pi = *pj;                              // を交換
            *pj = w;                                // し
            pi++;                                   // 左側を中に進める
            pj--;                                   // 右側を中に進める
        }                                           //
    }while( pi <= pj );                             // 左≦右なら繰返し
    if( pl < pj ){                                  // 外左 < 中右 なら
        sortXTypeXY1( pl, pj );                     // この間をソート
    }                                               //
    if( pi < pr ){                                  // 中左 < 外右 なら
        sortXTypeXY1( pi, pr );                     // この間をソート
    }                                               //
}

「pi=pl;pj=pr;」は、ローカルな左側・右側をセット
「p=pi+((int)pj-(int)pi)/(2*sizeof(TypeXY));」は、
ローカルなデータ配列の中央へのポインタをセット
「keyX=p->x;keyY=p->y;」は、左右の中央の場所の
キー値「p->x」とX座標、「p->y」とY座標、と今回は、
詰りXY座標値を取り出す!★備考★他の関数では中央値
へのポインタを算出せずに直接、キーデータを取り出して
居ますが、「TypeXY」と座標(X座標値Y座標値)のメン
バーとして使用するので理解し易い様に中央ポインタを先ず
作成してから、メンバーの座標値を取り出す事にしました!
二重ループで外側の
do構文「・・外側ループ本体・・}while(pi<=pj);」と
後置ループ条件「pi<=pj」と内部のポインタの左右関係が
保たれている間繰り返す!そして最初の内側のループ
「for(;;){・・無限ループ本体・・}」は、for無限ルー
プ構文「for(;;)」で無限ループ本体で「break;」でループ
から脱出する事でループを構築するが、無限ループ本体は、
先ず、「if(pi->x>keyX){pi++;}」で条件「pi->x>keyX」≪
詰り、左側X座標がキーの値越え≫の間「pi++;」ポインタ
を右側に移動を繰り返す、次に
「else if(pi->x==keyX){if(pi->y>keyY){pi++;}else{
break;}}」と条件「pi->x==keyX」とX座標が同値の時、
「if(pi->y>keyY){pi++;}else{break;}」と、更に条件
「pi->y>keyY」≪詰り、左側Y座標がキーの値越え≫の間
「pi++;」ポインタを右側に移動を繰り返す、そして条件
「pi->y>keyY」が不成立なら「break;」と無限ループ脱出
更に条件「pi->x==keyX」が不成立なら「break;」と無限
ループ脱出、
次の内側ループも「for(;;){・・無限ループ本体・・}」
は、for無限ループ構文「for(;;)」で無限ループ本体で
「break;」でループから脱出する事でループを構築するが、
無限ループ本体は、先ず、「if(keyX<pj->x){pj--;}」で
条件「keyX<pj->x」≪詰り、右側X座標がキーの値未満≫
の間「pj--;」ポインタを左側に移動を繰り返す、次に
「else if(keyX==pj->x){if(keyY<pj->y){pj--;}else{
break;}}」と条件「pi->x==keyX」とX座標が同値の時、
「if(keyY<pj->y){pj--;}else{break;}}」と、更に条件
「keyY<pj->y」≪詰り、右側Y座標がキーの値未満≫の
間「pj--;」ポインタを左側に移動を繰り返す、そして条件
「pi->y>keyY」が不成立なら「break;」と無限ループ脱出
更に条件「keyX==pj->x」が不成立なら「break;」と無限
ループ脱出、★備考★この関数「sortXTypeXY1()」では、
座標の比較をX座標を比較しますが、X座標とキーが同じ
場合は、Y座標で比較する事は理解していますね!
そしてif構文
「if(pi<=pj){w=*pi;*pi=*pj;*pj=w;pi++;pj--;}」は、
条件「pi<=pj」と左右関係が保たれていたら
「w=*pi;*pi=*pj;*pj=w;pi++;pj--;}」で先ず
「w=*pi;*pi=*pj;*pj=w;」でキーデータ左右を入れ替え、
「pi++;pj--;」とローカル左右ポインタを進める!
「do構文」を終えると!
そして「if(pl<pj){sortXTypeXY1(pl,pj);}」
で再帰呼び出しを自分自身「sortXTypeXY1()」関数を
サブルーチン関数として条件「pl<pj」=「元々の左側が
内部の右側と左右関係が保たれて居る」なら、再帰呼び出し
「sortXTypeXY1(pl,pj);」を行う事で数学の
「帰納的定義法」と考えて再帰呼び出しを行った部分
「plからpjのポインタの示す左右範囲」が昇順にソート済
みと見なして処理する方法です!★備考★これが再帰呼び出
しを行う事で実現する「クイックソート」と呼ばれる通常の
データでは最速と言われているアルゴリズムです同じ様に
「if(pi<pr){sortXTypeXY1(pi,pr);}」で範囲
「piからpr」のポインタの示す左右範囲」が昇順にソート
済みと見なして処理します!★備考★これが、再帰呼び出し
を行う事で実現する「クイックソート」と呼ばれる通常の
データでは最速と言われているアルゴリズムですコレは、
多くの画像処理以外のプログラミングで使用されて居ますの
で数学的帰納法をアルゴリズムに応用した事を理解して下さ
い!C言語的には「再帰呼び出し」との文言で平気で多用し
ます!
★★特注「note編集機能不具合」★★
「p=pi+((int)pj-(int)pi)/(2*sizeof(TypeXY));」と
コピペでテキストを記載したら、
「p=pi+((int)pj-(int)pi)/(2sizeof(TypeXY));」と
等と主に「*」が消える事が多々ありますので注意して手作業
で修正して居るが、全て修正出来て無い部分が有る事に留意
して読んで頂きたい!必ず、【<>code】機能で生の
テキストを必ず参考にして下さい!!

ココまでで区切り≪「private:属性」の関数の並びが、
「sortXTypeXY1()」関数までとソート系「X座標」が終了
したので次から「sortYTypeXY0()」とソート系「Y座標」
関数の説明になるので≫が良いので終わります?!
継続追加は有りません!★備考★
勿論、記載ミスは直して行きますが!
引き続き、
新規解説『解説クラスCopyClear(37)』
御贔屓下さい!

文末


いいなと思ったら応援しよう!