<?php
print (3 + 5)."\n";
print (3 + 5)."\n";
print (3 - 5)."\n";
print (3 * 5)."\n";
print pow(3, 5)."\n";
print (5 / 3)."\n";
print (int)(5 / 3)."\n";
print (5 % 3)."\n";

echo  3 * 5, "\n";

printf("%3d\n",     3 * 5);
printf("%23.20f\n", 5 / 3);
?>
<?php
$i = 3 * 5;
print "3 * 5 = $i\n";
print "3 * 5 = ".$i."\n";

printf("3 * 5 = %d\n", $i);

echo "3 * 5 = $i\n";
echo "3 * 5 = ".$i."\n";
echo "3 * 5 = ", $i, "\n";
?>
<?php
foreach (range(1, 9) as $i)
{
    echo "$i, ";
}
echo "\n";
?>
<?php
foreach (range(1, 9) as $i)
{
    if ($i % 3 == 0)
    {
        echo "$i, ";
    }
}
echo "\n";
?>
<?php
error_reporting(E_NOTICE);

$sum = 0;
foreach (range(1, 99) as $i)
{
    if ($i % 3 == 0)
    {
        $sum += $i;
    }
}
echo "$sum\n";
?>
<?php
array_map(function ($n) {echo $n, ",";}, range(1,9))
?>
<?php
$ary = array_filter(range(1,9), function ($n) {return ($n % 3 == 0);});
array_map(function ($n) {echo $n, ",";}, $ary);
?>
<?php
$ary = array_filter(range(1,9), function ($n) {return ($n % 3 == 0);});
echo array_reduce($ary, function($x, $y) {return $x + $y;}, 0);
?>
<?php
# 初項:a, 公差:a で 上限:lim の数列の総和を返す関数
function sn($a, $lim)
{
    $n = (int)($lim / $a);     # 項数:n  =  上限:lim / 公差:a
    $l = $n * $a;              # 末項:l  =  項数:n   * 公差:a
    return ($a + $l) * $n / 2; # 総和:sn = (初項:a   + 末項:l) * 項数:n / 2
}

# 3 の倍数の合計
$sum = sn(3, 999);
echo $sum, "\n";
?>
<?php
# 10000 までの 自然数の和
# 項目数 n = 10000
$n = 10000;
echo ($n * ($n + 1) / 2), "\n";
?>
<?php
# 10000 までの 偶数の和
# 項目数 n = 5000
$n = 10000 / 2;
echo ($n * ($n + 1)), "\n";
?>
<?php
# 10000 までの 奇数の和
# 項目数 n = 5000
$n = 10000 / 2;
echo pow($n, 2), "\n";
?>
<?php
# 1000 までの 自然数の2乗の和
$n = 1000;
echo ($n * ($n + 1) * (2 * $n + 1) / 6), "\n";
?>
<?php
# 100 までの 自然数の3乗の和
$n = 100;
echo (pow($n, 2) * pow(($n + 1), 2) / 4), "\n";
?>
<?php
# 初項 2, 公比 3, 項数 10 の等比数列の和
$n = 10;
$a = 2;
$r = 3;
echo (($a * (pow($r,  $n) - 1)) / ($r - 1)), "\n";
?>
<?php
$a = 5;  # 初項 5
$d = 3;  # 公差 3
$n = 10; # 項数 10
$p = 1;  # 積

foreach (range(1, $n) as $i)
{
    $m = $a + ($d * ($i - 1));
    $p *= $m;
}
echo $p;
?>
<?php
# 初項 5, 公差 3, 項数 10 の数列の積を表示する
echo product(5, 3, 10);

function product($m, $d, $n)
{
    if ($n == 0)
        return 1;
    else
        return $m * product($m + $d, $d, $n - 1);
}
?>
<?php
# 階乗を求める関数
function Fact($n)
{
    if ($n <= 1)
        return 1;
    else
        return $n * Fact($n - 1);
}

# 10の階乗
echo Fact(10), "\n";
echo 10 * 9 * 8 * 7 * 6 * 5 * 4 * 3 * 2 * 1, "\n";
?>
<?php
# 下降階乗冪
function FallingFact($x, $n)
{
    if ($n <= 1)
        return $x;
    else
        return $x * FallingFact($x - 1, $n - 1);
}

# 10 から 6 までの 総乗
echo FallingFact(10, 5), "\n";
echo 10 * 9 * 8 * 7 * 6, "\n";
?>
# 上昇階乗冪
function RisingFact($x, $n)
{
    if ($n <= 1)
        return $x;
    else
        return $x * RisingFact($x + 1, $n - 1);
}

# 10 から 14 までの 総乗
echo RisingFact(10, 5), "\n";
echo 10 * 11 * 12 * 13 * 14, "\n";
<?php
# 階乗
function Fact($n)
{
    if ($n <= 1)
        return 1;
    else
        return $n * Fact($n - 1);
}

# 下降階乗冪
function FallingFact($x, $n)
{
    if ($n <= 1)
        return $x;
    else
        return $x * FallingFact($x - 1, $n - 1);
}

# 順列 (異なる 10 個のものから 5 個取ってできる順列の総数)
$n = 10;
$r = 5;
echo Fact($n) / Fact($n - $r), "\n";
echo FallingFact($n, $r), "\n";
?>
<?php
# 重複順列 (異なる 10 個のものから重複を許して 5 個取ってできる順列の総数)
$n = 10;
$r = 5;
echo pow($n, $r), "\n";
?>
<?php
# 組合せ
function Comb($n, $r)
{
    if ($r == 0 || $r == $n)
        return 1;
    elseif ($r == 1)
        return $n;
    else
        return Comb($n - 1, $r - 1) + Comb($n - 1, $r);
}

# 組合せ (異なる 10 個のものから 5 個取ってできる組合せの総数)
$n = 10;
$r = 5;
echo Comb($n, $r), "\n";
?>
<?php
# 組合せ
function Comb($n, $r)
{
    if ($r == 0 || $r == $n)
        return 1;
    elseif ($r == 1)
        return $n;
    else
        return Comb($n - 1, $r - 1) + Comb($n - 1, $r);
}

# 重複組合せ (異なる 10 個のものから重複を許して 5 個とる組合せの総数)
$n = 10;
$r = 5;
echo Comb($n + $r - 1, $r), "\n";
?>
<?php
# 自作の正弦関数
function mySin($x, $n, $nega, $numerator, $denominator, $y)
{
    $m           = 2 * $n;
    $denominator = $denominator * ($m + 1) * $m;
    $numerator   = $numerator * $x * $x;
    $a           = $numerator / $denominator;
    # 十分な精度になったら処理を抜ける
    if ($a <= 0.00000000001)
        return $y;
    else
        return $y + mySin($x, ++$n, !$nega, $numerator, $denominator, $nega ? $a : -$a);
}

foreach (range(0, 24) as $i)
{
    $degree = $i * 15;
    if ($degree % 30 == 0 || $degree % 45 == 0)
    {
        $radian = deg2rad($degree);
        # 自作の正弦関数
        $d1     = mySin($radian, 1, false, $radian, 1.0, $radian);
        # 標準の正弦関数
        $d2     = sin($radian);
        # 標準関数との差異
        printf("%3d : %13.10f - %13.10f = %13.10f\n", $degree, $d1, $d2, $d1 - $d2);
    }
}
?>
<?php
# 自作の余弦関数
function myCos($x, $n, $nega, $numerator, $denominator, $y)
{
    $m           = 2 * $n;
    $denominator = $denominator * $m * ($m - 1);
    $numerator   = $numerator * $x * $x;
    $a           = $numerator / $denominator;
    # 十分な精度になったら処理を抜ける
    if ($a <= 0.00000000001)
        return $y;
    else
        return $y + myCos($x, ++$n, !$nega, $numerator, $denominator, $nega ? $a : -$a);
}

