<?php /********************************/ /* 補間法(3次スプライン関数) */ /* coded by Y.Suganuma */ /********************************/ // 設定 $n = 5; $h = array($n); $b = array($n); $d = array($n); $g = array($n); $u = array($n); $r = array($n+1); $x = array($n+1); $y = array($n+1); $x[0] = 0.0; $x[1] = 1.0; $x[2] = 2.0; $x[3] = 3.0; $x[4] = 4.0; $x[5] = 5.0; $y[0] = 0.0; $y[1] = 1.0; $y[2] = 4.0; $y[3] = 9.0; $y[4] = 16.0; $y[5] = 25.0; // 実行と出力 $x1 = 0.0; $sp = 0.1; while ($x1 <= 5.01) { $y1 = spline($n, $x, $y, $x1, $h, $b, $d, $g, $u, $r); printf("%f %f\n", $x1, $y1); $x1 += $sp; } /**********************************/ /* 3次スプライン関数による補間 */ /* n : 区間の数 */ /* x, y : 点の座標 */ /* x1 : 補間値を求める値 */ /* h, b, d, g, u, r : 作業域 */ /* return : 補間値 */ /* coded by Y.Suganuma */ /**********************************/ function spline($n, $x, $y, $x1, $h, $b, $d, $g, $u, $r) { $i = -1; // 区間の決定 for ($i1 = 1; $i1 < $n && $i < 0; $i1++) { if ($x1 < $x[$i1]) $i = $i1 - 1; } if ($i < 0) $i = $n - 1; // ステップ1 for ($i1 = 0; $i1 < $n; $i1++) $h[$i1] = $x[$i1+1] - $x[$i1]; for ($i1 = 1; $i1 < $n; $i1++) { $b[$i1] = 2.0 * ($h[$i1] + $h[$i1-1]); $d[$i1] = 3.0 * (($y[$i1+1] - $y[$i1]) / $h[$i1] - ($y[$i1] - $y[$i1-1]) / $h[$i1-1]); } // ステップ2 $g[1] = $h[1] / $b[1]; for ($i1 = 2; $i1 < $n-1; $i1++) $g[$i1] = $h[$i1] / ($b[$i1] - $h[$i1-1] * $g[$i1-1]); $u[1] = $d[1] / $b[1]; for ($i1 = 2; $i1 < $n; $i1++) $u[$i1] = ($d[$i1] - $h[$i1-1] * $u[$i1-1]) / ($b[$i1] - $h[$i1-1] * $g[$i1-1]); // ステップ3 $k = ($i > 1) ? $i : 1; $r[0] = 0.0; $r[$n] = 0.0; $r[$n-1] = $u[$n-1]; for ($i1 = $n-2; $i1 >= $k; $i1--) $r[$i1] = $u[$i1] - $g[$i1] * $r[$i1+1]; // ステップ4 $xx = $x1 - $x[$i]; $qi = ($y[$i+1] - $y[$i]) / $h[$i] - $h[$i] * ($r[$i+1] + 2.0 * $r[$i]) / 3.0; $si = ($r[$i+1] - $r[$i]) / (3.0 * $h[$i]); $y1 = $y[$i] + $xx * ($qi + $xx * ($r[$i] + $si * $xx)); return $y1; } ?>
<?php /********************************/ /* 補間法(3次スプライン関数) */ /* coded by Y.Suganuma */ /********************************/ /****************/ /* クラスの定義 */ /****************/ class Spline { private $r = array(); private $q = array(); private $s = array(); private $x = array(); private $y = array(); private $n; /**************************/ /* コンストラクタ */ /* n1 : 区間の数 */ /* x1, y1 : 点の座標 */ /**************************/ function Spline($n1, $x1, $y1) { // 領域の確保 $this->n = $n1; $h = array(); $b = array(); $d = array(); $g = array(); $u = array(); for ($i1 = 0; $i1 <= $this->n; $i1++) { $this->x[$i1] = $x1[$i1]; $this->y[$i1] = $y1[$i1]; } // ステップ1 for ($i1 = 0; $i1 < $this->n; $i1++) $h[$i1] = $this->x[$i1+1] - $this->x[$i1]; for ($i1 = 1; $i1 < $this->n; $i1++) { $b[$i1] = 2.0 * ($h[$i1] + $h[$i1-1]); $d[$i1] = 3.0 * (($this->y[$i1+1] - $this->y[$i1]) / $h[$i1] - ($this->y[$i1] - $this->y[$i1-1]) / $h[$i1-1]); } // ステップ2 $g[1] = $h[1] / $b[1]; for ($i1 = 2; $i1 < $this->n-1; $i1++) $g[$i1] = $h[$i1] / ($b[$i1] - $h[$i1-1] * $g[$i1-1]); $u[1] = $d[1] / $b[1]; for ($i1 = 2; $i1 < $this->n; $i1++) $u[$i1] = ($d[$i1] - $h[$i1-1] * $u[$i1-1]) / ($b[$i1] - $h[$i1-1] * $g[$i1-1]); // ステップ3 $this->r[0] = 0.0; $this->r[$this->n] = 0.0; $this->r[$this->n-1] = $u[$this->n-1]; for ($i1 = $this->n-2; $i1 >= 1; $i1--) $this->r[$i1] = $u[$i1] - $g[$i1] * $this->r[$i1+1]; // ステップ4 for ($i1 = 0; $i1 < $this->n; $i1++) { $this->q[$i1] = ($this->y[$i1+1] - $this->y[$i1]) / $h[$i1] - $h[$i1] * ($this->r[$i1+1] + 2.0 * $this->r[$i1]) / 3.0; $this->s[$i1] = ($this->r[$i1+1] - $this->r[$i1]) / (3.0 * $h[$i1]); } } /******************************/ /* 補間値の計算 */ /* x1 : 補間値を求める値 */ /* return : 補間値 */ /******************************/ function value($x1) { $i = -1; // 区間の決定 for ($i1 = 1; $i1 < $this->n && $i < 0; $i1++) { if ($x1 < $this->x[$i1]) $i = $i1 - 1; } if ($i < 0) $i = $this->n - 1; // 計算 $xx = $x1 - $this->x[$i]; $y1 = $this->y[$i] + $xx * ($this->q[$i] + $xx * ($this->r[$i] + $this->s[$i] * $xx)); return $y1; } } // 設定 $n = 5; $x = array($n+1); $y = array($n+1); $x[0] = 0.0; $x[1] = 1.0; $x[2] = 2.0; $x[3] = 3.0; $x[4] = 4.0; $x[5] = 5.0; $y[0] = 0.0; $y[1] = 1.0; $y[2] = 4.0; $y[3] = 9.0; $y[4] = 16.0; $y[5] = 25.0; $spline = new Spline($n, $x, $y); // 実行と出力 $x1 = 0.0; $sp = 0.1; while ($x1 <= 5.01) { $y1 = $spline->value($x1); printf("%f %f\n", $x1, $y1); $x1 += $sp; } ?>