// Copyright (C) 2026 Kiyotsugu Arai
// SPDX-License-Identifier: LGPL-3.0-or-later

// matrix.cpp — explicit instantiation of Matrix<T> (float, double)
//
// This compiles the float/double Matrix code into sangi_matrix.lib exactly once,
// suppressing template re-instantiation in each TU.
// It pairs with the extern template declarations on the header side.

// In this TU, disable extern template and generate the actual entities here
#define SANGI_MATRIX_EXPLICIT_INSTANTIATION
#include <math/core/matrix.hpp>
// The implementation body of Matrix<T>::solve() lives in solvers.hpp, so
// include solvers.hpp here as well to ensure that the explicit instantiation
// (Matrix<float>, Matrix<double>) resolves all member functions.
#include <math/linalg/solvers.hpp>

namespace sangi {

// ---------------------------------------------------------------------------
// detail::DynamicMatrixStorage<T>
// ---------------------------------------------------------------------------
template class detail::DynamicMatrixStorage<float>;
template class detail::DynamicMatrixStorage<double>;

// ---------------------------------------------------------------------------
// detail::MatrixBase<T, DynamicMatrixStorage<T>>
// ---------------------------------------------------------------------------
template class detail::MatrixBase<float, detail::DynamicMatrixStorage<float>>;
template class detail::MatrixBase<double, detail::DynamicMatrixStorage<double>>;

// ---------------------------------------------------------------------------
// Matrix<T>
// ---------------------------------------------------------------------------
template class Matrix<float>;
template class Matrix<double>;

// ---------------------------------------------------------------------------
// Free functions
// ---------------------------------------------------------------------------
template Matrix<float> power(const Matrix<float>&, unsigned int);
template Matrix<double> power(const Matrix<double>&, unsigned int);

template std::ostream& operator<<(std::ostream&, const Matrix<float>&);
template std::ostream& operator<<(std::ostream&, const Matrix<double>&);

template std::string toLatex(const Matrix<float>&, const std::string&, std::size_t);
template std::string toLatex(const Matrix<double>&, const std::string&, std::size_t);

template Matrix<float> zeros(std::size_t, std::size_t);
template Matrix<double> zeros(std::size_t, std::size_t);

template Matrix<float> ones(std::size_t, std::size_t);
template Matrix<double> ones(std::size_t, std::size_t);

template Matrix<float> identity(std::size_t);
template Matrix<double> identity(std::size_t);

} // namespace sangi