foreach (range(0, 24) as $i)
{
    $degree = $i * 15;
    if ($degree % 30 == 0 || $degree % 45 == 0)
    {
        $radian = deg2rad($degree);
        # 自作の余弦関数
        $d1     = myCos($radian, 1, false, 1.0, 1.0, 1.0);
        # 標準の余弦関数
        $d2     = cos($radian);
        # 標準関数との差異
        printf("%3d : %13.10f - %13.10f = %13.10f\n", $degree, $d1, $d2, $d1 - $d2);
    }
}
?>
<?php
# 自作の正接関数
function myTan($x, $x2, $n, $t)
{
    $t = $x2 / ($n - $t);
    $n -= 2;
    if ($n <= 1)
        return $x / (1 - $t);
    else
        return myTan($x, $x2, $n, $t);
}
foreach (range(0, 12) as $i)
{
    if (($i * 15) % 180 != 0)
    {
        $degree = $i * 15 - 90;
        $radian = deg2rad($degree);
        $x2     = $radian * $radian;
        # 自作の正接関数
        $d1     = myTan($radian, $x2, 15, 0.0); # 15:必要な精度が得られる十分大きな奇数
        # 標準の正接関数
        $d2     = tan($radian);
        # 標準関数との差異
        printf("%3d : %13.10f - %13.10f = %13.10f\n", $degree, $d1, $d2, $d1 - $d2);
    }
}
?>
<?php
# 自作の指数関数
function myExp($x, $n, $numerator, $denominator, $y)
{
    $denominator = $denominator * $n;
    $numerator   = $numerator   * $x;
    $a           = $numerator / $denominator;
    # 十分な精度になったら処理を抜ける
    if (abs($a) <= 0.00000000001)
        return $y;
    else
        return $y + myExp($x, ++$n, $numerator, $denominator, $a);
}

foreach (range(0, 20) as $i)
{
    $x  = ($i - 10) / 4.0;
    # 標準の指数関数
    $d1 = exp($x);
    # 自作の指数関数
    $d2 = myExp($x, 1, 1.0, 1.0, 1.0);
    # 標準関数との差異
    printf("%5.2f : %13.10f - %13.10f = %13.10f\n", $x, $d1, $d2, $d1 - $d2);
}
?>
<?php
# 自作の指数関数
function myExp($x, $x2, $n, $t)
{
    $t = $x2 / ($n + $t);
    $n -= 4;

    if ($n < 6)
        return 1 + ((2 * $x) / (2 - $x + $t));
    else
        return myExp($x, $x2, $n, $t);
}

foreach (range(0, 20) as $i)
{
    $x  = ($i - 10) / 4.0;
    # 標準の指数関数
    $d1 = exp($x);
    # 自作の指数関数
    $x2 = $x * $x;
    $d2 = myExp($x, $x2, 30, 0.0); # 30:必要な精度が得られるよう, 6から始めて4ずつ増加させる
    # 標準関数との差異
    printf("%5.2f : %13.10f - %13.10f = %13.10f\n", $x, $d1, $d2, $d1 - $d2);
}
?>
<?php
# 自作の対数関数
function myLog($x2, $numerator, $denominator, $y)
{
    $denominator = $denominator + 2;
    $numerator   = $numerator   * $x2 * $x2;
    $a           = $numerator / $denominator;
    # 十分な精度になったら処理を抜ける
    if (abs($a) <= 0.00000000001)
        return $y;
    else
        return $y + myLog($x2, $numerator, $denominator, $a);
}

foreach (range(1, 20) as $i)
{
    $x  = $i / 5.0;
    # 標準の対数関数
    $d1 = log($x);
    # 自作の対数関数
    $x2 = ($x - 1) / ($x + 1);
    $d2 = 2 * myLog($x2, $x2, 1.0, $x2);
    # 標準関数との差異
    printf("%5.2f : %13.10f - %13.10f = %13.10f\n", $x, $d1, $d2, $d1 - $d2);
}
?>
<?php
# 自作の対数関数
function myLog($x, $n, $t)
{
    $n2 = $n;
    $x2 = $x;
    if ($n > 3)
    {
        if ($n % 2 == 0)
            $n2 = 2;
        $x2 = $x * (int)($n / 2);
    }
    $t = $x2 / ($n2 + $t);

    if ($n <= 2)
        return $x / (1 + $t);
    else
        return myLog($x, --$n, $t);
}

foreach (range(1, 20) as $i)
{
    $x  = $i / 5.0;
    # 標準の対数関数
    $d1 = log($x);
    # 自作の対数関数
    $d2 = myLog($x - 1, 27, 0.0); # 27:必要な精度が得られる十分大きな奇数
    # 標準関数との差異
    printf("%5.2f : %13.10f - %13.10f = %13.10f\n", $x, $d1, $d2, $d1 - $d2);
}
?>
<?php
# 自作の双曲線正弦関数
function mySinh($x, $n, $numerator, $denominator, $y)
{
    $m           = 2 * $n;
    $denominator = $denominator * ($m + 1) * $m;
    $numerator   = $numerator * $x * $x;
    $a           = $numerator / $denominator;

    # 十分な精度になったら処理を抜ける
    if (abs($a) <= 0.00000000001)
        return $y;
    else
        return $y + mySinh($x, ++$n, $numerator, $denominator, $a);
}

foreach (range(0, 20) as $i)
{
    $x  = $i - 10;
    # 自作の双曲線正弦関数
    $d1 = mySinh($x, 1, $x, 1.0, $x);
    # 標準の双曲線正弦関数
    $d2 = sinh($x);
    # 標準関数との差異
    printf("%3d : %17.10f - %17.10f = %13.10f\n", $x, $d1, $d2, $d1 - $d2);
}
?>
<?php
# 自作の双曲線余弦関数
function myCosh($x, $n, $numerator, $denominator, $y)
{
    $m           = 2 * $n;
    $denominator = $denominator * $m * ($m - 1);
    $numerator   = $numerator * $x * $x;
    $a           = $numerator / $denominator;

    # 十分な精度になったら処理を抜ける
    if (abs($a) <= 0.00000000001)
        return $y;
    else
        return $y + myCosh($x, ++$n, $numerator, $denominator, $a);
}

foreach (range(0, 20) as $i)
{
    $x  = $i - 10;
    # 自作の双曲線余弦関数
    $d1 = myCosh($x, 1, 1.0, 1.0, 1.0);
    # 標準の双曲線余弦関数
    $d2 = cosh($x);
    # 標準関数との差異
    printf("%3d : %17.10f - %17.10f = %13.10f\n", $x, $d1, $d2, $d1 - $d2);
}
?>
<?php
$a = 0;
$b = 1;

# 台形則で積分
$n = 2;
foreach (range(1, 10) as $j)
{
    $h = ($b - $a) / $n;
    $s = 0;
    $x = $a;
    foreach (range(1, ($n - 1)) as $i)
    {
        $x += $h;
        $s += f($x);
    }
    $s = $h * ((f($a) + f($b)) / 2 + $s);
    $n *= 2;

    # 結果を π と比較
    printf("%2d : %13.10f, %13.10f\n", $j, $s, $s - M_PI);
}

function f($x)
{
    return 4 / (1 + $x * $x);
}
?>
<?php
$a = 0;
$b = 1;

# 中点則で積分
$n = 2;
foreach (range(1, 10) as $j)
{
    $h = ($b - $a) / $n;
    $s = 0;
    $x = $a + ($h / 2);
    foreach (range(1, $n) as $i)
    {
        $s += f($x);
        $x += $h;
    }
    $s *= $h;
    $n *= 2;

    # 結果を π と比較
    printf("%2d : %13.10f, %13.10f\n", $j, $s, $s - M_PI);
}

