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

#define _USE_MATH_DEFINES
#include <math/core/Complex.hpp>
#include <cmath>
#include <iomanip>
#include <iostream>

using namespace sangi;
using namespace sangi::literals;

static void print_c(const Complex<double>& z) {
    std::cout << z.re << (z.im >= 0 ? "+" : "") << z.im << "i";
}

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

    // ---- constructors / accessors --------------------------------
    {
        std::cout << "[ctor]\n";
        Complex<double> z1(3.0, 4.0);
        Complex<double> z2 = 2.0 + 1.0_i;
        Complex<double> z3(5.0);  // real only
        std::cout << "  z1="; print_c(z1); std::cout << "  re=" << z1.real() << "  im=" << z1.imag() << "\n";
        std::cout << "  z2="; print_c(z2); std::cout << "\n";
        std::cout << "  z3="; print_c(z3); std::cout << "\n";
        std::cout << "  z1.normSq()=" << z1.normSq() << "\n";
        std::cout << "  z1.toString()=" << z1.toString() << "\n";
    }

    // ---- arithmetic ----------------------------------------------
    {
        std::cout << "[arith]\n";
        Complex<double> z1(3.0, 4.0);
        Complex<double> z2 = 2.0 + 1.0_i;
        auto s = z1 + z2;       // 5+5i
        auto d = z1 - z2;       // 1+3i
        auto p = z1 * z2;       // (3*2-4*1)+(3*1+4*2)i = 2+11i
        auto q = z1 / z2;       // (3+4i)*(2-i)/5 = (10+5i)/5 = 2+i
        std::cout << "  z1+z2="; print_c(s); std::cout << "\n";
        std::cout << "  z1-z2="; print_c(d); std::cout << "\n";
        std::cout << "  z1*z2="; print_c(p); std::cout << "\n";
        std::cout << "  z1/z2="; print_c(q); std::cout << "\n";

        // scalar mix
        auto sp = z1 * 2.0;     // 6+8i
        auto sd = 1.0 + z1;     // 4+4i
        std::cout << "  z1*2.0="; print_c(sp); std::cout << "\n";
        std::cout << "  1.0+z1="; print_c(sd); std::cout << "\n";
    }

    // ---- math functions ------------------------------------------
    {
        std::cout << "[math]\n";
        Complex<double> z1(3.0, 4.0);
        std::cout << "  abs(z1)=" << abs(z1) << "\n";            // 5
        std::cout << "  arg(z1)=" << arg(z1) << "\n";            // atan2(4,3) ~= 0.9272952...
        std::cout << "  conj(z1)="; print_c(conj(z1)); std::cout << "\n";  // 3-4i
        std::cout << "  norm(z1)=" << norm(z1) << "\n";          // 25

        auto w = polar(5.0, std::atan2(4.0, 3.0));               // -> 3+4i
        std::cout << "  polar(5, atan2(4,3))="; print_c(w); std::cout << "\n";

        auto e = exp(Complex<double>(0.0, M_PI));                 // -> -1 + 0i (within eps)
        std::cout << "  exp(i*pi)="; print_c(e); std::cout << "\n";

        auto sq = sqrt(Complex<double>(-1.0, 0.0));               // -> 0+1i
        std::cout << "  sqrt(-1)="; print_c(sq); std::cout << "\n";

        auto lg = log(Complex<double>(1.0, 0.0));                 // -> 0+0i
        std::cout << "  log(1)="; print_c(lg); std::cout << "\n";
    }

    // ---- twiddle factors -----------------------------------------
    {
        std::cout << "[twiddle N=8]\n";
        int N = 8;
        for (int k = 0; k < N; ++k) {
            auto tw = expI(-2.0 * M_PI * k / N);
            std::cout << "  W_8^" << k << "="; print_c(tw); std::cout << "\n";
        }
    }

    // ---- std::complex interop ------------------------------------
    {
        std::cout << "[std::complex interop]\n";
        std::complex<double> sc(1.0, 2.0);
        Complex<double> from_std = sc;
        std::complex<double> to_std = from_std;
        std::cout << "  from_std="; print_c(from_std); std::cout << "\n";
        std::cout << "  to_std.real=" << to_std.real() << " imag=" << to_std.imag() << "\n";
    }

    return 0;
}
