From 93f414794166703088773bc39f1171ecd3601e6d Mon Sep 17 00:00:00 2001 From: lisyarus Date: Wed, 1 Dec 2021 21:23:13 +0300 Subject: [PATCH] Add n-dimensional dual numbers implementation --- libs/geom/include/psemek/geom/dual.hpp | 160 +++++++++++++++++++++++++ 1 file changed, 160 insertions(+) create mode 100644 libs/geom/include/psemek/geom/dual.hpp diff --git a/libs/geom/include/psemek/geom/dual.hpp b/libs/geom/include/psemek/geom/dual.hpp new file mode 100644 index 00000000..d1b190aa --- /dev/null +++ b/libs/geom/include/psemek/geom/dual.hpp @@ -0,0 +1,160 @@ +#pragma once + +#include + +#include + +namespace psemek::geom +{ + + template + struct dual + { + T scalar = T{0}; + vector delta = vector::zero(); + + dual() = default; + + dual(T scalar) + : scalar{std::move(scalar)} + {} + + dual(T scalar, vector delta) + : scalar{std::move(scalar)} + , delta{std::move(delta)} + {} + + dual & operator += (dual const & d); + dual & operator -= (dual const & d); + dual & operator *= (dual const & d); + dual & operator /= (dual const & d); + }; + + template + dual operator + (dual const & d) + { + return d; + } + + template + dual operator - (dual const & d) + { + return {-d.scalar, -d.delta}; + } + + template + dual operator + (dual const & d1, dual const & d2) + { + return {d1.scalar + d2.scalar, d1.delta + d2.delta}; + } + + template + dual operator - (dual const & d1, dual const & d2) + { + return {d1.scalar - d2.scalar, d1.delta - d2.delta}; + } + + template + dual operator * (dual const & d1, dual const & d2) + { + return {d1.scalar * d2.scalar, d1.scalar * d2.delta + d2.scalar * d1.delta}; + } + + template + dual inverse(dual const & d) + { + return {T{1} / d.scalar, - d.delta / d.scalar / d.scalar}; + } + + template + dual operator / (dual const & d1, dual const & d2) + { + return d1 * inverse(d2); + } + + template + dual & dual::operator += (dual const & d) + { + *this = *this + d; + return *this; + } + + template + dual & dual::operator -= (dual const & d) + { + *this = *this - d; + return *this; + } + + template + dual & dual::operator *= (dual const & d) + { + *this = *this * d; + return *this; + } + + template + dual & dual::operator /= (dual const & d) + { + *this = *this / d; + return *this; + } + + template + dual operator + (dual const & d, T const & v) + { + return {d.scalar + v, d.delta}; + } + + template + dual operator + (T const & v, dual const & d) + { + return {d.scalar + v, d.delta}; + } + + template + dual operator - (dual const & d, T const & v) + { + return {d.scalar - v, d.delta}; + } + + template + dual operator - (T const & v, dual const & d) + { + return {v - d.scalar, -d.delta}; + } + + template + dual operator * (dual const & d, T const & v) + { + return {d.scalar * v, d.delta * v}; + } + + template + dual operator * (T const & v, dual const & d) + { + return {d.scalar * v, d.delta * v}; + } + + template + dual operator / (dual const & d, T const & v) + { + return {d.scalar / v, d.delta / v}; + } + + template + dual operator / (T const & v, dual const & d) + { + return v * inverse(d); + } + + template + std::ostream & operator << (std::ostream & os, dual const & d) + { + os << d.scalar; + for (std::size_t i = 0; i < N; ++i) + os << " + " << d.delta[i] << " e_" << i; + return os; + } + +}