function f($x)
{
    return 4 / (1 + $x * $x);
}
?>
<?php
$a = 0;
$b = 1;

# Simpson則で積分
$n = 2;
foreach (range(1, 5) as $j)
{
    $h  = ($b - $a) / $n;
    $s2 = 0;
    $s4 = 0;
    $x  = $a + $h;
    foreach (range(1, ($n / 2)) as $i)
    {
        $s4 += f($x);
        $x  += $h;
        $s2 += f($x);
        $x  += $h;
    }
    $s2 =  ($s2 - f($b)) * 2 + f($a) + f($b);
    $s4 *= 4;
    $s  =  ($s2 + $s4) * $h / 3;
    $n  *= 2;

    # 結果を π と比較
    printf("%2d : %13.10f, %13.10f\n", $j, $s, $s - M_PI);
}

function f($x)
{
    return 4 / (1 + $x * $x);
}
?>
<?php
$a = 0;
$b = 1;

$t = array();

# 台形則で積分
$n = 2;
foreach (range(1, 6) as $i)
{
    $h = ($b - $a) / $n;
    $s = 0;
    $x = $a;
    foreach (range(1, ($n - 1)) as $j)
    {
        $x += $h;
        $s += f($x);
    }
    # 結果を保存
    $t[$i][1] = $h * ((f($a) + f($b)) / 2 + $s);
    $n *= 2;
}

# Richardsonの補外法
$n = 4;
foreach (range(2, 6) as $j)
{
    foreach (range($j, 6) as $i)
    {
        $t[$i][$j] = $t[$i][$j - 1] + ($t[$i][$j - 1] - $t[$i - 1][$j - 1]) / ($n - 1);
        if ($i == $j)
        {
            # 結果を π と比較
            printf("%2d : %13.10f, %13.10f\n", $j, $t[$i][$j], $t[$i][$j] - M_PI);
        }
    }
    $n *= 4;
}

function f($x)
{
    return 4 / (1 + $x * $x);
}
?>
<?php
# データ点の数 - 1
define("N", 6);

$x = array();
$y = array();

# 1.5刻みで -4.5〜4.5 まで, 7点だけ値をセット
foreach (range(0, N) as $i)
{
    $d = $i * 1.5 - 4.5;
    $x[$i] = $d;
    $y[$i] = f($d);
}

# 0.5刻みで 与えられていない値を補間
foreach (range(0, 18) as $i)
{
    $d  = $i * 0.5 - 4.5;
    $d1 = f($d);
    $d2 = lagrange($d, $x, $y);

    # 元の関数と比較
    printf("%5.2f\t%8.5f\t%8.5f\t%8.5f\n", $d, $d1, $d2, $d1 - $d2);
}

# 元の関数
function f($x)
{
    return $x - pow($x, 3) / (3 * 2) + pow($x, 5) / (5 * 4 * 3 * 2);
}

# Lagrange (ラグランジュ) 補間
function lagrange($d, $x, $y)
{
    $sum = 0;
    foreach (range(0, N) as $i)
    {
        $prod = $y[$i];
        foreach (range(0, N) as $j)
        {
            if ($j != $i)
            {
                $prod *= ($d - $x[$j]) / ($x[$i] - $x[$j]);
            }
        }
        $sum += $prod;
    }
    return $sum;
}
?>
<?php
# データ点の数 - 1
define("N", 6);

$x = array();
$y = array();

# 1.5刻みで -4.5〜4.5 まで, 7点だけ値をセット
foreach (range(0, N) as $i)
{
    $d = $i * 1.5 - 4.5;
    $x[$i] = $d;
    $y[$i] = f($d);
}

# 0.5刻みで 与えられていない値を補間
foreach (range(0, 18) as $i)
{
    $d  = $i * 0.5 - 4.5;
    $d1 = f($d);
    $d2 = neville($d, $x, $y);

    # 元の関数と比較
    printf("%5.2f\t%8.5f\t%8.5f\t%8.5f\n", $d, $d1, $d2, $d1 - $d2);
}

# 元の関数
function f($x)
{
    return $x - pow($x, 3) / (3 * 2) + pow($x, 5) / (5 * 4 * 3 * 2);
}

# Neville (ネヴィル) 補間
function neville($d, $x, $y)
{
    $w = array();
    foreach (range(0, N) as $i)
    {
        $w[0][$i] = $y[$i];
    }

    foreach (range(1, N) as $j)
    {
        foreach (range(0, N - $j) as $i)
        {
            $w[$j][$i] = $w[$j-1][$i+1] + ($w[$j-1][$i+1] - $w[$j-1][$i]) * ($d - $x[$i+$j]) / ($x[$i+$j] - $x[$i]);
        }
    }
    return $w[N][0];
}
?>
<?php
# データ点の数 - 1
define("N", 6);

$x = array();
$y = array();

# 1.5刻みで -4.5〜4.5 まで, 7点だけ値をセット
foreach (range(0, N) as $i)
{
    $d1 = $i * 1.5 - 4.5;
    $x[$i] = $d1;
    $y[$i] = f($d1);
}

# 差分商の表を作る
$d = array();
foreach (range(0, N) as $j)
{
    $d[0][$j] = $y[$j];
}
foreach (range(1, N) as $i)
{
    foreach (range(0, N - $i) as $j)
    {
        $d[$i][$j] = ($d[$i-1][$j+1] - $d[$i-1][$j]) / ($x[$j+$i] - $x[$j]);
    }
}
# n階差分商
$a = array();
foreach (range(0, N) as $j)
{
    $a[$j] = $d[$j][0];
}

# 0.5刻みで 与えられていない値を補間
foreach (range(0, 18) as $i)
{
    $d1 = $i * 0.5 - 4.5;
    $d2 = f($d1);
    $d3 = newton($d1, $x, $a);

    # 元の関数と比較
    printf("%5.2f\t%8.5f\t%8.5f\t%8.5f\n", $d1, $d2, $d3, $d2 - $d3);
}

# 元の関数
function f($x)
{
    return $x - pow($x, 3) / (3 * 2) + pow($x, 5) / (5 * 4 * 3 * 2);
}

# Newton (ニュートン) 補間
function newton($d, $x, $a)
{
    $sum = $a[0];
    foreach (range(1, N) as $i)
    {
        $prod = $a[$i];
        foreach (range(0, $i - 1) as $j)
        {
            $prod *= ($d - $x[$j]);
        }
        $sum += $prod;
    }
    return $sum;
}
?>
<?php
# データ点の数 - 1
define("N",    6);
define("Nx2", 13);

$x  = array();
$y  = array();
$yd = array();

# 1.5刻みで -4.5〜4.5 まで, 7点だけ値をセット
foreach (range(0, N) as $i)
{
    $d1     = $i * 1.5 - 4.5;
    $x[$i]  = $d1;
    $y[$i]  = f($d1);
    $yd[$i] = fd($d1);
}

# 差分商の表を作る
$z = array();
$d = array();
foreach (range(0, Nx2) as $i)
{
    $j        = (int)($i / 2);
    $z[$i]    = $x[$j];
    $d[0][$i] = $y[$j];
}
foreach (range(1, Nx2) as $i)
{
    foreach (range(0, Nx2 - $i) as $j)
    {
        if ($i == 1 && $j % 2 == 0)
            $d[$i][$j] = $yd[(int)($j / 2)];
        else
            $d[$i][$j] = ($d[$i-1][$j+1] - $d[$i-1][$j]) / ($z[$j+$i] - $z[$j]);
    }
}
# n階差分商
$a = array();
foreach (range(0, Nx2) as $j)
{
    $a[$j] = $d[$j][0];
}

