// =====================================================================================================================
//  fennec, a free and open source game engine
//  Copyright © 2025 - 2026  Medusa Slockbower
//
//  This program is free software: you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation, either version 3 of the License, or
//  (at your option) any later version.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
//
//  You should have received a copy of the GNU General Public License
//  along with this program.  If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================

///
/// \file fennec/math/trigonometric.h
/// \brief the \ref fennec_math_trigonometric
///
///
/// \details
/// \author Medusa Slockbower
///
/// \copyright Copyright © 2025 - 2026 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
///
///

#ifndef FENNEC_MATH_TRIGONOMETRIC_H
#define FENNEC_MATH_TRIGONOMETRIC_H

///
///
///
/// \page fennec_math_trigonometric Trigonometry
///
/// \brief The Trigonometric Functions defined in the [OpenGL 4.6 Shading Language Specification](https://registry.khronos.org/OpenGL/specs/gl/GLSLangSpec.4.60.pdf).
///
/// \code #include <fennec/math/trigonometric.h> \endcode
///
///
///
///  \section section_fennec_conversions Angle Conversions
///
/// <table width="100%" class="fieldtable" id="table_fennec_math_trigonometry_angle_conversions">
/// <tr><th style="vertical-align: top">Syntax
///     <th style="vertical-align: top">Description
/// <tr><td width="50%" style="vertical-align: top"> <br>
///         \ref fennec::degrees "genFType degrees(genFType x)"
///     <td width="50%" style="vertical-align: top">
///         \copydoc fennec::degrees
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
///         \ref fennec::radians "genFType radians(genFType x)"
///     <td width="50%" style="vertical-align: top">
///         \copydoc fennec::radians
///
/// </table>
///
///
///
///  \section section_fennec_trigonometric_functions Trigonometric Functions
///
/// <table width="100%" class="fieldtable" id="table_fennec_math_trigonometry_functions">
/// <tr><th style="vertical-align: top">Syntax
///     <th style="vertical-align: top">Description
/// <tr><td width="50%" style="vertical-align: top"> <br>
///         \ref fennec::sin "genFType sin(genFType x)"
///     <td width="50%" style="vertical-align: top">
///         \copydoc fennec::sin
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
///         \ref fennec::cos "genFType cos(genFType x)"
///     <td width="50%" style="vertical-align: top">
///         \copydoc fennec::cos
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
///         \ref fennec::tan "genFType tan(genFType x)"
///     <td width="50%" style="vertical-align: top">
///         \copydoc fennec::tan
///
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
///         \ref fennec::asin "genFType asin(genFType x)"
///     <td width="50%" style="vertical-align: top">
///         \copydoc fennec::asin
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
///         \ref fennec::acos "genFType acos(genFType x)"
///     <td width="50%" style="vertical-align: top">
///         \copydoc fennec::acos
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
///         \ref fennec::atan "genFType atan(genFType x)"
///     <td width="50%" style="vertical-align: top">
///         \copydoc fennec::atan
///
/// </table>
///
///
///
///  \section section_fennec_hyperbolic_functions Hyperbolic Functions
///
/// <table width="100%" class="fieldtable" id="table_fennec_math_trigonometry_hyperbolic">
/// <tr><th style="vertical-align: top">Syntax
///     <th style="vertical-align: top">Description
/// <tr><td width="50%" style="vertical-align: top"> <br>
///         \ref fennec::sinh "genFType sinh(genFType x)"
///     <td width="50%" style="vertical-align: top">
///         \copydoc fennec::sinh
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
///         \ref fennec::cosh "genFType cosh(genFType x)"
///     <td width="50%" style="vertical-align: top">
///         \copydoc fennec::cosh
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
///         \ref fennec::tanh "genFType tanh(genFType x)"
///     <td width="50%" style="vertical-align: top">
///         \copydoc fennec::tanh
///
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
///         \ref fennec::asinh "genFType asinh(genFType x)"
///     <td width="50%" style="vertical-align: top">
///         \copydoc fennec::asinh
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
///         \ref fennec::acosh "genFType acosh(genFType x)"
///     <td width="50%" style="vertical-align: top">
///         \copydoc fennec::acosh
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
///         \ref fennec::atanh "genFType atanh(genFType x)"
///     <td width="50%" style="vertical-align: top">
///         \copydoc fennec::atanh
///
/// </table>
///
///
///
///
///

#include <fennec/math/detail/_math.h>
#include <fennec/math/vector.h>
#include <fennec/lang/types.h>

