// =====================================================================================================================
//  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/exponential.h
/// \brief \ref fennec_math_exponential
///
///
/// \details
/// \author Medusa Slockbower
///
/// \copyright Copyright © 2025 - 2026 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
///
///


#ifndef FENNEC_MATH_EXPONENTIAL_H
#define FENNEC_MATH_EXPONENTIAL_H

///
///
///
/// \page fennec_math_exponential Exponential
///
/// \brief The Exponential 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/exponential.h> \endcode
///
///
/// \section fennec_math_exponential_section_functions Exponential Functions
///
/// <table width="100%" class="fieldtable" id="table_fennec_math_exponential_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::pow "genFType pow(genFType x, genFType y)"
///     <td width="50%" style="vertical-align: top">
///         \copydetails fennec::pow
///
/// <tr><td width="50%" style="vertical-align: top" class="odd_c"> <br>
///         \ref fennec::exp"genFType exp(genFType x)"
///     <td width="50%" style="vertical-align: top" class="odd_c">
///         \copydetails fennec::exp
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
///         \ref fennec::exp2 "genFType exp2(genFType x)"
///     <td width="50%" style="vertical-align: top">
///         \copydetails fennec::exp2
///
/// <tr><td width="50%" style="vertical-align: top" class="odd_c"> <br>
///         \ref fennec::log "genFType log(genFType x)"
///     <td width="50%" style="vertical-align: top" class="odd_c">
///         \copydetails fennec::log
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
///         \ref fennec::log2 "genFType log2(genFType x)"
///     <td width="50%" style="vertical-align: top">
///         \copydetails fennec::log2
///
/// <tr><td width="50%" style="vertical-align: top" class="odd_c"> <br>
///         \ref fennec::sqrt "genFType sqrt(genFType x)"
///     <td width="50%" style="vertical-align: top" class="odd_c">
///         \copydetails fennec::sqrt
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
///         \ref fennec::inversesqrt "genFType inversesqrt(genFType x)"
///     <td width="50%" style="vertical-align: top">
///         \copydetails fennec::inversesqrt
///
/// </table>
///
///
///

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

namespace fennec
{


// pow =================================================================================================================

///
/// \brief Returns \math{x} raised to the \math{y} power, i.e., \math{x^y}.
///
/// \returns \math{x} raised to the \math{y} power, i.e., \math{x^y}.<br><br>
/// \details Results are undefined if \math{x<0}. <br><br>Results are undefined if \math{x=0} and \math{{y}\le{0}}.<br><br>
///
/// \param x the base
/// \param y the exponent
template<typename genType>
constexpr genType pow(genType x, genType y) {
	return ::pow(x, y);
}


// exp =================================================================================================================

///
/// \brief Returns the natural exponentiation of \math{x}, i.e., \math{e^x}
///
/// \returns the natural exponentiation of \math{x}, i.e., \math{e^x}.<br><br>
///
/// \param x the exponent
template<typename genType>
constexpr genType exp(genType x) {
	return ::exp(x);
}


// exp2 ================================================================================================================

///
/// \brief Returns 2 raised to the \math{x} power, i.e., \math{e^x}
///
/// \returns 2 raised to the \math{x} power, i.e., \math{e^x}<br><br>
///
/// \param x the exponent
template<typename genType> constexpr genType exp2(genType x) {
	return ::exp2(x);
}


// log =================================================================================================================

///
/// \brief Returns the natural logarithm of \math{x}.
///
/// \returns the natural logarithm of \math{x}, i.e., returns the value \math{y} which satisfies the equation \math{x=e^y}.<br><br>
/// \details Results are undefined if \math{{x}\le{0}}.<br><br>
///
/// \param x the input value
template<typename genType> constexpr genType log(genType x) {
	return ::log(x);
}


// log2 ================================================================================================================

///
/// \brief Returns the base 2 logarithm of \math{x}.
///
/// \returns the base 2 logarithm of \math{x}, i.e., returns the value \math{y} which satisfies the equation
///          \math{x=2^y}. <br><br>
/// \details Results are undefined if \math{{x}\le{0}}. <br><br>
///
/// \param x the input value
template<typename genType> constexpr genType log2(genType x) {
	return ::log2(x);
}


// sqrt ================================================================================================================

///
/// \brief Returns \math{\sqrt{x}}.
///
/// \returns \math{\sqrt{x}}. <br><br>
/// \details Results are undefined if \math{x<0}<br><br>
///
/// \param x the input value
template<typename genType> constexpr genType sqrt(genType x) {
	return ::sqrt(x);
}


// inversesqrt =========================================================================================================

///
/// \brief Returns \math{\frac{1}{\sqrt{x}}}.
///
/// \returns \math{\frac{1}{\sqrt{x}}}.<br><br>
/// \details Results are undefined if \math{x<0}.<br><br>
///
/// \param x the input value
template<typename genType> constexpr genType inversesqrt(genType x) {
	return 1.0f / ::sqrt(x);
}


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

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

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

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

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

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

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

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


}

#endif // FENNEC_MATH_EXPONENTIAL_H