# 0.5刻みで 与えられていない値を補間
foreach (range(0, 18) as $i)
{
    $d1 = $i * 0.5 - 4.5;
    $d2 = f($d1);
    $d3 = hermite($d1, $z, $a);

    # 元の関数と比較
    printf("%5.2f\t%8.5f\t%8.5f\t%8.5f\n", $d1, $d2, $d3, $d2 - $d3);
}

# 元の関数
function f($x)
{
    return $x - pow($x, 3) / (3 * 2) + pow($x, 5) / (5 * 4 * 3 * 2);
}
# 導関数
function fd($x)
{
    return 1 - pow($x, 2) / 2 + pow($x, 4) / (4 * 3 * 2);
}

# Hermite (エルミート) 補間
function hermite($d, $z, $a)
{
    $sum = $a[0];
    foreach (range(1, Nx2) as $i)
    {
        $prod = $a[$i];
        foreach (range(0, $i - 1) as $j)
        {
            $prod *= ($d - $z[$j]);
        }
        $sum += $prod;
    }
    return $sum;
}
?>
<?php
# データ点の数 - 1
define("N", 6);

$x = array();
$y = array();

# 1.5刻みで -4.5〜4.5 まで, 7点だけ値をセット
foreach (range(0, N) as $i)
{
    $d1 = $i * 1.5 - 4.5;
    $x[$i] = $d1;
    $y[$i] = f($d1);
}

# 3項方程式の係数の表を作る
$a = array();
$b = array();
$c = array();
$d = array();
foreach (range(1, N - 1) as $i)
{
    $a[$i] =         $x[$i]   - $x[$i-1];
    $b[$i] = 2.0 *  ($x[$i+1] - $x[$i-1]);
    $c[$i] =         $x[$i+1] - $x[$i];
    $d[$i] = 6.0 * (($y[$i+1] - $y[$i]) / ($x[$i+1] - $x[$i]) - ($y[$i] - $y[$i-1]) / ($x[$i] - $x[$i-1]));
}
# 3項方程式を解く (ト−マス法)
$g = array();
$s = array();
$g[1] = $b[1];
$s[1] = $d[1];
foreach (range(2, N - 1) as $i)
{
    $g[$i] = $b[$i] - $a[$i] * $c[$i-1] / $g[$i-1];
    $s[$i] = $d[$i] - $a[$i] * $s[$i-1] / $g[$i-1];
}
$z = array();
$z[0] = 0;
$z[N] = 0;
$z[N-1] = $s[N-1] / $g[N-1];
for ($i = N - 2; $i >= 1; $i--)
{
    $z[$i] = ($s[$i] - $c[$i] * $z[$i+1]) / $g[$i];
}

# 0.5刻みで 与えられていない値を補間
foreach (range(0, 18) as $i)
{
    $d1 = $i * 0.5 - 4.5;
    $d2 = f($d1);
    $d3 = spline($d1, $x, $y, $z);

    # 元の関数と比較
    printf("%5.2f\t%8.5f\t%8.5f\t%8.5f\n", $d1, $d2, $d3, $d2 - $d3);
}

# 元の関数
function f($x)
{
    return $x - pow($x, 3) / (3 * 2) + pow($x, 5) / (5 * 4 * 3 * 2);
}

# Spline (スプライン) 補間
function spline($d, $x, $y, $z)
{
    # 補間関数値がどの区間にあるか
    $k = -1;
    foreach (range(1, N) as $i)
    {
        if ($d <= $x[$i])
        {
            $k = $i - 1;
            break;
        }
    }
    if ($k < 0) $k = N;

    $d1 = $x[$k+1] - $d;
    $d2 = $d       - $x[$k];
    $d3 = $x[$k+1] - $x[$k];
    return ($z[$k] * pow($d1, 3) + $z[$k+1] * pow($d2, 3)) / (6.0 * $d3) +
           ($y[$k]   / $d3 - $z[$k]   * $d3 / 6.0) * $d1 +
           ($y[$k+1] / $d3 - $z[$k+1] * $d3 / 6.0) * $d2;
}
?>
<?php

# 重力加速度
$g = -9.8;
# 空気抵抗係数
$k = -0.01;
# 時間間隔(秒)
$h = 0.01;

# 角度
$degree = 45;
$radian = $degree * M_PI / 180.0;
# 初速 250 km/h -> 秒速に変換
$v = (int)(250 * 1000 / 3600);
# 水平方向の速度
$vx = array();
$vx[0] = $v * cos($radian);
# 鉛直方向の速度
$vy = array();
$vy[0] = $v * sin($radian);
# 経過秒数
$t = 0.0;
# 位置
$x = 0.0;
$y = 0.0;

# Euler法
for ($i = 1; $y >= 0.0; $i++)
{
    # 経過秒数
    $t = $i * $h;

    # 位置
    $x += $h * $vx[0];
    $y += $h * $vy[0];

    printf("%4.2f\t%8.5f\t%9.5f\t%9.5f\t%8.5f\n", $t, $vx[0], $vy[0], $x, $y);

    # 速度
    $vx[1] = $vx[0] + $h * fx($vx[0], $vy[0]);
    $vy[1] = $vy[0] + $h * fy($vx[0], $vy[0]);
    $vx[0] = $vx[1];
    $vy[0] = $vy[1];
}

# 空気抵抗による水平方向の減速分
function fx($vx, $vy)
{
    global $k;
    return $k * sqrt($vx * $vx + $vy * $vy) * $vx;
}
# 重力と空気抵抗による鉛直方向の減速分
function fy($vx, $vy)
{
    global $g, $k;
    return $g + ($k * sqrt($vx * $vx + $vy * $vy) * $vy);
}
?>
<?php

# 重力加速度
$g = -9.8;
# 空気抵抗係数
$k = -0.01;
# 時間間隔(秒)
$h = 0.01;

# 角度
$degree = 45;
$radian = $degree * M_PI / 180.0;
# 初速 250 km/h -> 秒速に変換
$v = (int)(250 * 1000 / 3600);
# 水平方向の速度
$vx = array();
$vx[0] = $v * cos($radian);
# 鉛直方向の速度
$vy = array();
$vy[0] = $v * sin($radian);
# 経過秒数
$t = 0.0;
# 位置
$x = array();
$x[0] = 0.0;
$y = array();
$y[0] = 0.0;

# Heun法
for ($i = 1; $y[0] >= 0.0; $i++)
{
    # 経過秒数
    $t = $i * $h;

    # 位置・速度
    $x[1]  =  $x[0] + $h *    $vx[0];
    $y[1]  =  $y[0] + $h *    $vy[0];
    $vx[1] = $vx[0] + $h * fx($vx[0], $vy[0]);
    $vy[1] = $vy[0] + $h * fy($vx[0], $vy[0]);

    $x[2]  =  $x[0] + $h * (   $vx[0]          +    $vx[1]         ) / 2;
    $y[2]  =  $y[0] + $h * (   $vy[0]          +    $vy[1]         ) / 2;
    $vx[2] = $vx[0] + $h * (fx($vx[0], $vy[0]) + fx($vx[1], $vy[1])) / 2;
    $vy[2] = $vy[0] + $h * (fy($vx[0], $vy[0]) + fy($vx[1], $vy[1])) / 2;

    $x[0]  =  $x[2];
    $y[0]  =  $y[2];
    $vx[0] = $vx[2];
    $vy[0] = $vy[2];

    printf("%4.2f\t%8.5f\t%9.5f\t%9.5f\t%8.5f\n", $t, $vx[0], $vy[0], $x[0], $y[0]);
}

