neoGFX
Cross-platform C++ app/game engine
Loading...
Searching...
No Matches
numerical.hpp
Go to the documentation of this file.
1// numerical.hpp
2/*
3 neogfx C++ App/Game Engine
4 Copyright (c) 2020 Leigh Johnston. All Rights Reserved.
5
6 This program is free software: you can redistribute it and / or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
18*/
19
20#pragma once
21
22#include <neogfx/neogfx.hpp>
24
25namespace neogfx
26{
27 namespace math
28 {
29 using namespace boost::math::constants;
30 using namespace neolib::math;
31 }
32
33 using namespace boost::math::constants;
34 using namespace neolib::math;
35
36 using neolib::math::operators::operator~;
37 using neolib::math::operators::operator+;
38 using neolib::math::operators::operator-;
39 using neolib::math::operators::operator*;
40 using neolib::math::operators::operator/;
41 using neolib::math::operators::operator<;
42 using neolib::math::operators::operator>;
43 using neolib::math::operators::operator<=;
44 using neolib::math::operators::operator>=;
45 using neolib::math::operators::operator==;
46 using neolib::math::operators::operator!=;
47
49
50 // why? most of these operations would normally be indeterminate; only use these functions if inf is being used as a special a sentinal value (e.g. neoGFX unbounded dimensions)
51 template <typename T>
52 inline T inf_add(T lhs, T rhs)
53 {
54 if (lhs != std::abs(std::numeric_limits<T>::infinity()) && rhs != std::abs(std::numeric_limits<T>::infinity()))
55 return lhs + rhs;
56 else if (lhs == std::numeric_limits<T>::infinity() && rhs == std::numeric_limits<T>::infinity())
57 return std::numeric_limits<T>::infinity();
58 else if (lhs == -std::numeric_limits<T>::infinity() && rhs == -std::numeric_limits<T>::infinity())
59 return -std::numeric_limits<T>::infinity();
60 else if (lhs == -std::numeric_limits<T>::infinity() && rhs == std::numeric_limits<T>::infinity())
61 return 0.0;
62 else if (lhs == std::numeric_limits<T>::infinity() && rhs == -std::numeric_limits<T>::infinity())
63 return 0.0;
64 else if (lhs == std::numeric_limits<T>::infinity() || rhs == std::numeric_limits<T>::infinity())
65 return std::numeric_limits<T>::infinity();
66 else
67 return -std::numeric_limits<T>::infinity();
68 }
69
70 // why? most of these operations would normally be indeterminate; only use these functions if inf is being used as a special a sentinal value (e.g. neoGFX unbounded dimensions)
71 template <typename T>
72 inline T inf_multiply(T lhs, T rhs)
73 {
74 if (lhs == 0.0 || rhs == 0.0)
75 return 0.0;
76 else if (lhs != std::numeric_limits<T>::infinity() && rhs != std::numeric_limits<T>::infinity())
77 return lhs * rhs;
78 else if ((lhs > 0.0 && rhs > 0.0) || (lhs < 0.0 && rhs < 0.0))
79 return std::numeric_limits<T>::infinity();
80 else
81 return -std::numeric_limits<T>::infinity();
82 }
83
84 // why? most of these operations would normally be indeterminate; only use these functions if inf is being used as a special a sentinal value (e.g. neoGFX unbounded dimensions)
85 template <typename T, uint32_t D>
87 {
88 if (left.is_identity())
89 return right;
91 for (uint32_t row = 0; row < D; ++row)
92 for (uint32_t index = 0; index < D; ++index)
93 result[row] = inf_add(result[row], inf_multiply(left[index][row], right[index]));
94 return result;
95 }
96
97 // why? most of these operations would normally be indeterminate; only use these functions if inf is being used as a special a sentinal value (e.g. neoGFX unbounded dimensions)
98 template <typename T, uint32_t D>
100 {
101 if (right.is_identity())
102 return left;
104 for (uint32_t column = 0; column < D; ++column)
105 for (uint32_t index = 0; index < D; ++index)
106 result[column] = inf_add(result[column], inf_multiply(left[index], right[column][index]));
107 return result;
108 }
109
110 template <typename T>
111 inline T mix(const T& aLhs, const T& aRhs, double aMixValue)
112 {
113 if constexpr (std::is_scalar_v<T>)
114 return static_cast<T>(static_cast<double>(aLhs) * (1.0 - aMixValue) + static_cast<double>(aRhs) * aMixValue);
115 else
116 return aLhs;
117 }
118
119 template <typename T1, typename T2>
120 inline T1 mix(const T1& aLhs, const T2&, double)
121 {
122 return aLhs;
123 }
124
125 template <typename T>
126 inline T mix(const std::optional<T>& aLhs, const std::optional<T>& aRhs, double aMixValue)
127 {
128 if (!aLhs.has_value() && !aRhs.has_value())
129 return T{};
130 else if (aLhs.has_value() && !aRhs.has_value())
131 return *aLhs;
132 else if (!aLhs.has_value() && aRhs.has_value())
133 return *aRhs;
134 else
135 return mix(*aLhs, *aRhs, aMixValue);
136 }
137}
T inf_add(T lhs, T rhs)
Definition numerical.hpp:52
T inf_multiply(T lhs, T rhs)
Definition numerical.hpp:72
point mix(const point &aLhs, const point &aRhs, double aMixValue)
bool nearly_equal(T lhs, T rhs, scalar epsilon=0.00001, std::enable_if_t< std::is_floating_point_v< T >, sfinae >={})