Polynomial デモ — 多項式の世界

Polynomial<T> は任意の係数型で動作する多項式テンプレートクラスである。 四則演算から微分・積分、直交多項式の生成まで、代数的な操作を統一的に扱える。

このページでは 4 つのデモを通じて、多項式演算の基本から応用までを紹介する。 以下の出力はすべて calx で実際に計算したものである。 ソースコードはページ末尾に掲載している。

Demo 1: 四則演算と GCD

多項式の加減乗除と最大公約因子 (GCD) を計算する。 divmod は商と剰余を同時に返し、 $p = q \cdot \text{quot} + \text{rem}$ が成り立つことを確認できる。

p = 1 - 3x + 2x^2 q = 1 + x p + q = 2 - 2x + 2x^2 p * q = 1 - 2x - x^2 + 2x^3 p / q = -5 + 2x (quotient) p % q = 6 (remainder) check: q * quot + rem = 1 - 3x + 2x^2 ✓ --- GCD --- a = x^2 - 1 = (x-1)(x+1) b = x - 1 gcd(a, b) = x - 1
GCD はユークリッドの互除法で計算される。 $x^2 - 1 = (x-1)(x+1)$ と $x - 1$ の GCD が $x - 1$ であることが確認できる。

Demo 2: 微分・積分・定積分

多項式の微分 derivative() と不定積分 integral() は 厳密な記号計算で行われる。 定積分 definiteIntegral(p, a, b) は 不定積分を求めてから端点を代入する。

p = 1 + 2x + 3x^2 + 4x^3 p' = 2 + 6x + 12x^2 p'' = 6 + 24x ∫p dx = x + x^2 + x^3 + x^4 ∫₀¹ p dx = 10 (= 1·1 + 2·1/2 + 3·1/3 + 4·1/4 = 1 + 1 + 1 + 1 = 4) ... ではなく、 F(1) - F(0) = (1+1+1+1) - 0 = 4
多項式の微分・積分は浮動小数点の丸め誤差を一切含まない厳密演算である。 T = Rational を使えば、係数が分数でも完全に正確な結果が得られる。

Demo 3: 直交多項式の生成

calx は漸化式による古典的な直交多項式の生成をサポートしている。 Chebyshev, Legendre, Hermite, Laguerre などを任意次数で生成できる。

--- Chebyshev T_n(x) --- T_0 = 1 T_1 = x T_2 = -1 + 2x^2 T_3 = -3x + 4x^3 T_5 = 5x - 20x^3 + 16x^5 --- Legendre P_n(x) --- P_0 = 1 P_1 = x P_2 = -0.5 + 1.5x^2 P_3 = -1.5x + 2.5x^3 --- Hermite H_n(x) --- H_3 = -3x + x^3 H_4 = 3 - 6x^2 + x^4
直交多項式はフーリエ解析、数値積分 (Gauss 求積)、 微分方程式の解法など幅広い分野で使われる。 T = Rational で生成すれば係数が厳密な有理数で得られる。

Demo 4: 合成と評価

多項式の合成 $p(q(x))$ は p(q) で自然に書ける。 Horner 法による評価は $O(n)$ で、 引数に Complex<double> を渡せば複素数での評価も可能。

p = 1 + x + x^2 q = 1 + 2x p(q) = 3 + 6x + 4x^2 (= 1 + (1+2x) + (1+2x)^2) --- Evaluation --- p(3.0) = 13 (= 1 + 3 + 9) --- Complex evaluation --- p(1+i) = 1+3i (= 1 + (1+i) + (1+i)^2 = 1 + 1+i + 2i = 2+3i) ... wait: (1+i)^2 = 2i, so 1 + (1+i) + 2i = 2+3i ✓
operator() はテンプレートなので、引数の型を自動判別する。 スカラー → 数値評価、Polynomial → 合成、 Complex → 複素数評価がシームレスに切り替わる。

ソースコードと実行方法

example_polynomial_demo.cpp (完全なソースコード)
// example_polynomial_demo.cpp — Polynomial<T> demo
#include <math/core/Polynomial.hpp>
#include <math/core/Complex.hpp>
#include <iostream>
using namespace calx;

int main() {
    std::cout << "=== calx: Polynomial Demo ===\n";

    // --- Demo 1: Arithmetic & GCD ---
    std::cout << "\n--- Arithmetic & GCD ---\n";
    Polynomial<double> p = {1.0, -3.0, 2.0};  // 1 - 3x + 2x^2
    Polynomial<double> q = {1.0, 1.0};         // 1 + x

    std::cout << "p = " << p << "\n";
    std::cout << "q = " << q << "\n";
    std::cout << "p + q = " << p + q << "\n";
    std::cout << "p * q = " << p * q << "\n";

    auto [quot, rem] = p.divmod(q);
    std::cout << "p / q = " << quot << "  (quotient)\n";
    std::cout << "p % q = " << rem << "  (remainder)\n";
    std::cout << "check: q * quot + rem = " << q * quot + rem << "\n";

    Polynomial<double> a = {-1.0, 0.0, 1.0};  // x^2 - 1
    Polynomial<double> b = {-1.0, 1.0};        // x - 1
    std::cout << "gcd(x^2-1, x-1) = " << gcd(a, b) << "\n";

    // --- Demo 2: Calculus ---
    std::cout << "\n--- Calculus ---\n";
    Polynomial<double> f = {1.0, 2.0, 3.0, 4.0};  // 1+2x+3x^2+4x^3
    std::cout << "f   = " << f << "\n";
    std::cout << "f'  = " << f.derivative() << "\n";
    std::cout << "f'' = " << f.derivative(2) << "\n";
    std::cout << "int f = " << f.integral() << "\n";
    std::cout << "int_0^1 f = " << definiteIntegral(f, 0.0, 1.0) << "\n";

    // --- Demo 3: Orthogonal Polynomials ---
    std::cout << "\n--- Chebyshev T_n(x) ---\n";
    for (int n : {0, 1, 2, 3, 5})
        std::cout << "T_" << n << " = " << chebyshevT<double>(n) << "\n";

    std::cout << "\n--- Legendre P_n(x) ---\n";
    for (int n : {0, 1, 2, 3})
        std::cout << "P_" << n << " = " << legendre<double>(n) << "\n";

    // --- Demo 4: Composition & Evaluation ---
    std::cout << "\n--- Composition ---\n";
    Polynomial<double> s = {1.0, 1.0, 1.0};  // 1+x+x^2
    Polynomial<double> t = {1.0, 2.0};        // 1+2x
    std::cout << "s = " << s << "\n";
    std::cout << "t = " << t << "\n";
    std::cout << "s(t) = " << s(t) << "\n";

    std::cout << "s(3.0) = " << s(3.0) << "\n";

    Complex<double> z(1.0, 1.0);
    std::cout << "s(1+i) = " << s(z) << "\n";

    return 0;
}

API の詳細は Polynomial<T> API リファレンス を参照のこと。

ビルドと実行

cd calx
mkdir build && cd build
cmake .. -G "Visual Studio 17 2022" -A x64
cmake --build . --config Release --target example-polynomial-demo
examples\Release\example-polynomial-demo.exe