# 空気抵抗による水平方向の減速分
function fx($vx, $vy)
{
    global $k;
    return $k * sqrt($vx * $vx + $vy * $vy) * $vx;
}
# 重力と空気抵抗による鉛直方向の減速分
function fy($vx, $vy)
{
    global $g, $k;
    return $g + ($k * sqrt($vx * $vx + $vy * $vy) * $vy);
}
?>
<?php

# 重力加速度
$g = -9.8;
# 空気抵抗係数
$k = -0.01;
# 時間間隔(秒)
$h = 0.01;

# 角度
$degree = 45;
$radian = $degree * M_PI / 180.0;
# 初速 250 km/h -> 秒速に変換
$v = (int)(250 * 1000 / 3600);
# 水平方向の速度
$vx = array();
$vx[0] = $v * cos($radian);
# 鉛直方向の速度
$vy = array();
$vy[0] = $v * sin($radian);
# 経過秒数
$t = 0.0;
# 位置
$x = array();
$x[0] = 0.0;
$y = array();
$y[0] = 0.0;

# 中点法
for ($i = 1; $y[0] >= 0.0; $i++)
{
    # 経過秒数
    $t = $i * $h;

    # 位置・速度
    $vx[1] = $h * fx($vx[0], $vy[0]);
    $vy[1] = $h * fy($vx[0], $vy[0]);

    $wx = $vx[0] + $vx[1] / 2;
    $wy = $vy[0] + $vy[1] / 2;
    $vx[0] = $vx[0] + $h * fx($wx, $wy);
    $vy[0] = $vy[0] + $h * fy($wx, $wy);
    $x[0]  =  $x[0] + $h *    $wx;
    $y[0]  =  $y[0] + $h *    $wy;

    printf("%4.2f\t%8.5f\t%9.5f\t%9.5f\t%9.5f\n", $t, $vx[0], $vy[0], $x[0], $y[0]);
}

# 空気抵抗による水平方向の減速分
function fx($vx, $vy)
{
    global $k;
    return $k * sqrt($vx * $vx + $vy * $vy) * $vx;
}
# 重力と空気抵抗による鉛直方向の減速分
function fy($vx, $vy)
{
    global $g, $k;
    return $g + ($k * sqrt($vx * $vx + $vy * $vy) * $vy);
}
?>
<?php

# 重力加速度
$g = -9.8;
# 空気抵抗係数
$k = -0.01;
# 時間間隔(秒)
$h = 0.01;

# 角度
$degree = 45;
$radian = $degree * M_PI / 180.0;
# 初速 250 km/h -> 秒速に変換
$v = (int)(250 * 1000 / 3600);
# 水平方向の速度
$vx = array();
$vx[0] = $v * cos($radian);
# 鉛直方向の速度
$vy = array();
$vy[0] = $v * sin($radian);
# 経過秒数
$t = 0.0;
# 位置
$x = array();
$x[0] = 0.0;
$y = array();
$y[0] = 0.0;

# Runge-Kutta法
for ($i = 1; $y[0] >= 0.0; $i++)
{
    # 経過秒数
    $t = $i * $h;

    # 位置・速度
    $x[1]  = $h *    $vx[0];
    $y[1]  = $h *    $vy[0];
    $vx[1] = $h * fx($vx[0], $vy[0]);
    $vy[1] = $h * fy($vx[0], $vy[0]);

    $wx = $vx[0] + $vx[1] / 2;
    $wy = $vy[0] + $vy[1] / 2;
    $x[2]  = $h *    $wx;
    $y[2]  = $h *    $wy;
    $vx[2] = $h * fx($wx, $wy);
    $vy[2] = $h * fy($wx, $wy);

    $wx    = $vx[0] + $vx[2] / 2;
    $wy    = $vy[0] + $vy[2] / 2;
    $x[3]  = $h *    $wx;
    $y[3]  = $h *    $wy;
    $vx[3] = $h * fx($wx, $wy);
    $vy[3] = $h * fy($wx, $wy);

    $wx    = $vx[0] + $vx[3];
    $wy    = $vy[0] + $vy[3];
    $x[4]  = $h *    $wx;
    $y[4]  = $h *    $wy;
    $vx[4] = $h * fx($wx, $wy);
    $vy[4] = $h * fy($wx, $wy);

    $x[0]  += ( $x[1] +  $x[2] * 2 +  $x[3] * 2 +  $x[4]) / 6;
    $y[0]  += ( $y[1] +  $y[2] * 2 +  $y[3] * 2 +  $y[4]) / 6;
    $vx[0] += ($vx[1] + $vx[2] * 2 + $vx[3] * 2 + $vx[4]) / 6;
    $vy[0] += ($vy[1] + $vy[2] * 2 + $vy[3] * 2 + $vy[4]) / 6;

    printf("%4.2f\t%8.5f\t%9.5f\t%9.5f\t%9.5f\n", $t, $vx[0], $vy[0], $x[0], $y[0]);
}

# 空気抵抗による水平方向の減速分
function fx($vx, $vy)
{
    global $k;
    return $k * sqrt($vx * $vx + $vy * $vy) * $vx;
}
# 重力と空気抵抗による鉛直方向の減速分
function fy($vx, $vy)
{
    global $g, $k;
    return $g + ($k * sqrt($vx * $vx + $vy * $vy) * $vy);
}
?>
<?php

# 重力加速度
$g = -9.8;
# 空気抵抗係数
$k = -0.01;
# 時間間隔(秒)
$h = 0.01;

# 角度
$degree = 45;
$radian = $degree * M_PI / 180.0;
# 初速 250 km/h -> 秒速に変換
$v = (int)(250 * 1000 / 3600);
# 水平方向の速度
$vx = array();
$vx[0] = $v * cos($radian);
# 鉛直方向の速度
$vy = array();
$vy[0] = $v * sin($radian);
# 経過秒数
$t = 0.0;
# 位置
$x = array();
$x[0] = 0.0;
$y = array();
$y[0] = 0.0;

# Runge-Kutta-Gill法
for ($i = 1; $y[0] >= 0.0; $i++)
{
    # 経過秒数
    $t = $i * $h;

    # 位置・速度
    $x[1]  = $h *    $vx[0];
    $y[1]  = $h *    $vy[0];
    $vx[1] = $h * fx($vx[0], $vy[0]);
    $vy[1] = $h * fy($vx[0], $vy[0]);

    $wx = $vx[0] + $vx[1] / 2;
    $wy = $vy[0] + $vy[1] / 2;
    $x[2]  = $h *    $wx;
    $y[2]  = $h *    $wy;
    $vx[2] = $h * fx($wx, $wy);
    $vy[2] = $h * fy($wx, $wy);

    $wx    = $vx[0] + $vx[1] * ((sqrt(2.0) - 1) / 2) + $vx[2] * (1 - 1 / sqrt(2.0));
    $wy    = $vy[0] + $vy[1] * ((sqrt(2.0) - 1) / 2) + $vy[2] * (1 - 1 / sqrt(2.0));
    $x[3]  = $h *    $wx;
    $y[3]  = $h *    $wy;
    $vx[3] = $h * fx($wx, $wy);
    $vy[3] = $h * fy($wx, $wy);

    $wx    = $vx[0] - $vx[2] / sqrt(2.0) + $vx[3] * (1 + 1 / sqrt(2.0));
    $wy    = $vy[0] - $vy[2] / sqrt(2.0) + $vy[3] * (1 + 1 / sqrt(2.0));
    $x[4]  = $h *    $wx;
    $y[4]  = $h *    $wy;
    $vx[4] = $h * fx($wx, $wy);
    $vy[4] = $h * fy($wx, $wy);

    $x[0]  += ( $x[1] +  $x[2] * (2 - sqrt(2.0)) +  $x[3] * (2 + sqrt(2.0)) +  $x[4]) / 6;
    $y[0]  += ( $y[1] +  $y[2] * (2 - sqrt(2.0)) +  $y[3] * (2 + sqrt(2.0)) +  $y[4]) / 6;
    $vx[0] += ($vx[1] + $vx[2] * (2 - sqrt(2.0)) + $vx[3] * (2 + sqrt(2.0)) + $vx[4]) / 6;
    $vy[0] += ($vy[1] + $vy[2] * (2 - sqrt(2.0)) + $vy[3] * (2 + sqrt(2.0)) + $vy[4]) / 6;

    printf("%4.2f\t%8.5f\t%9.5f\t%9.5f\t%9.5f\n", $t, $vx[0], $vy[0], $x[0], $y[0]);
}

