deal.II version GIT relicensing-6839-g338455934c 2026-10-02 12:10:01+00:00
\(\newcommand{\dealvcentcolon}{\mathrel{\mathop{:}}}\) \(\newcommand{\dealcoloneq}{\dealvcentcolon\mathrel{\mkern-1.2mu}=}\) \(\newcommand{\jump}[1]{\left[\!\left[ #1 \right]\!\right]}\) \(\newcommand{\average}[1]{\left\{\!\left\{ #1 \right\}\!\right\}}\)
Loading...
Searching...
No Matches
symengine_number_types.cc
Go to the documentation of this file.
1// -----------------------------------------------------------------------------
2//
3// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception OR LGPL-2.1-or-later
4// Copyright (C) 2019 - 2026 by the deal.II authors
5//
6// This file is part of the deal.II library.
7//
8// Detailed license information governing the source code and contributions
9// can be found in LICENSE.md and CONTRIBUTING.md at the top level directory.
10//
11// -----------------------------------------------------------------------------
12
13#include <deal.II/base/config.h>
14
15#ifdef DEAL_II_WITH_SYMENGINE
16
18
22
23# include <symengine/complex_double.h>
24# include <symengine/logic.h>
25# include <symengine/number.h>
26# include <symengine/parser.h>
27# include <symengine/real_double.h>
28# include <symengine/symbol.h>
29# include <symengine/symengine_exception.h>
30
31# include <string>
32
33
34#endif // DEAL_II_WITH_SYMENGINE
35
37
38#ifdef DEAL_II_WITH_SYMENGINE
39
40namespace Differentiation
41{
42 namespace SD
43 {
44 namespace SE = ::SymEngine;
45
46
47 /* ---------------------------- Constructors -------------------------- */
48
49
51 : expression()
52 {}
53
54
55 Expression::Expression(const bool value)
56 : expression(SE::boolean(value))
57 {}
58
59
60 Expression::Expression(const SymEngine::integer_class &value)
61 : expression(value)
62 {}
63
64
65 Expression::Expression(const SymEngine::rational_class &value)
66 : expression(value)
67 {}
68
69
71 const Expression &expression_if_true,
72 const Expression &expression_if_false)
73 {
74 Assert(SE::is_a_Boolean(condition.get_value()),
76 "The conditional expression must return a boolean type."));
77
78 const SE::RCP<const SE::Boolean> condition_rcp =
79 SE::rcp_static_cast<const SE::Boolean>(condition.get_RCP());
81 SE::piecewise({{expression_if_true.get_RCP(), condition_rcp},
82 {expression_if_false.get_RCP(), SE::boolTrue}});
83 }
84
85
86 Expression::Expression(const std::vector<std::pair<Expression, Expression>>
87 &condition_expression,
88 const Expression &expression_otherwise)
89 {
90 SE::PiecewiseVec piecewise_function;
91 piecewise_function.reserve(condition_expression.size() + 1);
92
93 // Add tested conditional entries
94 for (const auto &entry : condition_expression)
95 {
96 Assert(SE::is_a_Boolean(entry.first.get_value()),
98 "The conditional expression must return a boolean type."));
99 piecewise_function.emplace_back(
100 entry.second.get_RCP(),
101 SE::rcp_static_cast<const SE::Boolean>(entry.first.get_RCP()));
102 }
103
104 // Add default value
105 piecewise_function.emplace_back(expression_otherwise.get_RCP(),
106 SE::boolTrue);
107
108 // Initialize. Note that we need to use a std::move() here for
109 // compatibility with older compilers.
110 expression = SE::piecewise(std::move(piecewise_function)); // NOLINT
111 }
112
113
114 Expression::Expression(const std::vector<std::pair<Expression, Expression>>
115 &condition_expression)
116 {
117 // Use the other constructor with a fatal termination point
118 // ensuring that an error is thrown if none of the conditions
119 // are met.
120 *this = Expression(condition_expression,
121 Expression(numbers::signaling_nan<double>()));
122 }
123
124
125 Expression::Expression(const char *symbol)
126 : expression(SE::symbol(symbol))
127 {}
128
129
130 Expression::Expression(const std::string &str,
131 const bool parse_as_expression)
132 {
133 try
134 {
135 expression = (parse_as_expression ?
136 SE::parse(str) // The string is a symbolic "name"
137 :
138 SE::rcp_static_cast<const SE::Basic>(SE::symbol(
139 str))); // The string is a symbolic "expression"
140 }
141 catch (...)
142 {
144 }
145 }
146
147
148 Expression::Expression(const std::string &symbol_func,
149 const types::symbol_vector &arguments)
150 : expression(SE::function_symbol(
151 symbol_func,
152 Utilities::convert_expression_vector_to_basic_vector(arguments)))
153 {}
154
155
156 Expression::Expression(const SymEngine::Expression &rhs)
157 : expression(rhs)
158 {}
159
160
161 Expression::Expression(const SymEngine::RCP<const SymEngine::Basic> &rhs)
162 : expression(rhs)
163 {}
164
165
166 Expression::Expression(SymEngine::RCP<const SymEngine::Basic> &&rhs)
167 : expression(rhs)
168 {}
169
170
171 /* ------------------------------ Utilities ---------------------------- */
172
173
174 Expression &
175 Expression::parse(const std::string &expression)
176 {
177 *this = Expression(expression, true /*parse_as_expression*/);
178 return *this;
179 }
180
181
182 std::ostream &
183 Expression::print(std::ostream &os) const
184 {
185 os << *this;
186 return os;
187 }
188
189
190 void
191 Expression::save(std::ostream &os) const
192 {
193 // We write each expression on a new line.
194 // Note: SymEngine outputs a non-terminating string
195 os << *this;
196 os << std::endl;
197 }
198
199
200 void
201 Expression::load(std::istream &is)
202 {
203 // Need to make sure that we read the entire line in,
204 // and then subsequently parse it.
205 std::string expr;
206 std::getline(is, expr);
207 Assert(!is.bad(), ExcIO());
208 parse(expr);
209 }
210
211
212 /* ------------------------------- Values ----------------------------- */
213
214
215 const SE::Expression &
217 {
218 return expression;
219 }
220
221
222 SE::Expression &
224 {
225 return expression;
226 }
227
228
229 const SE::Basic &
231 {
232 return *get_RCP();
233 }
234
235
236 const SE::RCP<const SE::Basic> &
238 {
239 return get_expression().get_basic();
240 }
241
242
243 /* --------------------------- Differentiation ------------------------- */
244
245
248 const SymEngine::RCP<const SymEngine::Symbol> &symbol) const
249 {
250 return Expression(SE::diff(get_RCP(), symbol));
251 }
252
253
256 const SymEngine::RCP<const SymEngine::Basic> &symbol) const
257 {
258 // Potential symbol
259 return Expression(SE::sdiff(get_RCP(), symbol));
260 }
261
262
265 {
266 return differentiate(symbol.get_RCP());
267 }
268
269
270 /* ------------- Conversion operators ------------------------- */
271
272
273 Expression::operator const SymEngine::Expression &() const
274 {
275 return get_expression();
276 }
277
278
279 Expression::operator const SymEngine::RCP<const SymEngine::Basic> &() const
280 {
281 return get_expression().get_basic();
282 }
283
284
285 /* ------------- Dictionary-based substitution ------------------------- */
286
287
288 Expression
290 const SymEngine::map_basic_basic &substitution_values) const
291 {
292 return Expression(get_expression().subs(substitution_values));
293 }
294
295
298 const types::substitution_map &substitution_values) const
299 {
300 return substitute(
302 }
303
304
307 const Expression &value) const
308 {
309 Assert(SE::is_a<SE::Symbol>(symbol.get_value()),
311 "Substitution with a number that does not represent a symbol."));
312
314 sub_vals[symbol] = value;
315 return substitute(sub_vals);
316 }
317
318
319 /* -------------------- Math and relational operators ------------------ */
320
321
322 Expression &
324 {
325 if (this != &rhs)
326 this->expression = rhs.get_expression();
327
328 return *this;
329 }
330
331
332 Expression &
334 {
335 if (this != &rhs)
336 this->expression = std::move(rhs.expression);
337
338 return *this;
339 }
340
341
344 {
345 return Expression(-get_expression());
346 }
347
348
349 Expression &
351 {
352 this->expression += rhs.get_expression();
353 return *this;
354 }
355
356
357 Expression &
359 {
360 this->expression -= rhs.get_expression();
361 return *this;
362 }
363
364
365 Expression &
367 {
368 this->expression *= rhs.get_expression();
369 return *this;
370 }
371
372
373 Expression &
375 {
376 this->expression /= rhs.get_expression();
377 return *this;
378 }
379
380
381 std::ostream &
382 operator<<(std::ostream &stream, const Expression &expr)
383 {
384 stream << expr.get_expression();
385 return stream;
386 }
387
388
389 std::istream &
390 operator>>(std::istream &stream, Expression &expr)
391 {
392 std::string str;
393 stream >> str;
394 expr.parse(str);
395 return stream;
396 }
397
398
399 Expression
400 operator==(const Expression &lhs, const Expression &rhs)
401 {
402 return Expression(SE::Eq(lhs.get_RCP(), rhs.get_RCP()));
403 }
404
405
406 Expression
407 operator!=(const Expression &lhs, const Expression &rhs)
408 {
409 return Expression(SE::Ne(lhs.get_RCP(), rhs.get_RCP()));
410 }
411
412
414 operator<(const Expression &lhs, const Expression &rhs)
415 {
416 return Expression(SE::Lt(lhs.get_RCP(), rhs.get_RCP()));
417 }
418
419
420 Expression
421 operator>(const Expression &lhs, const Expression &rhs)
422 {
423 return Expression(SE::Gt(lhs.get_RCP(), rhs.get_RCP()));
424 }
425
426
428 operator<=(const Expression &lhs, const Expression &rhs)
429 {
430 return Expression(SE::Le(lhs.get_RCP(), rhs.get_RCP()));
431 }
432
433
434 Expression
435 operator>=(const Expression &lhs, const Expression &rhs)
436 {
437 return Expression(SE::Ge(lhs.get_RCP(), rhs.get_RCP()));
438 }
439
440
441 Expression
442 operator!(const Expression &expression)
443 {
444 Assert(SE::is_a_Boolean(expression.get_value()),
445 ExcMessage("The expression must return a boolean type."));
446
447 const SE::RCP<const SE::Boolean> expression_rcp =
448 SE::rcp_static_cast<const SE::Boolean>(expression.get_RCP());
449
450 return Expression(SE::logical_not(expression_rcp));
451 }
452
453
454 Expression
455 operator&(const Expression &lhs, const Expression &rhs)
456 {
457 Assert(SE::is_a_Boolean(lhs.get_value()),
458 ExcMessage("The lhs expression must return a boolean type."));
459 Assert(SE::is_a_Boolean(rhs.get_value()),
460 ExcMessage("The rhs expression must return a boolean type."));
461
462 const SE::RCP<const SE::Boolean> lhs_rcp =
463 SE::rcp_static_cast<const SE::Boolean>(lhs.get_RCP());
464 const SE::RCP<const SE::Boolean> rhs_rcp =
465 SE::rcp_static_cast<const SE::Boolean>(rhs.get_RCP());
466
467 return Expression(SE::logical_and({lhs_rcp, rhs_rcp}));
468 }
469
470
471 Expression
472 operator|(const Expression &lhs, const Expression &rhs)
473 {
474 Assert(SE::is_a_Boolean(lhs.get_value()),
475 ExcMessage("The lhs expression must return a boolean type."));
476 Assert(SE::is_a_Boolean(rhs.get_value()),
477 ExcMessage("The rhs expression must return a boolean type."));
478
479 const SE::RCP<const SE::Boolean> lhs_rcp =
480 SE::rcp_static_cast<const SE::Boolean>(lhs.get_RCP());
481 const SE::RCP<const SE::Boolean> rhs_rcp =
482 SE::rcp_static_cast<const SE::Boolean>(rhs.get_RCP());
483
484 return Expression(SE::logical_or({lhs_rcp, rhs_rcp}));
485 }
486
487
488 Expression
489 operator^(const Expression &lhs, const Expression &rhs)
490 {
491 Assert(SE::is_a_Boolean(lhs.get_value()),
492 ExcMessage("The lhs expression must return a boolean type."));
493 Assert(SE::is_a_Boolean(rhs.get_value()),
494 ExcMessage("The rhs expression must return a boolean type."));
495
496 const SE::RCP<const SE::Boolean> lhs_rcp =
497 SE::rcp_static_cast<const SE::Boolean>(lhs.get_RCP());
498 const SE::RCP<const SE::Boolean> rhs_rcp =
499 SE::rcp_static_cast<const SE::Boolean>(rhs.get_RCP());
500
501 return Expression(SE::logical_xor({lhs_rcp, rhs_rcp}));
502 }
503
504
505 Expression
506 operator&&(const Expression &lhs, const Expression &rhs)
507 {
508 return lhs & rhs;
509 }
510
511
512 Expression
513 operator||(const Expression &lhs, const Expression &rhs)
514 {
515 return lhs | rhs;
516 }
517
518
519 Expression
521 {
522 lhs += rhs;
523 return lhs;
524 }
525
526
527 Expression
529 {
530 lhs -= rhs;
531 return lhs;
532 }
533
534
535 Expression
537 {
538 lhs *= rhs;
539 return lhs;
540 }
541
542
543 Expression
545 {
546 lhs /= rhs;
547 return lhs;
548 }
549
550
551 } // namespace SD
552} // namespace Differentiation
553
554
555
556#endif // DEAL_II_WITH_SYMENGINE
*  *  reference operator*() const
Expression & operator/=(const Expression &rhs)
Expression & parse(const std::string &expression)
Expression & operator=(const Expression &rhs)
const SymEngine::RCP< const SymEngine::Basic > & get_RCP() const
Expression & operator*=(const Expression &rhs)
std::ostream & print(std::ostream &stream) const
Expression substitute(const types::substitution_map &substitution_values) const
void save(std::ostream &stream) const
Expression & operator-=(const Expression &rhs)
const SymEngine::Basic & get_value() const
const SymEngine::Expression & get_expression() const
Expression & operator+=(const Expression &rhs)
Expression differentiate(const Expression &symbol) const
#define DEAL_II_NAMESPACE_OPEN
Definition config.h:38
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:39
static ::ExceptionBase & ExcIO()
static ::ExceptionBase & ExcSymEngineParserError(std::string arg1)
#define Assert(cond, exc)
static ::ExceptionBase & ExcMessage(std::string arg1)
#define AssertThrow(cond, exc)
SymEngine::map_basic_basic convert_expression_map_to_basic_map(const SD::types::substitution_map &substitution_map)
std::vector< SD::Expression > symbol_vector
std::map< SD::Expression, SD::Expression, internal::ExpressionKeyLess > substitution_map
Expression operator<(const Expression &lhs, const Expression &rhs)
Expression operator-(Expression lhs, const Expression &rhs)
Expression operator+(Expression lhs, const Expression &rhs)
Expression operator!(const Expression &expression)
Expression operator||(const Expression &lhs, const Expression &rhs)
Expression operator^(const Expression &lhs, const Expression &rhs)
Expression operator>=(const Expression &lhs, const Expression &rhs)
Expression operator!=(const Expression &lhs, const Expression &rhs)
Expression operator|(const Expression &lhs, const Expression &rhs)
Expression operator>(const Expression &lhs, const Expression &rhs)
Expression operator&(const Expression &lhs, const Expression &rhs)
Expression operator/(Expression lhs, const Expression &rhs)
Expression operator<=(const Expression &lhs, const Expression &rhs)
Expression operator&&(const Expression &lhs, const Expression &rhs)
std::ostream & operator<<(std::ostream &stream, const Expression &expression)
Expression operator==(const Expression &lhs, const Expression &rhs)
std::istream & operator>>(std::istream &stream, Expression &expression)