math.h 3.37 KB
Newer Older
Sebastian Wolf's avatar
Sebastian Wolf committed
1
// Xerus - A General Purpose Tensor Library
2
// Copyright (C) 2014-2017 Benjamin Huber and Sebastian Wolf. 
Sebastian Wolf's avatar
Sebastian Wolf committed
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
// 
// Xerus is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License,
// or (at your option) any later version.
// 
// Xerus 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 Affero General Public License for more details.
// 
// You should have received a copy of the GNU Affero General Public License
// along with Xerus. If not, see <http://www.gnu.org/licenses/>.
//
// For further information on Xerus visit https://libXerus.org 
// or contact us at contact@libXerus.org.

/**
* @file
* @brief Header file for some additional math functions.
*/

#pragma once

27 28
#include <limits>
#include <cmath>
Sebastian Wolf's avatar
Sebastian Wolf committed
29
#include "standard.h"
30
#include "sfinae.h"
Sebastian Wolf's avatar
Sebastian Wolf committed
31 32 33 34 35

namespace xerus {
	namespace misc {
		///@brief: Calculates the signum (-1, 0, 1) of a given value.
		template<class T> 
Benjamin Huber's avatar
Benjamin Huber committed
36
		constexpr int sgn(const T _value) noexcept {
Sebastian Wolf's avatar
Sebastian Wolf committed
37 38 39 40 41 42
			return (T(0) < _value) - (_value < T(0));
		}
		
		
		///@brief: Calculates _a*_a.
		template<class T>
Benjamin Huber's avatar
Benjamin Huber committed
43
		constexpr T sqr(const T &_a) noexcept {
Sebastian Wolf's avatar
Sebastian Wolf committed
44 45 46 47
			return _a*_a;
		}
		
		
Sebastian Wolf's avatar
Sebastian Wolf committed
48
		///@brief: Calculates _base^_exp by binary exponentiation
49 50
		template<class T, class I, typename std::enable_if<std::is_integral<I>::value && std::is_unsigned<I>::value, bool>::type = true> 
		constexpr T pow(const T &_base, const I _exp) noexcept {
Sebastian Wolf's avatar
Sebastian Wolf committed
51
			return _exp==0 ? T(1) : (_exp%2==0 ? pow(T(_base*_base), _exp/2) : T(_base*pow(_base, _exp-1)));
Sebastian Wolf's avatar
Sebastian Wolf committed
52 53 54 55
		}
		
		
		///@brief: Calculates _base^_exp by binary exponentiation
56 57
		template<class T, class I, typename std::enable_if<std::is_integral<I>::value && !std::is_unsigned<I>::value, bool>::type = true> 
		constexpr T pow(const T &_base, const I _exp) noexcept {
Sebastian Wolf's avatar
Sebastian Wolf committed
58
			return _exp==0 ? 
Sebastian Wolf's avatar
Sebastian Wolf committed
59
						T(1) :
Sebastian Wolf's avatar
Sebastian Wolf committed
60
						(
Sebastian Wolf's avatar
Sebastian Wolf committed
61 62 63 64
							_exp<0 ? 
								T( 1/pow(_base, -_exp)) 
							: 
								( _exp%2==0 ? pow(T(_base*_base), _exp/2) : T(_base*pow(_base, _exp-1)) )
Sebastian Wolf's avatar
Sebastian Wolf committed
65 66 67 68 69 70
						);
		}
		
		
		///@brief: Checks whether the relative difference between @a _a and @a _b (i.e. |a-b|/(|a|/2+|b|/2)) is smaller than @a _eps.
		template<class T, typename std::enable_if<std::is_floating_point<T>::value, bool>::type = true>
Benjamin Huber's avatar
Benjamin Huber committed
71
		bool approx_equal(T _a, T _b, T _eps = 4*std::numeric_limits<T>::epsilon()) noexcept {
Sebastian Wolf's avatar
Sebastian Wolf committed
72 73 74 75 76 77 78 79 80 81 82 83 84
			return std::abs(_a-_b) <= _eps*0.5*(std::abs(_a)+std::abs(_b));
		}
		
		
		///@brief: Checks whether @a _a and @a _b are equal (for non floating point types).
		template<class T, typename std::enable_if<!std::is_floating_point<T>::value, bool>::type = true>
		bool approx_equal(T _a, T _b) {
			return _a == _b;
		}
		
		
		///@brief: Checks for hard equality ( == operator) without compiler warnings.
		template<class T>
Benjamin Huber's avatar
Benjamin Huber committed
85
		constexpr bool hard_equal(const T _a, const T _b) noexcept {
Sebastian Wolf's avatar
Sebastian Wolf committed
86 87 88 89 90 91 92
			#pragma GCC diagnostic push
				#pragma GCC diagnostic ignored "-Wfloat-equal"
				return _a == _b;
			#pragma GCC diagnostic pop
		}
		
		
93
		///@brief: Checks for hard inequality ( != operator) without compiler warnings.
Sebastian Wolf's avatar
Sebastian Wolf committed
94
		template<class T>
Benjamin Huber's avatar
Benjamin Huber committed
95
		constexpr bool hard_not_equal(const T _a, const T _b) noexcept {
Sebastian Wolf's avatar
Sebastian Wolf committed
96 97 98 99 100 101 102
			#pragma GCC diagnostic push
				#pragma GCC diagnostic ignored "-Wfloat-equal"
				return _a != _b;
			#pragma GCC diagnostic pop
		}
	}
}