# 空気抵抗による水平方向の減速分
function fx($vx, $vy)
{
    global $k;
    return $k * sqrt($vx * $vx + $vy * $vy) * $vx;
}
# 重力と空気抵抗による鉛直方向の減速分
function fy($vx, $vy)
{
    global $g, $k;
    return $g + ($k * sqrt($vx * $vx + $vy * $vy) * $vy);
}
?>
<?php
$a = 1;
$b = 2;
printf("%12.10f\n", bisection($a, $b));

function bisection($a, $b)
{
    while (TRUE)
    {
        # 区間 (a, b) の中点 c = (a + b) / 2
        $c = ($a + $b) / 2;
        printf("%12.10f\t%13.10f\n", $c, $c - sqrt(2));

        $fc = f($c);
        if (abs($fc) < 0.0000000001) break;

        if ($fc < 0)
        {
            # f(c) < 0 であれば, 解は区間 (c, b) の中に存在
            $a = $c;
        }
        else
        {
            # f(c) > 0 であれば, 解は区間 (a, c) の中に存在
            $b = $c;
        }
    }
    return $c;
}

function f($x)
{
    return $x * $x - 2;
}
?>
<?php
$a = 1;
$b = 2;
printf("%12.10f\n", falseposition($a, $b));

function falseposition($a, $b)
{
    while (TRUE)
    {
        # 点 (a,f(a)) と 点 (b,f(b)) を結ぶ直線と x軸の交点
        $c = ($a * f($b) - $b * f($a)) / (f($b) - f($a));
        printf("%12.10f\t%13.10f\n", $c, $c - sqrt(2));

        $fc = f($c);
        if (abs($fc) < 0.0000000001) break;

        if ($fc < 0)
        {
            # f(c) < 0 であれば, 解は区間 (c, b) の中に存在
            $a = $c;
        }
        else
        {
            # f(c) > 0 であれば, 解は区間 (a, c) の中に存在
            $b = $c;
        }
    }
    return $c;
}

function f($x)
{
    return $x * $x - 2;
}
?>
<?php
$x = 1;
printf("%12.10f\n", iterative($x));

function iterative($x0)
{
    while (TRUE)
    {
        $x1 = g($x0);
        printf("%12.10f\t%13.10f\n", $x1, $x1 - sqrt(2));

        if (abs($x1 - $x0) < 0.0000000001) break;

        $x0 = $x1;
    }
    return $x1;
}

function g($x)
{
    return ($x / 2) + (1 / $x);
}
?>
<?php
$x = 2;
printf("%12.10f\n", newton($x));

function newton($x0)
{
    while (TRUE)
    {
        $x1 = $x0 - (f0($x0) / f1($x0));
        printf("%12.10f\t%13.10f\n", $x1, $x1 - sqrt(2));

        if (abs($x1 - $x0) < 0.0000000001) break;

        $x0 = $x1;
    }
    return $x1;
}

function f0($x)
{
    return $x * $x - 2;
}

function f1($x)
{
    return 2 * $x;
}
?>
<?php
$x = 2;
printf("%12.10f\n", bailey($x));

function bailey($x0)
{
    while (TRUE)
    {
        $x1 = $x0 - (f0($x0) / (f1($x0) - (f0($x0) * f2($x0) / (2 * f1($x0)))));
        printf("%12.10f\t%13.10f\n", $x1, $x1 - sqrt(2));

        if (abs($x1 - $x0) < 0.0000000001) break;

        $x0 = $x1;
    }
    return $x1;
}

function f0($x)
{
    return $x * $x - 2;
}

function f1($x)
{
    return 2 * $x;
}

function f2($x)
{
    return 2;
}
?>
<?php
$x0 = 1;
$x1 = 2;
printf("%12.10f\n", secant($x0, $x1));

function secant($x0, $x1)
{
    while (TRUE)
    {
        $x2 = $x1 - f($x1) * ($x1 - $x0) / (f($x1) - f($x0));
        printf("%12.10f\t%13.10f\n", $x2, $x2 - sqrt(2));

        if (abs($x2 - $x1) < 0.0000000001) break;

        $x0 = $x1;
        $x1 = $x2;
    }
    return $x2;
}

function f($x)
{
    return $x * $x - 2;
}
?>
<?php
define("N", 3);

$a = [[9,2,1,1],[2,8,-2,1],[-1,-2,7,-2],[1,-1,-2,6]];
$b = [20,16,8,17];
$c = [0,0,0,0];

# ヤコビの反復法
jacobi($a, $b, $c);

print "解\n";
foreach (range(0, N) as $i)
    printf("%14.10f\t", $c[$i]);
print "\n";

# ヤコビの反復法
function jacobi($a, $b, &$x0)
{
    while (true)
    {
        $x1 = array();
        $finish = true;
        foreach (range(0, N) as $i)
        {
            $x1[$i] = 0;
            foreach (range(0, N) as $j)
            {
                if ($j != $i)
                    $x1[$i] += $a[$i][$j] * $x0[$j];
            }
            $x1[$i] = ($b[$i] - $x1[$i]) / $a[$i][$i];
            if (abs($x1[$i] - $x0[$i]) > 0.0000000001) $finish = false;
        }

        foreach (range(0, N) as $i)
        {
            $x0[$i] = $x1[$i];
            printf("%14.10f\t", $x0[$i]);
        }
        print "\n";
        if ($finish) return;
    }
}
?>
<?php
define("N", 3);

$a = [[9,2,1,1],[2,8,-2,1],[-1,-2,7,-2],[1,-1,-2,6]];
$b = [20,16,8,17];
$c = [0,0,0,0];

# ガウス・ザイデル法
gauss($a, $b, $c);

print "解\n";
foreach (range(0, N) as $i)
    printf("%14.10f\t", $c[$i]);
print "\n";

# ガウス・ザイデル法
function gauss($a, $b, &$x0)
{
    while (true)
    {
        $finish = true;
        foreach (range(0, N) as $i)
        {
            $x1 = 0;
            foreach (range(0, N) as $j)
            {
                if ($j != $i)
                    $x1 += $a[$i][$j] * $x0[$j];
            }
            $x1 = ($b[$i] - $x1) / $a[$i][$i];
            if (abs($x1 - $x0[$i]) > 0.0000000001) $finish = false;
            $x0[$i] = $x1;
        }

        foreach (range(0, N) as $i)
        {
            printf("%14.10f\t", $x0[$i]);
        }
        print "\n";
        if ($finish) return;
    }
}
?>
<?php
define("N", 3);

$a = [[-1,-2,7,-2],[1,-1,-2,6],[9,2,1,1],[2,8,-2,1]];
$b = [8,17,20,16];

# ピボット選択
pivoting($a,$b);
print "ピボット選択後\n";
disp_progress($a,$b);

