ライフゲームで在来と省エネ型ソースコード
ライフゲームで在来と省エネ型ソースコード
2024年9月17初稿
エッセイ『現在のデーターセンターに置ける省エネ型コン
ピューターを考察』の補足の為に具体的なソースコードとし
て「ライフゲーム」と言う良く知られている物を使用!
ライフゲームでは初期状態のみでその後の状態が決定される
碁盤のような格子があり、一つの格子はセル(細胞)と呼ば
れる。各セルには8つの近傍のセルがある (ムーア近傍) 。
各セルには「生」と「死」の2つの状態があり、あるセルの
次のステップ(世代)の状態は周囲の8つのセルの今の世代
における状態により決定される。
セルの生死は次のルールに従う。
誕生
死んでいるセルに隣接する生きたセルがちょうど3つあれば、
次の世代が誕生する。
生存
生きているセルに隣接する生きたセルが2つか3つならば、
次の世代でも生存する。
過疎
生きているセルに隣接する生きたセルが1つ以下ならば、
過疎により死滅する。
過密
生きているセルに隣接する生きたセルが4つ以上ならば、
過密により死滅する。
下に中央のセルにおける次のステップでの生死の例を示す。
生きているセルは■、死んでいるセルは□で表す。
生きているセルは■、死んでいるセルは□で表す。
1.教科書的なソースコード
/*ライフゲームで在来型ソースコード*/
/*ライフゲームで在来型CPU使用例在来型ソースコード*/
#include <stdio.h> /* 標準的なC言語システムヘッダ */
#define HSIZE 1000 /* 水平方向サイズが1000*/
#define VSIZE 1000 /* 垂直方向サイズが1000*/
typedef unsigned char CELL; /* 生死情報型名 */
CELL stage[1000000]; /* ライフゲームの実現ステージとし縦横1000×1000サイズ領域 */
/* ステージをクリア≪全て生者が無い状態に初期化≫ */
void ClearStage(void) /* 仮引数も関数返値も無い */
{
int i; /* カウンタ:インデックス */
for( i = 0; i < 1000000; i++ ){ /* お馴染みforループ構文で1000000回繰り返す */
stage[i] = 0; /* ライフゲームの実現ステージに生者が無い状態=0セット */
}
}
/* ライフゲームの実現ステージ≪1次元データ配列の記録領域だが2次元と見なす≫縦横を */
/* 2次元座標XY指定で位置の生死セル状態を取出する関数 */
int getCELL( int x, int y ){ /* 仮引数で座標XY指定 */
return( stage[ x + y * HSIZE] ); /* 1次元データを2次元と見なしてアクセスしてデータ取り出し */
}
/* ライフゲームの実現ステージ≪1次元データ配列の記録領域だが2次元と見なす≫縦横を */
/* 2次元座標XY指定で位置の生死セル状態変更(セット)する関数 */
void putCELL( int x, int y, int d ){ /* 仮引数で座標XY指定と生死データ指定、関数返値は無い */
stage[ x + y * HSIZE] = d; /* 1次元データを2次元と見なしてアクセスしてデータを */
/* 状態変更(セット) */
}
/* ライフゲームの一世代進行≪世代交代≫ */
/* ★備考★極、教科書で記載する様なソースコード */
void generationalChange(void) /* 仮引数も関数返値も無い */
{
int x; /* 横(水平或はX座標)方向の位置 */
int y; /* 縦(垂直或はY座標)方向の位置 */
int sum; /* 注視点の生死判定する隣接セル生死把握の為の生セル合計 */
for( y = 0; y < VSIZE; y++ ){ /* 2重ループの外側「縦(垂直)方向Y」増加ループ */
for( x = 0; x < HSIZE; x++ ){ /* 2重ループの内側「横(水平)方向X」増加ループ */
sum = getCELL( x - 1, y - 1 ) /* 注視点の斜め左上隣 */
+= getCELL( x, y - 1 ) /* 注視点の上隣 */
+= getCELL( x + 1, y - 1 ) /* 注視点の斜め右上隣 */
+= getCELL( x - 1, y ) /* 注視点の左隣 */
+= getCELL( x + 1, y ) /* 注視点の右隣 */
+= getCELL( x - 1, y + 1 ) /* 注視点の斜め左下隣 */
+= getCELL( x, y + 1 ) /* 注視点の下隣 */
+= getCELL( x + 1, y + 1 ); /* 注視点の斜め右下隣と注視点周辺生セル合計 */
if( 3 == sum ){ /* セル誕生条件なら */
putCELL( x, y, 1 ); /* 誕生≪セルの値を「1」にセット≫ */
}else if( 1 <= sum ){ /* 過疎条件ならば */
putCELL( x, y, 0 ); /* 死滅≪セルの値を「0」にセット≫ */
}else if( 4 >= sum ){ /* 過密条件ならば */
putCELL( x, y, 0 ); /* 死滅≪セルの値を「0」にセット≫ */
} /* if構文の終端 */
} /* 内側「横(水平)方向X」増加ループ終端 */
} /* 外側「縦(垂直)方向Y」増加ループ終端 */
}
/* ライフゲームの遊び方 */
void example1(void) /* 例文1 */
{
char buf[100]; /* 印刷用文字列バッファ */
int i; /* インデックス・カウンタ */
int x; /* X座標 */
int y; /* Y座標 */
ClearStage(); /* 全て死の世界 */
putCELL( 1, 1, 1 ); /* 生者をセット */
putCELL( 2, 1, 1 ); /* 生者をセット */
putCELL( 3, 1, 1 ); /* 生者をセット */
putCELL( 1, 2, 1 ); /* 生者をセット */
putCELL( 1, 3, 1 ); /* 生者をセット */
for( y = 0; y < 100; ){ /* 先頭(上)から100行印刷ループ */
for( i = 0; i < 100; i++ ){ /* 印刷用文字列バッファを */
buf[i] = 0; /* 0クリア */
} /* */
for( x = 0; x < 100; ){ /* 先頭(最左側)から100セル印刷ループ */
if( 0 == getCELL( x, y ) ){ /* セルに死者しか無い */
buf[x] = ' '; /* 文字「空白」をバッファにセット */
}else{ /* セルに生者発見 */
buf[x] = '*'; /* 文字「アスタリスク」をバッファにセット */
} /* if構文終端 */
} /* for構文(X座標)終端 */
printf( "%s\n", buf ); /* 文字バッファを印刷 */
} /* for構文(Y座標)終端 */
generationalChange(); /* ライフゲームの一世代進行 */
for( y = 0; y < 100; ){ /* 先頭(上)から100行印刷ループ */
for( i = 0; i < 100; i++ ){ /* 印刷用文字列バッファを */
buf[i] = 0; /* 0クリア */
} /* */
for( x = 0; x < 100; ){ /* 先頭(最左側)から100セル印刷ループ */
if( 0 == getCELL( x, y ) ){ /* セルに死者しか無い */
buf[x] = ' '; /* 文字「空白」をバッファにセット */
}else{ /* セルに生者発見 */
buf[x] = '*'; /* 文字「アスタリスク」をバッファにセット */
} /* if構文終端 */
} /* for構文(X座標)終端 */
printf( "%s\n", buf ); /* 文字バッファを印刷 */
} /* for構文(Y座標)終端 */
}
在来型CPUでの在来型ソースコードで取り敢えず
ライフゲームのプログラムを作成して見ました!
省エネ型は、引き続き、このエッセイに記載しますが、
先ずは、理解して頂く為にここまでとします!
2.私の画像処理ライブラリに多用しているポイント多用のソースコード
/* ライフゲームの一世代進行≪世代交代≫ */
/* ★備考★私が画像処理ライブラリ開発に使用した高速化処理ソースコード */
void generationalChange(void) /* 仮引数も関数返値も無い */
{
int x; /* 横(水平或はX座標)方向の位置カウンタ */
int y; /* 縦(垂直或はY座標)方向の位置カウンタ */
CELL* px; /* 横(水平或はX座標)方向の位置をポインタ変数表現 */
CELL* py; /* 縦(垂直或はY座標)方向の位置をポインタ変数表現 */
int sum; /* 注視点の生死判定する隣接セル生死把握の為の生セル合計 */
py = stage; /* ポインタ原点をセット */
for( y = VSIZE; --y >= 0; py -= HSIZE ){ /* 2重ループの外側「縦(垂直)方向Y」増加ループ */
px = py; /* 「横(水平)方向X」ポインタ原点をセット */
for( x = HSIZE; --x >= 0; px-- ){ /* 2重ループの内側「横(水平)方向X」増加ループ */
sum = *(px - 1 - HSIZE ) /* 注視点の斜め左上隣 */
+= *(px - HSIZE ) /* 注視点の上隣 */
+= *(px + 1 - HSIZE ) /* 注視点の斜め右上隣 */
+= *(px - 1 ) /* 注視点の左隣 */
+= *(px x + 1 ) /* 注視点の右隣 */
+= *(px - 1 + HSIZE ) /* 注視点の斜め左下隣 */
+= *(px + HSIZE ) /* 注視点の下隣 */
+= *(px+ 1 + HSIZE ); /* 注視点の斜め右下隣 */
if( 3 == sum ){ /* セル誕生条件なら */
*px = 1; /* 誕生≪セルの値を「1」にセット≫ */
}else if( 1 <= sum ){ /* 過疎条件ならば */
*px = 0; /* 死滅≪セルの値を「0」にセット≫ */
}else if( 4 >= sum ){ /* 過密条件ならば */
*px = 0; /* 死滅≪セルの値を「0」にセット≫ */
} /* if構文の終端 */
} /* 内側「横(水平)方向X」増加ループ終端 */
} /* 外側「縦(垂直)方向Y」増加ループ終端 */
}