numerical-collection-cpp 0.10.0
A collection of algorithms in numerical analysis implemented in C++
Loading...
Searching...
No Matches
variable.h
Go to the documentation of this file.
1/*
2 * Copyright 2021 MusicScience37 (Kenta Kabashima)
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
20#pragma once
21
22#include <optional>
23#include <utility>
24
25#include <Eigen/Core>
26
31
33
42template <base::concepts::real_scalar Value, typename Diff = Value>
43class variable {
44public:
46 using value_type = Value;
47
49 using diff_type = Diff;
50
57 template <typename DiffArg>
58 variable(const value_type& value, DiffArg&& diff)
59 : value_(value), diff_(std::forward<DiffArg>(diff)) {}
60
66 variable(const value_type& value) // NOLINT: implicit conversion required
67 : value_(value) {}
68
72 variable() : variable(static_cast<value_type>(0)) {}
73
79 [[nodiscard]] auto value() const noexcept -> const value_type& {
80 return value_;
81 }
82
88 [[nodiscard]] auto has_diff() const noexcept -> bool {
89 return diff_.has_value();
90 }
91
97 [[nodiscard]] auto diff() const -> const diff_type& {
99 "diff function called for a variable without differential "
100 "coefficients.");
101 return *diff_;
102 }
103
109 auto operator-() const -> variable {
110 if (diff_) {
111 return variable(-value_, -*diff_);
112 }
113 return variable(-value_);
114 }
115
122 auto operator+=(const variable& right) -> variable& {
123 value_ += right.value_;
124 if (right.diff_) {
125 if (diff_) {
126 *diff_ += *right.diff_;
127 } else {
128 diff_ = *right.diff_;
129 }
130 }
131 return *this;
132 }
133
140 auto operator-=(const variable& right) -> variable& {
141 value_ -= right.value_;
142 if (right.diff_) {
143 if (diff_) {
144 *diff_ -= *right.diff_;
145 } else {
146 diff_ = -*right.diff_;
147 }
148 }
149 return *this;
150 }
151
158 auto operator*=(const variable& right) -> variable& {
159 if (right.diff_) {
160 if (diff_) {
161 *diff_ *= right.value_;
162 *diff_ += value_ * (*right.diff_);
163 } else {
164 diff_ = value_ * (*right.diff_);
165 }
166 } else {
167 if (diff_) {
168 *diff_ *= right.value_;
169 }
170 }
171 value_ *= right.value_;
172 return *this;
173 }
174
181 auto operator/=(const variable& right) -> variable& {
182 value_ /= right.value_;
183 if (right.diff_) {
184 if (diff_) {
185 *diff_ = ((*diff_) - (*right.diff_) * value_) / right.value_;
186 } else {
187 diff_ = -(*right.diff_) * value_ / right.value_;
188 }
189 } else {
190 if (diff_) {
191 *diff_ = (*diff_) / right.value_;
192 }
193 }
194 return *this;
195 }
196
197private:
200
202 std::optional<diff_type> diff_{};
203};
204
214template <typename Value, typename Diff>
215[[nodiscard]] inline auto operator+(const variable<Value, Diff>& left,
217 return variable<Value, Diff>(left) += right;
218}
219
229template <typename Value, typename Diff>
230[[nodiscard]] inline auto operator+(const Value& left,
232 return variable<Value, Diff>(left) += right;
233}
234
244template <typename Value, typename Diff>
245[[nodiscard]] inline auto operator+(const variable<Value, Diff>& left,
246 const Value& right) -> variable<Value, Diff> {
247 return variable<Value, Diff>(left) += right;
248}
249
259template <typename Value, typename Diff>
260[[nodiscard]] inline auto operator-(const variable<Value, Diff>& left,
262 return variable<Value, Diff>(left) -= right;
263}
264
274template <typename Value, typename Diff>
275[[nodiscard]] inline auto operator-(const Value& left,
277 return variable<Value, Diff>(left) -= right;
278}
279
289template <typename Value, typename Diff>
290[[nodiscard]] inline auto operator-(const variable<Value, Diff>& left,
291 const Value& right) -> variable<Value, Diff> {
292 return variable<Value, Diff>(left) -= right;
293}
294
304template <typename Value, typename Diff>
305[[nodiscard]] inline auto operator*(const variable<Value, Diff>& left,
307 return variable<Value, Diff>(left) *= right;
308}
309
319template <typename Value, typename Diff>
320[[nodiscard]] inline auto operator*(const Value& left,
322 return variable<Value, Diff>(left) *= right;
323}
324
334template <typename Value, typename Diff>
335[[nodiscard]] inline auto operator*(const variable<Value, Diff>& left,
336 const Value& right) -> variable<Value, Diff> {
337 return variable<Value, Diff>(left) *= right;
338}
339
349template <typename Value, typename Diff>
350[[nodiscard]] inline auto operator/(const variable<Value, Diff>& left,
352 return variable<Value, Diff>(left) /= right;
353}
354
364template <typename Value, typename Diff>
365[[nodiscard]] inline auto operator/(const Value& left,
367 return variable<Value, Diff>(left) /= right;
368}
369
379template <typename Value, typename Diff>
380[[nodiscard]] inline auto operator/(const variable<Value, Diff>& left,
381 const Value& right) -> variable<Value, Diff> {
382 return variable<Value, Diff>(left) /= right;
383}
384
385} // namespace num_collect::auto_diff::forward
386
387namespace Eigen {
388
400template <typename Value, typename Diff>
401struct NumTraits<num_collect::auto_diff::forward::variable<Value, Diff>> {
404
407
409 using Literal = Real;
410
412 using Nested = Real;
413
414 enum { // NOLINT(performance-enum-size): Preserve the same implementation as Eigen library.
416 IsInteger = 0, // NOLINT
417
419 IsSigned = 1, // NOLINT
420
422 IsComplex = 0, // NOLINT
423
425 RequireInitialization = 1, // NOLINT
426
428 ReadCost = 1, // NOLINT
429
431 AddCost = 2, // NOLINT
432
434 MulCost = 4 // NOLINT
435 };
436
442 static constexpr auto epsilon() -> Real {
443 return NumTraits<Value>::epsilon();
444 }
445
451 static constexpr auto dummy_precision() -> Real {
452 return NumTraits<Value>::dummy_precision();
453 }
454
460 static constexpr auto highest() -> Real {
461 return NumTraits<Value>::highest();
462 }
463
469 static constexpr auto lowest() -> Real {
470 return NumTraits<Value>::lowest();
471 }
472
478 static constexpr auto digits10() -> int {
479 return NumTraits<Value>::digits10();
480 }
481
487 static constexpr auto infinity() -> Real {
488 return NumTraits<Value>::infinity();
489 }
490
496 static constexpr auto quiet_NaN() -> Real { // NOLINT
497 return NumTraits<Value>::quiet_NaN();
498 }
499};
500
501} // namespace Eigen
Class of variables in forward-mode automatic differentiation kubota1998.
Definition variable.h:43
auto operator+=(const variable &right) -> variable &
Add a variable.
Definition variable.h:122
auto operator/=(const variable &right) -> variable &
Divide by a variable.
Definition variable.h:181
std::optional< diff_type > diff_
Differential coefficients.
Definition variable.h:202
auto value() const noexcept -> const value_type &
Get the value.
Definition variable.h:79
auto operator*=(const variable &right) -> variable &
Multiply a variable.
Definition variable.h:158
variable(const value_type &value)
Constructor.
Definition variable.h:66
Diff diff_type
Type of differential coefficients.
Definition variable.h:49
auto operator-() const -> variable
Negate this variable.
Definition variable.h:109
variable(const value_type &value, DiffArg &&diff)
Constructor.
Definition variable.h:58
auto operator-=(const variable &right) -> variable &
Subtract a variable.
Definition variable.h:140
auto diff() const -> const diff_type &
Get the differential coefficients.
Definition variable.h:97
auto has_diff() const noexcept -> bool
Get whether this variable has differential coefficients.
Definition variable.h:88
Definition of exceptions.
Definition of macros for logging.
Namespace of Eigen library.
Definition variable.h:416
Namespace of forward-mode automatic differentiation.
auto operator/(const variable< Value, Diff > &left, const variable< Value, Diff > &right) -> variable< Value, Diff >
Divide a variable by another variable.
Definition variable.h:350
auto operator*(const variable< Value, Diff > &left, const variable< Value, Diff > &right) -> variable< Value, Diff >
Multiply two variables.
Definition variable.h:305
auto operator-(const variable< Value, Diff > &left, const variable< Value, Diff > &right) -> variable< Value, Diff >
Subtract a variable from another variable.
Definition variable.h:260
auto operator+(const variable< Value, Diff > &left, const variable< Value, Diff > &right) -> variable< Value, Diff >
Add two variables.
Definition variable.h:215
Namespace of num_collect source codes.
STL namespace.
Definition of NUM_COLLECT_PRECONDITION macro.
#define NUM_COLLECT_PRECONDITION(CONDITION,...)
Check whether a precondition is satisfied and throw an exception if not.
Definition of real_scalar concept.
static constexpr auto epsilon() -> Real
Get machine epsilon.
Definition variable.h:442
static constexpr auto dummy_precision() -> Real
Get dummy precision.
Definition variable.h:451
static constexpr auto infinity() -> Real
Get the infinity.
Definition variable.h:487
static constexpr auto lowest() -> Real
Get the lowest value.
Definition variable.h:469
static constexpr auto digits10() -> int
Get the number of digits.
Definition variable.h:478
static constexpr auto quiet_NaN() -> Real
Get the quiet NaN value.
Definition variable.h:496
static constexpr auto highest() -> Real
Get the highest value.
Definition variable.h:460