# 前進消去
forward_elimination($a,$b);
print "前進消去後\n";
disp_progress($a,$b);

# 後退代入
backward_substitution($a,$b);
print "解\n";
foreach (range(0, N) as $i)
    printf("%14.10f\t", $b[$i]);
print "\n";

# 前進消去
function forward_elimination(&$a, &$b)
{
    foreach (range(0, N - 1) as $pivot)
    {
        foreach (range($pivot + 1, N) as $row)
        {
            $s = $a[$row][$pivot] / $a[$pivot][$pivot];
            foreach (range($pivot, N) as $col)
                    $a[$row][$col] -= $a[$pivot][$col]    * $s;
            $b[$row]               -= $b[$pivot]          * $s;
        }
    }
}
# 後退代入
function backward_substitution(&$a, &$b)
{
     for ($row = N; $row >= 0; $row--)
    {
        for ($col = N; $col > $row; $col--)
            $b[$row] -= $a[$row][$col] * $b[$col];
        $b[$row] /= $a[$row][$row];
    }
}
# ピボット選択
function pivoting(&$a, &$b)
{
    foreach (range(0, N) as $pivot)
    {
        # 各列で 一番値が大きい行を 探す
        $max_row =   $pivot;
        $max_val =   0;
        foreach (range($pivot, N) as $row)
        {
            if (abs($a[$row][$pivot]) > $max_val)
            {
                # 一番値が大きい行
                $max_val =   abs($a[$row][$pivot]);
                $max_row =   $row;
            }
        }

        # 一番値が大きい行と入れ替え
        if ($max_row != $pivot)
        {
            foreach (range(0, N) as $col)
            {
                $tmp               =   $a[$max_row][$col];
                $a[$max_row][$col] =   $a[$pivot][$col];
                $a[$pivot][$col]   =   $tmp;
            }
            $tmp         =   $b[$max_row];
            $b[$max_row] =   $b[$pivot];
            $b[$pivot]   =   $tmp;
        }
    }
}
# 状態を確認
function disp_progress($a, $b)
{
  foreach (range(0, N) as $i)
 {
    foreach (range(0, N) as $j)
            printf("%14.10f\t", $a[$i][$j]);
    printf("%14.10f\n", $b[$i]);
  }
  print "\n";
}
?>
<?php
define("N", 3);

$a = [[-1,-2,7,-2],[1,-1,-2,6],[9,2,1,1],[2,8,-2,1]];
$b = [8,17,20,16];

# ピボット選択
pivoting($a,$b);
print "ピボット選択後\n";
disp_progress($a,$b);

# 前進消去
forward_elimination($a,$b);
print "前進消去後\n";
disp_progress($a,$b);

# 後退代入
backward_substitution($a,$b);
print "解\n";
foreach (range(0, N) as $i)
    printf("%14.10f\t", $b[$i]);
print "\n";

# 前進消去
function forward_elimination(&$a, &$b)
{
    # 対角線上の係数を 1 にする
    foreach (range(0, N) as $pivot)
    {
        $s = $a[$pivot][$pivot];
        foreach (range(0, N) as $col)
            $a[$pivot][$col] /= $s;
        $b[$pivot]           /= $s;
    }
    print "対角線上の係数を 1 にする\n";
    disp_progress($a,$b);

    # 対角行列にする
    foreach (range(0, N) as $pivot)
    {
        foreach (range(0, N) as $row)
        {
            if ($row == $pivot) continue;

            $s = $a[$row][$pivot] / $a[$pivot][$pivot];
        foreach (range($pivot, N) as $col)
                $a[$row][$col] -= $a[$pivot][$col] * $s;
            $b[$row] -= $b[$pivot] * $s;
        }
    }
}
# 後退代入
function backward_substitution(&$a, &$b)
{
    foreach (range(0, N) as $pivot)
        $b[$pivot]  /= $a[$pivot][$pivot];
}
# ピボット選択
function pivoting(&$a, &$b)
{
    foreach (range(0, N) as $pivot)
    {
        # 各列で 一番値が大きい行を 探す
        $max_row =   $pivot;
        $max_val =   0;
        foreach (range($pivot, N) as $row)
        {
            if (abs($a[$row][$pivot]) > $max_val)
            {
                # 一番値が大きい行
                $max_val =   abs($a[$row][$pivot]);
                $max_row =   $row;
            }
        }

        # 一番値が大きい行と入れ替え
        if ($max_row != $pivot)
        {
            foreach (range(0, N) as $col)
            {
                $tmp               =   $a[$max_row][$col];
                $a[$max_row][$col] =   $a[$pivot][$col];
                $a[$pivot][$col]   =   $tmp;
            }
            $tmp         =   $b[$max_row];
            $b[$max_row] =   $b[$pivot];
            $b[$pivot]   =   $tmp;
        }
    }
}
# 状態を確認
function disp_progress($a, $b)
{
  foreach (range(0, N) as $i)
 {
    foreach (range(0, N) as $j)
    {
            printf("%14.10f\t", $a[$i][$j]);
    }
    printf("%14.10f\n", $b[$i]);
  }
  print "\n";
}
?>
<?php
define("N", 3);

$a = [[-1,-2,7,-2],[1,-1,-2,6],[9,2,1,1],[2,8,-2,1]];
$b = [8,17,20,16];

# ピボット選択
pivoting($a,$b);
print "ピボット選択後\n";
disp_progress($a,$b);

# LU分解
$x = [0,0,0,0];
decomp($a,$b,$x);
print "X\n";
foreach (range(0, N) as $i)
    printf("%14.10f\t", $x[$i]);
print "\n";

# LU分解
function decomp(&$a, &$b, &$x)
{
    # 前進消去
    forward_elimination($a,$b);
    # 下三角行列を確認
    print "L\n";
    foreach (range(0, N) as $i)
    {
        foreach (range(0, N) as $j)
        {
            if ($i > $j)
            {
                printf("%14.10f\t", $a[$i][$j]);
            }
            elseif ($i == $j)
            {
                printf("%14.10f\t", 1.0);
            }
            else
            {
                printf("%14.10f\t", 0.0);
            }
        }
        print "\n";
    }
    print "\n";
    # 上三角行列を確認
    print "U\n";
    foreach (range(0, N) as $i)
    {
        foreach (range(0, N) as $j)
        {
            if ($i <= $j)
            {
                printf("%14.10f\t", $a[$i][$j]);
            }
            else
            {
                printf("%14.10f\t", 0.0);
            }
        }
        print "\n";
    }
    print "\n";

    # Ly=b から y を求める (前進代入)
    $y = [0,0,0,0];
    forward_substitution($a,$b,$y);
    # y の 値 を確認
    print "Y\n";
    foreach (range(0, N) as $i)
    {
        printf("%14.10f\t", $y[$i]);
    }
    print "\n";

    # Ux=y から x を求める (後退代入)
    backward_substitution($a,$y,$x);
}

