// Copyright (C) 2026 Kiyotsugu Arai
// SPDX-License-Identifier: LGPL-3.0-or-later
//
// example_doc_rationalfunction_samples.cpp
// Verification harness for samples in api/RationalFunction.html (ja+en).

#include <math/core/RationalFunction.hpp>
#include <math/core/RationalFunction_partialFractions.hpp>
#include <iomanip>
#include <iostream>

using namespace sangi;

int main() {
    std::cout << std::setprecision(15);

    // ---- construction + auto-simplify ----------------------------
    {
        std::cout << "[construction]\n";
        // (x^2 - 1) / (x - 1)  ascending coeffs: {-1,0,1} / {-1,1}
        RationalFunction<double> f({-1, 0, 1}, {-1, 1});
        std::cout << "  f = " << f.toString() << "\n";
        std::cout << "  numDeg=" << f.numeratorDegree()
                  << " denDeg=" << f.denominatorDegree() << "\n";
        std::cout << "  f(3) = " << f(3.0) << "\n";
    }

    // ---- arithmetic ----------------------------------------------
    {
        std::cout << "[arithmetic]\n";
        RationalFunction<double> f({1}, {1, 1});      // 1/(1+x)
        RationalFunction<double> g({0, 1}, {1, 1});   // x/(1+x)
        std::cout << "  f+g     = " << (f + g).toString() << "\n";
        std::cout << "  f*g     = " << (f * g).toString() << "\n";
        std::cout << "  f/g     = " << (f / g).toString() << "\n";
        std::cout << "  f+g at0 = " << (f + g)(0.0) << "\n";
    }

    // ---- derivative / reciprocal / pow ---------------------------
    {
        std::cout << "[calculus]\n";
        RationalFunction<double> f({1}, {1, 1});      // 1/(1+x)
        std::cout << "  d/dx f   = " << f.derivative().toString() << "\n";
        std::cout << "  1/f      = " << f.reciprocal().toString() << "\n";
        std::cout << "  f^2      = " << f.pow(2).toString() << "\n";
    }

    // ---- composition ---------------------------------------------
    {
        std::cout << "[composition]\n";
        RationalFunction<double> f({1}, {1, 1});      // 1/(1+x)
        RationalFunction<double> g({0, 1}, {1, 1});   // x/(1+x)
        auto h = compose(f, g);                       // f(g(x)) = (1+x)/(1+2x)
        std::cout << "  f(g(x))   = " << h.toString() << "\n";
        std::cout << "  f(g(1))   = " << h(1.0) << "\n";
    }

    // ---- partial fractions ---------------------------------------
    {
        std::cout << "[partial fractions]\n";
        // 1 / (x^2 - 1) = 1/((x-1)(x+1))  ascending: {1} / {-1,0,1}
        RationalFunction<double> f({1}, {-1, 0, 1});
        auto pfe = partialFractions(f);
        std::cout << "  success = " << (pfe.success ? "true" : "false") << "\n";
        std::cout << "  terms   = " << pfe.terms.size() << "\n";
        std::cout << "  pfe     = " << toString(pfe) << "\n";
        auto ps = poles(f);
        std::cout << "  poles   = ";
        for (std::size_t i = 0; i < ps.size(); ++i)
            std::cout << (i ? ", " : "") << ps[i].re;
        std::cout << "\n";
    }

    return 0;
}
