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

#include <math/core/mp/Float.hpp>
#include <math/core/mp/Float/FloatMath.hpp>
#include <iomanip>
#include <iostream>

using namespace sangi;

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

    // ---- Pi to 50 decimal digits ---------------------------------
    {
        std::cout << "[Pi at prec=170 bits ≈ 50 dec digits]\n";
        int prec = 170;
        Float::setDefaultPrecision(prec);
        Float pi = Float::pi(prec);
        std::cout << "  pi(170) = " << pi.toDecimalString(50) << "\n";
        std::cout << "  (expected: 3.14159265358979323846264338327950288419716939937510...)\n";
    }

    // ---- exp / log round-trip ------------------------------------
    {
        std::cout << "[exp/log round-trip at prec=100 bits]\n";
        int prec = 100;
        Float::setDefaultPrecision(prec);
        Float x("1.5");
        Float ex = exp(x, prec);
        Float lx = log(ex, prec);
        std::cout << "  exp(1.5)        = " << ex.toDecimalString(25) << "\n";
        std::cout << "  log(exp(1.5))   = " << lx.toDecimalString(25) << "\n";
    }

    // ---- NaN / Infinity propagation ------------------------------
    {
        std::cout << "[NaN / Infinity]\n";
        Float inf = Float::positiveInfinity();
        Float nanv = Float::nan();
        Float z = Float::zero();
        Float r1 = inf + Float(1);
        Float r2 = inf - inf;
        Float r3 = nanv + Float(42);
        Float r4 = Float(1) / z;
        std::cout << "  inf + 1   isInfinity = " << std::boolalpha << r1.isInfinity() << "\n";
        std::cout << "  inf - inf isNaN      = " << r2.isNaN() << "\n";
        std::cout << "  nan + 42  isNaN      = " << r3.isNaN() << "\n";
        std::cout << "  1   / 0   isInfinity = " << r4.isInfinity() << "\n";
    }

    // ---- trigonometric -------------------------------------------
    {
        std::cout << "[sin/cos/tan at 0.5]\n";
        int prec = 170;
        Float::setDefaultPrecision(prec);
        Float x("0.5");
        std::cout << "  sin(0.5) = " << sin(x, prec).toDecimalString(20) << "\n";
        std::cout << "  cos(0.5) = " << cos(x, prec).toDecimalString(20) << "\n";
        std::cout << "  tan(0.5) = " << tan(x, prec).toDecimalString(20) << "\n";
    }

    // ---- inverse trig (asin(0.5) = pi/6 ≈ 0.5236) ----------------
    {
        std::cout << "[asin/acos/atan at 0.5]\n";
        int prec = 170;
        Float::setDefaultPrecision(prec);
        Float x("0.5");
        std::cout << "  asin(0.5) = " << asin(x, prec).toDecimalString(20) << "  (= π/6)\n";
        std::cout << "  acos(0.5) = " << acos(x, prec).toDecimalString(20) << "  (= π/3)\n";
        std::cout << "  atan(0.5) = " << atan(x, prec).toDecimalString(20) << "\n";
    }

    // ---- hyperbolic ----------------------------------------------
    {
        std::cout << "[sinh/cosh/tanh at 1]\n";
        int prec = 170;
        Float::setDefaultPrecision(prec);
        Float x("1.0");
        std::cout << "  sinh(1) = " << sinh(x, prec).toDecimalString(20) << "\n";
        std::cout << "  cosh(1) = " << cosh(x, prec).toDecimalString(20) << "\n";
        std::cout << "  tanh(1) = " << tanh(x, prec).toDecimalString(20) << "\n";
    }

    // ---- sqrt / cbrt / pow ---------------------------------------
    {
        std::cout << "[sqrt/cbrt/pow at 2]\n";
        int prec = 170;
        Float::setDefaultPrecision(prec);
        Float x("2.0");
        std::cout << "  sqrt(2) = " << sqrt(x, prec).toDecimalString(25) << "\n";
        std::cout << "  cbrt(2) = " << cbrt(x, prec).toDecimalString(25) << "\n";
        Float half("0.5");
        std::cout << "  2^0.5   = " << pow(x, half, prec).toDecimalString(25) << "\n";
    }

    // ---- erf / gamma ---------------------------------------------
    {
        std::cout << "[erf/gamma at 1]\n";
        int prec = 170;
        Float::setDefaultPrecision(prec);
        Float x("1.0");
        std::cout << "  erf(1)       = " << erf(x, prec).toDecimalString(20) << "\n";
        std::cout << "  gamma(1)     = " << gamma(x, prec).toDecimalString(20) << "  (expected 1)\n";
        Float ten("10");
        std::cout << "  lnGamma(10)  = " << lnGamma(ten, prec).toDecimalString(20) << "  (= ln(9!))\n";
    }

    return 0;
}
