// Copyright (C) 2026 Kiyotsugu Arai
// SPDX-License-Identifier: LGPL-3.0-or-later
//
// example_doc_tensor_samples.cpp
// Verification harness for samples in api/Tensor.html.

#include <math/core/Tensor.hpp>
#include <math/core/matrix.hpp>
#include <math/core/vector.hpp>
#include <cmath>
#include <iomanip>
#include <iostream>

using namespace sangi;

template <typename T>
void print_tensor(const Tensor<T>& t) {
    std::cout << "shape=[";
    for (std::size_t i = 0; i < t.rank(); ++i) {
        if (i) std::cout << ",";
        std::cout << t.shape(i);
    }
    std::cout << "] data=[";
    for (std::size_t i = 0; i < t.size(); ++i) {
        if (i) std::cout << ",";
        std::cout << t.flat(i);
    }
    std::cout << "]";
}

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

    // ---- constructors --------------------------------------------
    {
        std::cout << "[constructors]\n";
        Tensor<double> t0;                              // rank-0 scalar
        Tensor<double> t1({3, 4, 5});                   // rank-3, zero
        Tensor<double> t2({2, 3}, 1.0);                 // all 1.0
        Tensor<double> t3({2, 3}, {1.0,2.0,3.0,4.0,5.0,6.0});
        Tensor<double> s(3.14);                         // rank-0
        std::cout << "  t0.rank=" << t0.rank() << " (=" << t0.flat(0) << ")\n";
        std::cout << "  t1: "; print_tensor(t1); std::cout << "\n";
        std::cout << "  t2: "; print_tensor(t2); std::cout << "\n";
        std::cout << "  t3: "; print_tensor(t3); std::cout << "\n";
        std::cout << "  s.toScalar=" << s.toScalar() << "\n";
    }

    // ---- reshape / transpose -------------------------------------
    {
        std::cout << "[reshape/transpose]\n";
        Tensor<double> t({2, 3, 4}, 1.0);
        auto r  = t.reshape({6, 4});
        auto tT = t.transpose({2, 1, 0});
        auto m  = t.transpose();
        std::cout << "  reshape: "; print_tensor(r); std::cout << "\n";
        std::cout << "  transpose({2,1,0}): rank=" << tT.rank() << " shape={"
                  << tT.shape(0) << "," << tT.shape(1) << "," << tT.shape(2)
                  << "} isContiguous=" << std::boolalpha << tT.isContiguous() << "\n";
        std::cout << "  full-reverse transpose: rank=" << m.rank()
                  << " shape={" << m.shape(0) << "," << m.shape(1) << "," << m.shape(2) << "}\n";
    }

    // ---- hadamard ------------------------------------------------
    {
        std::cout << "[hadamard]\n";
        Tensor<double> a({2,3}, {1.0,2.0,3.0,4.0,5.0,6.0});
        Tensor<double> b({2,3}, {6.0,5.0,4.0,3.0,2.0,1.0});
        Tensor<double> h = hadamard(a, b);
        std::cout << "  h: "; print_tensor(h); std::cout << "\n";
    }

    // ---- matrix product via contract -----------------------------
    {
        std::cout << "[contract = matmul]\n";
        Tensor<double> M({3, 4}, 1.0);
        Tensor<double> N({4, 5}, 2.0);
        Tensor<double> C = contract(M, N, {{1, 0}});
        std::cout << "  result: "; print_tensor(C); std::cout << "\n";
    }

    // ---- outer product -------------------------------------------
    {
        std::cout << "[outer product]\n";
        Tensor<double> u({3}, {1.0, 2.0, 3.0});
        Tensor<double> v({2}, {10.0, 20.0});
        Tensor<double> K = outerProduct(u, v);
        std::cout << "  K: "; print_tensor(K); std::cout << "\n";
    }

    // ---- Matrix / Vector interop ---------------------------------
    {
        std::cout << "[Matrix interop]\n";
        Matrix<double> M(3, 3, 1.0);
        Tensor<double> tM(M);
        std::cout << "  tM.rank=" << tM.rank() << " size=" << tM.size() << "\n";
        Matrix<double> M2 = tM.toMatrix();
        std::cout << "  round-trip: M2(0,0)=" << M2(0,0) << " M2(2,2)=" << M2(2,2) << "\n";
    }

    return 0;
}
