File size: 3,744 Bytes
985c397
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
// SPDX-License-Identifier: LGPL-2.1-or-later

/***************************************************************************
 *   Copyright (c) 2019 Viktor Titov (DeepSOIC) <vv.titov@gmail.com>       *
 *                                                                         *
 *   This file is part of the FreeCAD CAx development system.              *
 *                                                                         *
 *   This library is free software; you can redistribute it and/or         *
 *   modify it under the terms of the GNU Library General Public           *
 *   License as published by the Free Software Foundation; either          *
 *   version 2 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         *
 *   GNU Library General Public License for more details.                  *
 *                                                                         *
 *   You should have received a copy of the GNU Library General Public     *
 *   License along with this library; see the file COPYING.LIB. If not,    *
 *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
 *   Suite 330, Boston, MA  02111-1307, USA                                *
 *                                                                         *
 ***************************************************************************/

#ifndef FREECAD_BASE_DUAL_NUMBER_H
#define FREECAD_BASE_DUAL_NUMBER_H

#include <cmath>

// NOLINTBEGIN(readability-identifier-length)
namespace Base
{


/**
 * @brief Dual Numbers are 2-part numbers like complex numbers, but different
 * algebra. They are denoted as a + b*eps, where eps^2 = 0. eps, the nilpotent,
 * is like imaginary unit of complex numbers. The neat utility of dual numbers
 * is that if you use them instead of normal numbers in a function like sin(),
 * derivative is implicitly calculated as a multiplier to the dual part.
 */
class DualNumber
{
public:
    double re = 0.0;
    double du = 0.0;

public:
    DualNumber() = default;
    DualNumber(double re, double du = 0.0)  // NOLINT
        : re(re)
        , du(du)
    {}
    DualNumber operator-() const
    {
        return {-re, -du};
    }
};

inline DualNumber operator+(DualNumber a, DualNumber b)
{
    return {a.re + b.re, a.du + b.du};
}
inline DualNumber operator+(DualNumber a, double b)
{
    return {a.re + b, a.du};
}
inline DualNumber operator+(double a, DualNumber b)
{
    return {a + b.re, b.du};
}

inline DualNumber operator-(DualNumber a, DualNumber b)
{
    return {a.re - b.re, a.du - b.du};
}
inline DualNumber operator-(DualNumber a, double b)
{
    return {a.re - b, a.du};
}
inline DualNumber operator-(double a, DualNumber b)
{
    return {a - b.re, -b.du};
}

inline DualNumber operator*(DualNumber a, DualNumber b)
{
    return {a.re * b.re, a.re * b.du + a.du * b.re};
}
inline DualNumber operator*(double a, DualNumber b)
{
    return {a * b.re, a * b.du};
}
inline DualNumber operator*(DualNumber a, double b)
{
    return {a.re * b, a.du * b};
}

inline DualNumber operator/(DualNumber a, DualNumber b)
{
    return {a.re / b.re, (a.du * b.re - a.re * b.du) / (b.re * b.re)};
}
inline DualNumber operator/(DualNumber a, double b)
{
    return {a.re / b, a.du / b};
}

inline DualNumber pow(DualNumber a, double pw)
{
    return {std::pow(a.re, pw), pw * std::pow(a.re, pw - 1.0) * a.du};
}
}  // namespace Base
// NOLINTEND(readability-identifier-length)


#endif