// =====================================================================================================================
//  fennec, a free and open source game engine
//  Copyright © 2025  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 exponential.h
/// \brief \ref fennec_math_exponential
///
///
/// \details
/// \author Medusa Slockbower
///
/// \copyright Copyright © 2025 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 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(fennec::genType, fennec::genType) "genFType pow(genFType x, genFType y)"
///     <td width="50%" style="vertical-align: top">
///         \copydetails fennec::pow(fennec::genType, fennec::genType)
///
/// <tr><td width="50%" style="vertical-align: top" class="odd_c"> <br>
///         \ref fennec::exp(fennec::genType)"genFType exp(genFType x)"
///     <td width="50%" style="vertical-align: top" class="odd_c">
///         \copydetails fennec::exp(fennec::genType)
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
///         \ref fennec::exp2(fennec::genType) "genFType exp2(genFType x)"
///     <td width="50%" style="vertical-align: top">
///         \copydetails fennec::exp2(fennec::genType)
///
/// <tr><td width="50%" style="vertical-align: top" class="odd_c"> <br>
///         \ref fennec::log(fennec::genType) "genFType log(genFType x)"
///     <td width="50%" style="vertical-align: top" class="odd_c">
///         \copydetails fennec::log(fennec::genType)
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
///         \ref fennec::log2(fennec::genType) "genFType log2(genFType x)"
///     <td width="50%" style="vertical-align: top">
///         \copydetails fennec::log2(fennec::genType)
///
/// <tr><td width="50%" style="vertical-align: top" class="odd_c"> <br>
///         \ref fennec::sqrt(fennec::genType) "genFType sqrt(genFType x)"
///     <td width="50%" style="vertical-align: top" class="odd_c">
///         \copydetails fennec::sqrt(fennec::genType)
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
///         \ref fennec::inversesqrt(fennec::genType) "genFType inversesqrt(genFType x)"
///     <td width="50%" style="vertical-align: top">
///         \copydetails fennec::inversesqrt(fennec::genType)
///
/// </table>
///
///
///

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

namespace fennec
{


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

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


// Vector Specialization -----------------------------------------------------------------------------------------------

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]) ...);
}


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

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


// Vector Specialization -----------------------------------------------------------------------------------------------

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


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

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


// Vector Specialization -----------------------------------------------------------------------------------------------

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


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

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


// Vector Specialization -----------------------------------------------------------------------------------------------

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


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

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


// Vector Specialization -----------------------------------------------------------------------------------------------

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


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

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


// Vector Specialization -----------------------------------------------------------------------------------------------

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


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

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


// Vector Specialization -----------------------------------------------------------------------------------------------

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_MATH_EXPONENTIAL_H
