MathLib
Loading...
Searching...
No Matches
Dual.hpp
Go to the documentation of this file.
1#pragma once
2
4#include <cassert>
5#include <concepts>
6#include <type_traits>
7
8
17namespace Math
18{
19
24template<class T>
26{
27public:
31 using value_type = T;
33
37 constexpr BasicDual() = default;
38
46 constexpr BasicDual(const T &r) : real(r) { }
47
48 constexpr BasicDual(const T &r, const T &d) : real(r), dual(d) { }
50
54 constexpr static BasicDual<T> identity() { return { T{1}, T{0} }; }
55 constexpr static BasicDual<T> zero() { return { }; }
57
58 constexpr BasicDual<T> conjugate() const
59 {
60 if constexpr (std::is_floating_point_v<T>)
61 return { real, -dual };
62 else
63 return { real, conjugate(dual) };
64 }
65
66 constexpr T magnitude() const { return real; }
67
80 constexpr static BasicDual<T> make_pure(const T &input)
81 {
82 return { T{}, input };
83 }
85
89 bool isNaN() const
90 {
91 if constexpr ( std::is_floating_point_v<T> )
92 return std::isnan(real) || std::isnan(dual);
93 else
94 return real.isNaN() || dual.isNaN();
95 }
96
97 bool isInf() const
98 {
99 if constexpr ( std::is_floating_point_v<T> )
100 return std::isinf(real) || std::isinf(dual);
101 else
102 return real.isInf() || dual.isInf();
103 }
105
109 T real{};
110 T dual{};
112
113private:
114
129 friend constexpr bool operator ==(const BasicDual<T> &left, const BasicDual<T> &right)
130 {
131 return approximately_equal_to(left, right);
132 }
133
144 template <std::floating_point OT = T>
145 requires std::is_floating_point_v<T>
146 friend constexpr bool approximately_equal_to(const BasicDual<T> &value_to_test,
147 const BasicDual<T> &value_it_should_be,
148 OT tolerance = OT{0.0002})
149 {
150 return approximately_equal_to(value_to_test.real, value_it_should_be.real, tolerance) &&
151 approximately_equal_to(value_to_test.dual, value_it_should_be.dual, tolerance);
152 }
154
167 friend constexpr BasicDual<T> operator *(const BasicDual<T> &left, const BasicDual<T> &right)
168 {
169 return { left.real * right.real,
170 left.real * right.dual + right.real * left.dual };
171 }
172
180 template <std::floating_point OT = double>
181 friend constexpr BasicDual<T> operator *(OT scalar, const BasicDual<T> &d)
182 {
183 return BasicDual<T>( T(scalar) ) * d;
184 }
185
193 template <std::floating_point OT = double>
194 friend constexpr BasicDual<T> operator *(const BasicDual<T> &d, OT scalar)
195 {
196 return d * BasicDual<T>( T(scalar) );
197 }
198
200 friend constexpr BasicDual<T> operator /(const BasicDual<T> &left, const BasicDual<T> &right)
201 {
202 return { left.real * right.real / (right.real * right.real),
203 (left.dual * right.real - left.real * right.dual) / (right.real * right.real) };
204 }
205
214 template <std::floating_point OT = double>
215 friend constexpr BasicDual<T> operator /(OT scalar, const BasicDual<T> &d)
216 {
217 return BasicDual<T>( T(scalar) ) / d;
218 }
219
228 template <std::floating_point OT = double>
229 friend constexpr BasicDual<T> operator /(const BasicDual<T> &left, OT scalar)
230 {
231 return left / BasicDual<T>( T(scalar) );
232 }
233
235 friend constexpr BasicDual<T> operator +(const BasicDual<T> &left, const BasicDual<T> &right)
236 {
237 return { left.real + right.real, left.dual + right.dual };
238 }
239
241 template <std::floating_point OT = double>
242 friend constexpr BasicDual<T> operator +(OT scalar, const BasicDual<T> &d)
243 {
244 return BasicDual<T>( T(scalar) ) + d;
245 }
246
248 template <std::floating_point OT = double>
249 friend constexpr BasicDual<T> operator +(const BasicDual<T> &left, OT scalar)
250 {
251 return left + BasicDual<T>( T(scalar) );
252 }
253
255 friend constexpr BasicDual<T> operator -(const BasicDual<T> &left, const BasicDual<T> &right)
256 {
257 return { left.real - right.real, left.dual - right.dual };
258 }
259
261 template <std::floating_point OT = double>
262 friend constexpr BasicDual<T> operator -(OT scalar, const BasicDual<T> &d)
263 {
264 return BasicDual<T>( T(scalar) ) - d;
265 }
266
268 template <std::floating_point OT = double>
269 friend constexpr BasicDual<T> operator -(const BasicDual<T> &left, OT scalar)
270 {
271 return left - BasicDual<T>( T(scalar) );
272 }
275
293 template <std::floating_point OT = T>
294 requires std::is_floating_point_v<T>
295 friend bool check_if_equal(const BasicDual<T> &input,
296 const BasicDual<T> &near_to,
297 OT tolerance = OT{0.0002})
298 {
299 if (!approximately_equal_to(input, near_to, tolerance))
300 {
301 auto diff{ near_to - input };
302
303 std::cout << std::format("input: {} is not equal to near_to: {} within tolerance: {}. Difference is {} .",
304 format(input),
305 format(near_to),
306 tolerance,
307 format(near_to - input))
308 << std::endl;
309 return false;
310 }
311 return true;
312 }
313
322 template <std::floating_point OT = T>
323 requires std::is_floating_point_v<T>
324 friend bool check_if_not_equal(const BasicDual<T> &input,
325 const BasicDual<T> &near_to,
326 OT tolerance = OT{0.0002})
327 {
328 if (approximately_equal_to(input, near_to, tolerance))
329 {
330 auto diff{ near_to - input };
331
332 std::cout << std::format("input: {} is equal to near_to: {} within tolerance: {}. Difference is {} .",
333 format(input),
334 format(near_to),
335 tolerance,
336 format(near_to - input))
337 << std::endl;
338 return false;
339 }
340 return true;
341 }
344
362 template <std::floating_point OT = T>
363 requires std::is_floating_point_v<T>
364 friend void CHECK_IF_EQUAL(const BasicDual<T> &input,
365 const BasicDual<T> &near_to,
366 OT tolerance = OT{0.0002})
367 {
368 assert( check_if_equal(input, near_to, tolerance) );
369 }
370
379 template <std::floating_point OT = T>
380 requires std::is_floating_point_v<T>
381 friend void CHECK_IF_NOT_EQUAL(const BasicDual<T> &input,
382 const BasicDual<T> &near_to,
383 OT tolerance = OT{0.0002})
384 {
385 assert( check_if_not_equal(input, near_to, tolerance) );
386 }
387
395 template <std::floating_point OT = T>
396 requires std::is_floating_point_v<T>
397 friend void CHECK_IF_ZERO(const BasicDual<T> &input, OT tolerance = OT{0.0002})
398 {
399 assert( check_if_equal(input, BasicDual<T>::zero(), tolerance));
400 }
403
418 friend constexpr T dot(const BasicDual<T> &left, const BasicDual<T> &right)
419 {
420 return left.real * right.real +
421 left.dual * right.dual;
422 }
423
431 friend constexpr BasicDual<T> dualscalar_sqrt(const BasicDual<T> &input)
432 {
433 // Expect that T is a scalar type (float, double, int, etc.)
434 T root = std::sqrt(input.real);
435
436 return { root, input.dual / (T{2} * root) };
437 }
438
441 friend constexpr T dualscalar_normsquared(const BasicDual<T> &d)
442 {
443 BasicDual<T> result = d * d.conjugate();
444
445 assert( approximately_equal_to(result.dual, T{0}) );
446
447 return result.real;
448 }
449
454 friend constexpr T accumulate(const BasicDual<T> &input)
455 {
456 return T{input.real + input.dual};
457 }
458
463 friend constexpr BasicDual<T> conjugate(const BasicDual<T> &input)
464 {
465 return input.conjugate();
466 }
467
468 friend std::string format(const BasicDual<T> &input)
469 {
470 return std::format("[real: {}, dual: {}]", input.real, input.dual);
471 }
473};
474
475
494
495}
constexpr BasicDual()=default
Defaults to (0,0)
constexpr T magnitude() const
Definition Dual.hpp:66
bool isNaN() const
Definition Dual.hpp:89
friend constexpr T dualscalar_normsquared(const BasicDual< T > &d)
Definition Dual.hpp:441
static constexpr BasicDual< T > zero()
Definition Dual.hpp:55
friend constexpr BasicDual< T > conjugate(const BasicDual< T > &input)
Definition Dual.hpp:463
static constexpr BasicDual< T > identity()
Definition Dual.hpp:54
friend constexpr bool approximately_equal_to(const BasicDual< T > &value_to_test, const BasicDual< T > &value_it_should_be, OT tolerance=OT{0.0002})
Definition Dual.hpp:146
constexpr BasicDual(const T &r, const T &d)
Definition Dual.hpp:48
friend std::string format(const BasicDual< T > &input)
Definition Dual.hpp:468
static constexpr BasicDual< T > make_pure(const T &input)
Definition Dual.hpp:80
friend constexpr bool operator==(const BasicDual< T > &left, const BasicDual< T > &right)
Definition Dual.hpp:129
friend constexpr BasicDual< T > dualscalar_sqrt(const BasicDual< T > &input)
Definition Dual.hpp:431
friend constexpr T dot(const BasicDual< T > &left, const BasicDual< T > &right)
Definition Dual.hpp:418
constexpr BasicDual< T > conjugate() const
Definition Dual.hpp:58
constexpr BasicDual(const T &r)
Definition Dual.hpp:46
friend constexpr T accumulate(const BasicDual< T > &input)
Definition Dual.hpp:454
T value_type
The underlying implementation type.
Definition Dual.hpp:31
bool isInf() const
Definition Dual.hpp:97
friend void CHECK_IF_ZERO(const BasicDual< T > &input, OT tolerance=OT{0.0002})
Definition Dual.hpp:397
friend void CHECK_IF_NOT_EQUAL(const BasicDual< T > &input, const BasicDual< T > &near_to, OT tolerance=OT{0.0002})
Definition Dual.hpp:381
friend void CHECK_IF_EQUAL(const BasicDual< T > &input, const BasicDual< T > &near_to, OT tolerance=OT{0.0002})
Definition Dual.hpp:364
friend bool check_if_equal(const BasicDual< T > &input, const BasicDual< T > &near_to, OT tolerance=OT{0.0002})
Definition Dual.hpp:295
friend bool check_if_not_equal(const BasicDual< T > &input, const BasicDual< T > &near_to, OT tolerance=OT{0.0002})
Definition Dual.hpp:324
friend constexpr BasicDual< T > operator+(const BasicDual< T > &left, const BasicDual< T > &right)
Defines addition of two Duals.
Definition Dual.hpp:235
friend constexpr BasicDual< T > operator/(const BasicDual< T > &left, const BasicDual< T > &right)
Defines division of two Duals.
Definition Dual.hpp:200
friend constexpr BasicDual< T > operator*(const BasicDual< T > &left, const BasicDual< T > &right)
Defines multiplication of two Duals.
Definition Dual.hpp:167
friend constexpr BasicDual< T > operator-(const BasicDual< T > &left, const BasicDual< T > &right)
Defines subtraction of two Duals.
Definition Dual.hpp:255
Definition Angle.hpp:16