namespace fennec
{

// Angle Conversions ===================================================================================================

/// \name Angle Conversions
/// @{

///
/// \brief Converts \emph{degrees} to \emph{radians}, i.e., \math{degrees\cdot\frac{180}{\pi}}
///
/// \returns the angle \math{\theta} in \math{radians} <br><br>
/// \details Converts \emph{degrees} to \emph{radians}, i.e., \math{degrees\cdot\frac{180}{\pi}} <br><br>
///
/// \tparam genType floating point type
/// \param degrees the angle \math{\theta} in \math{degrees}
template<typename genType>
constexpr genType radians(genType degrees) {
	return genType(degrees * 0.01745329251994329576923690768489);
}


///
/// \brief Converts \emph{radians} to \emph{degrees}, i.e., \math{radians\cdot\frac{\pi}{180}}
///
/// \returns the angle \math{\theta} in \emph{degrees} <br><br>
/// \details Converts \emph{radians} to \emph{degrees}, i.e., \math{radians\cdot\frac{\pi}{180}} <br><br>
///
/// \tparam genType floating point type
/// \param radians the angle \math{\theta} in \emph{radians}
template<typename genType>
constexpr genType degrees(genType radians) {
	return genType(radians * 57.29577951308232087679815481410517);
}

/// @}



// Trigonometric  ======================================================================================================

/// \name Trigonometric Functions
/// @{

///
/// \brief The standard trigonometric sine
///
/// \returns the sine of \math{\theta} in the range \math{\left[-1,\,1\right]} <br><br>
/// \details The standard trigonometric sine <br><br>
///
/// \tparam genType floating point type
/// \param x the angle \math{\theta} in \math{radians}
template<typename genType>
constexpr genType sin(genType x) {
	return ::sin(x);
}


///
/// \brief The Standard Trigonometric Cosine
///
/// \returns the cosine of \math{\theta} in the range \math{\left[-1,\,1\right]} <br><br>
/// \details The Standard Trigonometric Cosine <br><br>
///
/// \tparam genType floating point type
/// \param x the angle \math{\theta} in \emph{radians}
template<typename genType>
constexpr genType cos(genType x) {
	return ::cos(x);
}


///
/// \brief The Standard Trigonometric Tangent
///
/// \returns The Tangent of \math{\theta} in the Range \math{\left[-\inf,\,\inf\right]}<br><br>
/// \details The Standard Trigonometric Tangent <br><br>
///
/// \tparam genType floating point type
/// \param x The Angle \math{\theta} in \math{radians}
template<typename genType>
constexpr genType tan(genType x) {
	return ::tan(x);
}

/// @}



/// \name Inverse Trigonometric Functions
/// @{

///
/// \brief Arc Sine. Returns an angle \math{\theta} whose sine is /a x.
///
/// \returns an angle \math{\theta} whose sine is /a x. <br><br>
/// \details Arc Sine. The range of values returned by this functions is
///          \math{\left[-\pi/2,\pi/2\right]}. Results are undefined if \math{\left|x\right|\,>\,1}. <br><br>
///
/// \tparam genType floating point type
/// \param x The Sine Value produced by \math{\theta}
template<typename genType>
constexpr genType asin(genType x) {
	return ::asin(x);
}


///
/// \brief Arc Cosine. Returns an angle \math{\theta} whose cosine is /a x.
///
/// \returns an angle \math{\theta} whose cosine is /a x.
/// \details Arc Cosine. The range of values returned by this functions is
///          \math{\left[0,\pi\right]}. Results are undefined if \math{\left|x\right|\,>\,1}.
///
/// \tparam genType floating point type
/// \param x The Cosine Value produced by \math{\theta}
template<typename genType>
constexpr genType acos(genType x) {
	return ::acos(x);
}


///
/// \brief Arc Tangent. Returns an angle \math{\theta} whose tangent is /a y_over_x.
///
/// \returns an angle \math{\theta} whose tangent is /a y_over_x.
/// \details Arc Tangent. The range of values returned by this functions is
///        \math{\left[\frac{-\pi}{2},\frac{\pi}{2}\right]}. Results are undefined if \math{\left|x\right|\,>\,1}.
///
/// \tparam genType floating point type
/// \param y_over_x The Cosine Value produced by \math{\theta}
template<typename genType>
constexpr genType atan(genType y_over_x) {
	return ::atan(y_over_x);
}


///
/// \brief Arc Tangent. Returns an angle whose tangent is \math{\frac{y}{x}}.
///
/// \returns an angle whose tangent is \math{\frac{y}{x}}. <br><br>
/// \details Arc Tangent. The signs of \a x and \a y are used to determine what quadrant the angle is in.
///        The range of values returned by this functions is \math{\left[-\pi,\pi\right]} <br><br>
///
/// \tparam genType floating point type
/// \param y The Sine Value produced by \math{\theta}
/// \param x The Cosine Value produced by \math{\theta}
template<typename genType>
constexpr genType atan(genType y, genType x) {
	return ::atan2(y, x);
}

/// @}



// Hyperbolic Functions ================================================================================================

/// \name Hyperbolic Functions
/// @{

///
/// \brief Returns the Hyperbolic Sine Function, \math{\frac{{e}^{x}-{e}^{-x}}{2}}
///
/// \returns The Hyperbolic Sine of \math{x}, \math{\frac{{e}^{x}-{e}^{-x}}{2}} <br><br>
///
/// \tparam genType floating point type
/// \param x The Hyperbolic Angle \math{\alpha}
template<typename genType>
constexpr genType sinh(genType x) {
	return ::sinh(x);
}


///
/// \brief Returns the Hyperbolic Cosine Function, \math{\frac{{e}^{x}+{e}^{-x}}{2}}
///
/// \returns The Hyperbolic Cosine of \math{x}, \math{\frac{{e}^{x}+{e}^{-x}}{2}} <br><br>
///
/// \param x The Hyperbolic Angle \math{\alpha}
template<typename genType>
constexpr genType cosh(genType x) {
	return ::cosh(x);
}


///
/// \brief Returns the Hyperbolic Tangent Function, \math{\frac{\text{sinh}(x)}{\text{cosh}(x)}}
///
/// \returns The Hyperbolic Tangent of \math{x}, \math{\frac{{e}^{x}+{e}^{-x}}{2}} <br><br>
///
/// \param x The Hyperbolic Angle \math{\alpha}
template<typename genType, size_t...i>
constexpr genType tanh(genType x) {
	return ::tanh(x);
}

/// @}



/// \name Inverse Hyperbolic Functions
/// @{

///
/// \brief The Inverse Hyperbolic Sine Function
///
/// \returns the value \math{y} that fulfills \math{x=\text{sinh}(y)} <br><br>
/// \details The Inverse Hyperbolic Sine Function <br><br>
///
/// \param x the hyperbolic angle \math{\alpha}
template<typename genType, size_t...i>
constexpr genType asinh(genType x) {
	return ::asinh(x);
}


///
/// \brief The Inverse Hyperbolic Cosine Function
///
/// \returns the value \math{y} that fulfills \math{x=\text{cosh}(y)} <br><br>
/// \details The Inverse Hyperbolic Cosine Function <br><br>
///
/// \param x the hyperbolic angle \math{\alpha}
template<typename genType, size_t...i>
constexpr genType acosh(genType x) {
	return ::acosh(x);
}


///
/// \brief The Inverse Hyperbolic Tangent Function
///
/// \returns the value \math{y} that fulfills \math{x=\text{atanh}(y)} <br><br>
/// \details The Inverse Hyperbolic Tangent Function <br><br>
///
/// \param x The Hyperbolic Angle \math{\alpha}
template<typename genType, size_t...i>
constexpr genType atanh(genType x) {
	return ::atanh(x);
}

/// @}



// Internal ============================================================================================================

#ifndef FENNEC_DOXYGEN
template<typename genType, size_t...i>
constexpr vector<genType, i...> radians(const vector<genType, i...>& degrees) {
	return vector<genType, i...>(degrees * 0.01745329251994329576923690768489);
}

template<typename genType, size_t...i>
constexpr vector<genType, i...> degrees(const vector<genType, i...>& radians) {
	return genType(radians * 57.29577951308232087679815481410517);
}

template<typename genType, size_t...i>
constexpr vector<genType, i...> sin(const vector<genType, i...>& x) {
	return vector<genType, i...>(fennec::sin(x[i]) ...);
}

template<typename genType, size_t...i>
constexpr vector<genType, i...> cos(const vector<genType, i...>& x) {
	return vector<genType, i...>(fennec::cos(x[i]) ...);
}

template<typename genType, size_t...i>
constexpr vector<genType, i...> tan(const vector<genType, i...>& x) {
	return vector<genType, i...>(fennec::tan(x[i]) ...);
}

template<typename genType, size_t...i>
constexpr vector<genType, i...> asin(const vector<genType, i...>& x) {
	return vector<genType, i...>(fennec::asin(x[i]) ...);
}

template<typename genType, size_t...i>
constexpr vector<genType, i...> acos(const vector<genType, i...>& x) {
	return vector<genType, i...>(fennec::acos(x[i]) ...);
}

template<typename genType, size_t...i>
constexpr vector<genType, i...> atan(const vector<genType, i...>& y_over_x) {
	return vector<genType, i...>(fennec::atan(y_over_x[i]) ...);
}

template<typename genType, size_t...i>
constexpr vector<genType, i...> atan(const vector<genType, i...>& y, const vector<genType, i...>& x) {
	return vector<genType, i...>(fennec::atan(y[i], x[i]) ...);
}

template<typename genType, size_t...i>
constexpr vector<genType, i...> sinh(const vector<genType, i...>& x) {
	return vector<genType, i...>(fennec::sinh(x[i]) ...);
}

template<typename genType, size_t...i>
constexpr vector<genType, i...> cosh(const vector<genType, i...>& x) {
	return vector<genType, i...>(fennec::cosh(x[i]) ...);
}

template<typename genType, size_t...i>
constexpr vector<genType, i...> tanh(const vector<genType, i...>& x) {
	return vector<genType, i...>(fennec::tanh(x[i]) ...);
}

template<typename genType, size_t...i>
constexpr vector<genType, i...> asinh(const vector<genType, i...>& x) {
	return vector<genType, i...>(fennec::asinh(x[i]) ...);
}

template<typename genType, size_t...i>
constexpr vector<genType, i...> acosh(const vector<genType, i...>& x) {
	return vector<genType, i...>(fennec::acosh(x[i]) ...);
}

template<typename genType, size_t...i>
constexpr vector<genType, i...> atanh(const vector<genType, i...>& x) {
	return vector<genType, i...>(fennec::atanh(x[i]) ...);
}
#endif



}



#endif // FENNEC_MATH_TRIGONOMETRIC_H