# 前進消去
function forward_elimination(&$a, $b)
{
    foreach (range(0, N - 1) as $pivot)
    {
        foreach (range($pivot + 1, N) as $row)
        {
            $s = $a[$row][$pivot] / $a[$pivot][$pivot];
            foreach (range($pivot, N) as $col)
                    $a[$row][$col] -= $a[$pivot][$col]    * $s; # これが 上三角行列
            $a[$row][$pivot] = $s;                              # これが 下三角行列
            # $b[$row]               -= $b[$pivot]          * $s;# この値は変更しない
        }
    }
}
# Ly=b から y を求める (前進代入)
function forward_substitution($a, $b, &$y)
{
    foreach (range(0, N) as $row)
    {
        foreach (range(0, $row) as $col)
        {
            $b[$row] -= $a[$row][$col] * $y[$col];
        }
        $y[$row] = $b[$row];
    }
}
# Ux=y から x を求める (後退代入)
function backward_substitution($a, $y, &$x)
{
    for ($row = N; $row >= 0; $row--)
    {
        for ($col = N; $col > $row; $col--)
        {
            $y[$row] -= $a[$row][$col] * $x[$col];
        }
        $x[$row] = $y[$row] / $a[$row][$row];
    }
}
# ピボット選択
function pivoting(&$a, &$b)
{
    foreach (range(0, N) as $pivot)
    {
        # 各列で 一番値が大きい行を 探す
        $max_row =   $pivot;
        $max_val =   0;
        foreach (range($pivot, N) as $row)
        {
            if (abs($a[$row][$pivot]) > $max_val)
            {
                # 一番値が大きい行
                $max_val =   abs($a[$row][$pivot]);
                $max_row =   $row;
            }
        }

        # 一番値が大きい行と入れ替え
        if ($max_row != $pivot)
        {
            foreach (range(0, N) as $col)
            {
                $tmp               =   $a[$max_row][$col];
                $a[$max_row][$col] =   $a[$pivot][$col];
                $a[$pivot][$col]   =   $tmp;
            }
            $tmp         =   $b[$max_row];
            $b[$max_row] =   $b[$pivot];
            $b[$pivot]   =   $tmp;
        }
    }
}
# 状態を確認
function disp_progress($a, $b)
{
  foreach (range(0, N) as $i)
 {
    foreach (range(0, N) as $j)
            printf("%14.10f\t", $a[$i][$j]);
    printf("%14.10f\n", $b[$i]);
  }
  print "\n";
}
?>
<?php
define("N", 3);

$a = [[5,2,3,4],[2,10,6,7],[3,6,15,9],[4,7,9,20]];
$b = [34,68,96,125];
print "A\n";
disp_progress($a);

# LL^T分解
$x = [0,0,0,0];
decomp($a,$b,$x);
print "X\n";
foreach (range(0, N) as $i)
  printf("%14.10f\t", $x[$i]);
print "\n";

# LL^T分解
function decomp(&$a, &$b, &$x)
{
  # 前進消去
    forward_elimination($a,$b);
    print "L と L^T\n";
    foreach (range(0, N) as $i)
    {
        foreach (range(0, N) as $j)
        {
            if ($j <= $i)
            {
                printf("%14.10f\t", $a[$i][$j]);
            }
            else
            {
                printf("%14.10f\t", $a[$j][$i]);
            }
        }
        print "\n";
    }
    print "\n";

    # Ly=b から y を求める (前進代入)
    $y = [0,0,0,0];
    forward_substitution($a,$b,$y);
    # y の 値 を確認
    print "Y\n";
    foreach (range(0, N) as $i)
    {
        printf("%14.10f\t", $y[$i]);
    }
    print "\n";

    # Ux=y から x を求める (後退代入)
    backward_substitution($a,$y,$x);
}

# 前進消去
function forward_elimination(&$a, $b)
{
    foreach (range(0, N) as $pivot)
    {
        $s = 0;
        for ($col = 0; $col < $pivot; $col++)
            $s += $a[$pivot][$col] * $a[$pivot][$col];
        # ここで根号の中が負の値になると計算できない!
        $a[$pivot][$pivot] = sqrt($a[$pivot][$pivot] - $s);

        for ($row = $pivot + 1; $row <= N; $row++)
        {
            $s = 0;
            for ($col = 0; $col < $pivot; $col++)
                $s += $a[$row][$col] * $a[$pivot][$col];
            $a[$row][$pivot] = ($a[$row][$pivot] - $s) / $a[$pivot][$pivot];
        }
    }
}
# Ly=b から y を求める (前進代入)
function forward_substitution($a, $b, &$y)
{
    foreach (range(0, N) as $row)
    {
        foreach (range(0, $row - 1) as $col)
        {
            $b[$row] -= $a[$row][$col] * $y[$col];
        }
        $y[$row] = $b[$row] / $a[$row][$row];
    }
}
# Ux=y から x を求める (後退代入)
function backward_substitution($a, $y, &$x)
{
    for ($row = N; $row >= 0; $row--)
    {
        for ($col = N; $col > $row; $col--)
        {
            $y[$row] -= $a[$col][$row] * $x[$col];
        }
        $x[$row] = $y[$row] / $a[$row][$row];
    }
}
# 状態を確認
function disp_progress($a)
{
  foreach (range(0, N) as $i)
 {
    foreach (range(0, N) as $j)
        printf("%14.10f\t", $a[$i][$j]);
    print "\n";
  }
  print "\n";
}
?>
<?php
define("N", 3);

$a = [[5,2,3,4],[2,10,6,7],[3,6,15,9],[4,7,9,20]];
$b = [34,68,96,125];

print "A\n";
disp_progress($a);

# LDL^T分解
$x = [0,0,0,0];
decomp($a,$b,$x);
print "X\n";
foreach (range(0, N) as $i)
  printf("%14.10f\t", $x[$i]);
print "\n";

# LDL^T分解
function decomp(&$a, &$b, &$x)
{
  # 前進消去
  forward_elimination($a,$b);
    print "L と D\n";
    foreach (range(0, N) as $i)
    {
        foreach (range(0, N) as $j)
        {
            if ($j <= $i)
            {
                printf("%14.10f\t", $a[$i][$j]);
            }
            else
            {
                printf("%14.10f\t", $a[$j][$i]);
            }
        }
        print "\n";
    }
    print "\n";

    # Ly=b から y を求める (前進代入)
    $y = [0,0,0,0];
    forward_substitution($a,$b,$y);
    # y の 値 を確認
    print "Y\n";
    foreach (range(0, N) as $i)
    {
        printf("%14.10f\t", $y[$i]);
    }
    print "\n";

    # DL^Tx=y から x を求める (後退代入)
    backward_substitution($a,$y,$x);
}

# 前進消去
function forward_elimination(&$a, $b)
{
    foreach (range(0, N) as $pivot)
    {
        # pivot < k の場合
        $s = 0;
        for ($col = 0; $col < $pivot; $col++)
        {
            $s = $a[$pivot][$col];
            for ($k = 0; $k < $col; $k++)
            {
                $s -= $a[$pivot][$k] * $a[$col][$k] * $a[$k][$k];
            }
            $a[$pivot][$col] = $s / $a[$col][$col];
        }

        # pivot == k の場合
        $s = $a[$pivot][$pivot];
        for ($k = 0; $k < $pivot; $k++)
        {
            $s -= $a[$pivot][$k] * $a[$pivot][$k] * $a[$k][$k];
        }
        $a[$pivot][$pivot] = $s;
    }
}
# Ly=b から y を求める (前進代入)
function forward_substitution($a, $b, &$y)
{
    foreach (range(0, N) as $row)
    {
        foreach (range(0, $row - 1) as $col)
        {
            $b[$row] -= $a[$row][$col] * $y[$col];
        }
        $y[$row] = $b[$row];
    }
}
# Ux=y から x を求める (後退代入)
function backward_substitution($a, $y, &$x)
{
    for ($row = N; $row >= 0; $row--)
    {
        for ($col = N; $col > $row; $col--)
        {
            $y[$row] -= $a[$col][$row] * $a[$row][$row] * $x[$col];
        }
        $x[$row] = $y[$row] / $a[$row][$row];
    }
}
# 状態を確認
function disp_progress($a)
{
  foreach (range(0, N) as $i)
 {
    foreach (range(0, N) as $j)
        printf("%14.10f\t", $a[$i][$j]);
    print "\n";
  }
  print "\n";
}
?>
inserted by FC2 system