#pragma region CPL License
/*
Nuclex Native Framework
Copyright (C) 2002-2015 Nuclex Development Labs
This library is free software; you can redistribute it and/or
modify it under the terms of the IBM Common Public License as
published by the IBM Corporation; either version 1.0 of the
License, or (at your option) any later version.
This library 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
IBM Common Public License for more details.
You should have received a copy of the IBM Common Public
License along with this library
*/
#pragma endregion // CPL License
#ifndef NUCLEX_GEOMETRY_MATH_H
#error This file must be included through Math.h
#endif
namespace Nuclex { namespace Geometry {
// ------------------------------------------------------------------------------------------- //
/// Math routines for geometry classes based on long double precision floats
template <>
class Math {
/// The PI constant
public: NUCLEX_GEOMETRY_API static constexpr long double Pi = (
3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825L
);
/// Two times PI, useful for some operations
public: NUCLEX_GEOMETRY_API static constexpr long double Perigon = (
6.283185307179586476925286766559005768394338798750211641949889184615632812572417997256069651L
);
/// Calculates the square root of the specified value
/// Value of which the square root is calculated
/// The square root of the specified number
public: NUCLEX_GEOMETRY_API static long double SquareRoot(long double value) {
return std::sqrt(value);
}
/// Returns a random number from 0.0 to the specified maximum
/// The random number generator that will be used
/// Upper limit for the random number (exclusive)
/// A random number from 0.0 to the specified maximum
public: template static long double Random(
TRandomNumberEngine &random, long double max
) {
std::uniform_real_distribution distribution(0.0, max);
return distribution(random);
}
/// Returns a random number in the specified range
/// The random number generator that will be used
/// Minimum possible value of the random number
/// Upper limit for the random number (exclusive)
/// A random number within the specified range
public: template static long double Random(
TRandomNumberEngine &random, long double min, long double max
) {
std::uniform_real_distribution distribution(min, max);
return distribution(random);
}
/// Calculates the sine of the specified angle
/// Angle for which the sine will be calculated
/// The sine of the specified angle
public: NUCLEX_GEOMETRY_API static long double Sine(long double angleInRadians) {
return std::sin(angleInRadians);
}
/// Calculates the cosine of the specified angle
/// Angle for which the cosine will be calculated
/// The cosine of the specified angle
public: NUCLEX_GEOMETRY_API static long double Cosine(long double angleInRadians) {
return std::cos(angleInRadians);
}
/// Calculates the angle of the specified sine value
/// Sine value of which the angle will be calculated
/// The angle of the specified sine value in radians
public: NUCLEX_GEOMETRY_API static long double ArcSine(long double sineValue) {
return std::asin(sineValue);
}
/// Calculates the angle of the specified cosine value
/// Cosine value for which the angle will be calculated
/// The angle of the specified cosine value in radians
public: NUCLEX_GEOMETRY_API static long double ArcCosine(long double cosineValue) {
return std::acos(cosineValue);
}
/// Calculates the angle of the tangent specified by a direction
/// X coordinate of the direction
/// Y coordinate of the direction
/// The angle of the tangent specified through the direction
public: NUCLEX_GEOMETRY_API static long double ArcTangent(long double x, long double y) {
return std::atan2(y, x);
}
/// Returns the absolute value of the specified value
/// Value of which the absolute value will be returned
/// The absolute value of the provided value
public: NUCLEX_GEOMETRY_API static long double Abs(long double value) {
return std::fabs(value);
}
/// Calculates to the power of
/// Value that will be multiplied
/// To which power the value will be multiplied
/// to the power of
public: NUCLEX_GEOMETRY_API static long double Power(long double value, long double power) {
return std::pow(value, power);
}
/// Returns the smaller of two values
/// First of the two values
/// Second of the two values
/// The smaller of the two provided values
public: NUCLEX_GEOMETRY_API static long double Min(long double first, long double second) {
return std::min(first, second);
}
/// Returns the smallest of three values
/// First of the three values
/// Second of the three values
/// Third of the three values
/// The smallest of the three provided values
public: NUCLEX_GEOMETRY_API static long double Min(
long double first, long double second, long double third
) {
return std::min(std::min(first, second), third);
}
/// Returns the larger of two values
/// First of the two values
/// Second of the two values
/// The larger of the two provided values
public: NUCLEX_GEOMETRY_API static long double Max(long double first, long double second) {
return std::max(first, second);
}
/// Returns the largest of three values
/// First of the three values
/// Second of the three values
/// Third of the three values
/// The largest of the three provided values
public: NUCLEX_GEOMETRY_API static long double Max(
long double first, long double second, long double third
) {
return std::max(std::max(first, second), third);
}
/// Determines the extremes of two values
/// First of the values whose extremes will be found
/// Second of the values whose extremes will be found
///
/// A pair containing the smaller and the larger value in that order
///
public: NUCLEX_GEOMETRY_API static std::pair Extremes(
long double first, long double second
) {
if(first < second) {
return std::pair(first, second);
} else {
return std::pair(second, first);
}
}
/// Determines the extremes of three values
/// First of the values whose extremes will be found
/// Second of the values whose extremes will be found
/// Third of the values whose extremes will be found
///
/// A pair containing the smallest and the largest value of the three inputs
///
public: NUCLEX_GEOMETRY_API static std::pair Extremes(
long double first, long double second, long double third
) {
if(first < second) {
if(second < third) { // first < second < third
return std::make_pair(first, third);
} else if(first < third) { // first < third < second
return std::make_pair(first, second);
} else { // third < first < second
return std::make_pair(third, second);
}
} else {
if(first < third) { // second < first < third
return std::make_pair(second, third);
} else if(second < third) { // second < third < first
return std::make_pair(second, first);
} else { // third < second < first
return std::make_pair(third, first);
}
}
}
/// Unwinds a value in a circular (repeating) value range
/// Value that will be unwound
/// Lower limit of the circular value range
/// Upper limit of the circular value range
/// The unwound value
public: NUCLEX_GEOMETRY_API static long double Unwind(
long double value, long double min, long double max
) {
long double range = (max - min);
long double floor = std::floor((value - min) / range);
return value - (floor * range);
}
/// Limits the value to the specified range
/// Value that will be limited
/// Minimum the value cannot go under
/// Maximum the value cannot go above
/// The value limited to the specified range
public: NUCLEX_GEOMETRY_API static long double Clamp(
long double value, long double min, long double max
) {
if(value < min) {
return min;
}
if(value > max) {
return max;
}
return value;
}
/// Linearly interpolates between two values
/// Value at the left interpolation point
/// Value at the right interpolation point
/// Time (0.0 .. 1.0) for which to interpolate the value
/// The interpolated value at the specified time
public: NUCLEX_GEOMETRY_API static long double Lerp(
long double left, long double right, long double t
) {
return (right - left) * t + left;
}
/// Calculates the time of a linearly interpolated value
/// Value at the left interpolation point
/// Value at the right interpolation point
/// Value that resulted from the interpolation
/// Time at which the value is placed in the interpolation range
public: NUCLEX_GEOMETRY_API static long double Unlerp(
long double left, long double right, long double value
) {
return (value - left) / (right - left);
}
/// Checks whether the specified value is invalid (not a number)
/// Value that will be checked
/// True if the specified value is not a number
public: NUCLEX_GEOMETRY_API static bool IsNan(long double value) {
return std::isnan(value);
}
};
// ------------------------------------------------------------------------------------------- //
}} // namespace Nuclex::Geometry