Bertini 2 d882924 (2026-10-06 19:56 UTC)
Numerical algebraic geometry library (C++ core)
Loading...
Searching...
No Matches
number.hpp
Go to the documentation of this file.
1//This file is part of Bertini 2.
2//
3//number.hpp is free software: you can redistribute it and/or modify
4//it under the terms of the GNU General Public License as published by
5//the Free Software Foundation, either version 3 of the License, or
6//(at your option) any later version.
7//
8//number.hpp is distributed in the hope that it will be useful,
9//but WITHOUT ANY WARRANTY; without even the implied warranty of
10//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11//GNU General Public License for more details.
12//
13//You should have received a copy of the GNU General Public License
14//along with number.hpp. If not, see <http://www.gnu.org/licenses/>.
15//
16// Copyright(C) Bertini2 Development Team
17//
18// See <http://www.gnu.org/licenses/> for a copy of the license,
19// as well as COPYING. Bertini2 is provided with permitted
20// additional terms in the b2/licenses/ directory.
21
22// number.hpp: Declares the class Number.
23
30
31
32#ifndef BERTINI_NODE_NUMBER_HPP
33#define BERTINI_NODE_NUMBER_HPP
34
35
37
38
39
40namespace bertini {
41namespace node{
42
43
49 class Number : public Symbol
50 {
51 public:
52
53 virtual ~Number() = default;
54
55
56
57
58
59
60
61
62
63
69 inline
70 int Degree(std::shared_ptr<Variable> const& /*v*/ = nullptr) const override
71 {
72 return 0;
73 }
74
80 inline
81 int Degree(VariableGroup const& /*vars*/) const override
82 {
83 return 0;
84 }
85
86
92 inline
93 std::vector<int> MultiDegreeImpl(VariableGroup const& vars) const override
94 {
95 return std::vector<int>(vars.size(), 0);
96 }
97
98
104 bool IsHomogeneous(std::shared_ptr<Variable> const& /*v*/ = nullptr) const override
105 {
106 return true;
107 }
108
112 bool IsHomogeneous(VariableGroup const& /*vars*/) const override
113 {
114 return true;
115 }
116
117
121 std::shared_ptr<Node> Differentiate(std::shared_ptr<Variable> const& v = nullptr) const override;
122
123 protected:
124
125 private:
127
128 template <typename Archive>
129 void serialize(Archive& ar, const unsigned /*version*/) {
130 ar & boost::serialization::base_object<Symbol>(*this);
131 }
132
133
134 };
135
136
142 class Integer : public Number
143 {
144 public:
146
147
148
149
150 Integer(Integer const&) = default;
151
152 ~Integer() = default;
153
154
155
156
157 void print(std::ostream & target) const override;
158
159 // negative literals print with a leading '-', so parenthesize like a Negate
160 unsigned Precedence() const override
161 {
162 return true_value_ < 0 ? PrecNegate : PrecAtom;
163 }
164
168 mpz_int const& GetValue() const
169 {
170 return true_value_;
171 }
172
173 bool IsLiteralZero() const override
174 {
175 return true_value_ == 0;
176 }
177
178 bool IsLiteralOne() const override
179 {
180 return true_value_ == 1;
181 }
182
183 std::size_t HashImpl() const override
184 {
185 std::size_t h = typeid(Integer).hash_code();
186 HashCombine(h, std::hash<std::string>{}(true_value_.str()));
187 return h;
188 }
189 bool IsSame(Node const& other) const override
190 {
191 auto o = dynamic_cast<Integer const*>(&other);
192 return o && true_value_ == o->true_value_;
193 }
194
196 template<typename... Ts>
197 static
198 std::shared_ptr<Integer> Make(Ts&& ...ts){
199 return std::static_pointer_cast<Integer>(Intern(std::shared_ptr<Node>( new Integer(ts...) )));
200 }
201
202 private:
203 // https://stackoverflow.com/questions/33933550/exception-bad-weak-ptr-while-shared-from-this
204 // struct MakeConstructorPublic;
205
206 explicit
207 Integer(int val) : true_value_(val)
208 {}
209
210 explicit
211 Integer(mpz_int val) : true_value_(val)
212 {}
213
214 explicit
215 Integer(std::string const& val) : true_value_(val)
216 {}
217
218
219
220
221
222 mpz_int true_value_;
223
225
226 Integer() = default;
227
228 template <typename Archive>
229 void serialize(Archive& ar, const unsigned /*version*/) {
230 ar & boost::serialization::base_object<Number>(*this);
231 ar & true_value_;
232 }
233 };
234
235 // struct Integer::MakeConstructorPublic : public Integer {
236 // template <typename... Args>
237 // MakeConstructorPublic(Args&& ...args) : Integer(std::forward<Args>(args)...)
238 // {}
239 // };
240
241
242
253 class Complex : public Number
254 {
255 public:
257
258
259
260 ~Complex() = default;
261
262
263
264
265
266 void print(std::ostream & target) const override;
267
268 // real-valued floats print bare (no complex pair); negative ones get
269 // a leading '-', so parenthesize like a Negate. pairs self-delimit.
270 unsigned Precedence() const override
271 {
272 if (highest_precision_value_.imag() == 0 && highest_precision_value_.real() < 0)
273 return PrecNegate;
274 return PrecAtom;
275 }
276
280 complex_mp const& GetValue() const
281 {
282 return highest_precision_value_;
283 }
284
285 bool IsLiteralZero() const override
286 {
287 return highest_precision_value_.real() == 0 && highest_precision_value_.imag() == 0;
288 }
289
290 bool IsLiteralOne() const override
291 {
292 return highest_precision_value_.real() == 1 && highest_precision_value_.imag() == 0;
293 }
294
295 std::size_t HashImpl() const override
296 {
297 std::size_t h = typeid(Complex).hash_code();
298 HashCombine(h, std::hash<std::string>{}(highest_precision_value_.real().str()));
299 HashCombine(h, std::hash<std::string>{}(highest_precision_value_.imag().str()));
300 return h;
301 }
302 bool IsSame(Node const& other) const override
303 {
304 auto o = dynamic_cast<Complex const*>(&other);
305 return o
306 && highest_precision_value_.real() == o->highest_precision_value_.real()
307 && highest_precision_value_.imag() == o->highest_precision_value_.imag();
308 }
309
311 template<typename... Ts>
312 static
313 std::shared_ptr<Complex> Make(Ts&& ...ts){
314 return std::static_pointer_cast<Complex>(Intern(std::shared_ptr<Node>( new Complex(ts...) )));
315 }
316
317 private:
318
319 explicit
320 Complex(complex_mp const& val) : highest_precision_value_(val)
321 {}
322
323 explicit
324 Complex(real_mp const& rval, real_mp const& ival = 0) : highest_precision_value_(rval,ival)
325 {}
326
327 explicit
328 Complex(std::string const& val) : highest_precision_value_(val)
329 {}
330
331 explicit
332 Complex(std::string const& rval, std::string const& ival) : highest_precision_value_(rval,ival)
333 {}
334
346 Complex(std::string const& rval, std::string const& ival, unsigned precision)
347 {
348 real_mp const re(rval, precision);
349 real_mp const im(ival, precision);
350 highest_precision_value_.precision(precision);
351 highest_precision_value_.real(re);
352 highest_precision_value_.imag(im);
353 }
354
355
356
357 complex_mp highest_precision_value_;
358
360 Complex() = default;
361 template <typename Archive>
362 void serialize(Archive& ar, const unsigned /*version*/) {
363 ar & boost::serialization::base_object<Number>(*this);
364 ar & const_cast<complex_mp &>(highest_precision_value_);
365 }
366 };
367
368
369
370
371
372
378 class Rational : public Number
379 {
380 public:
382
384
385
386
387
388 Rational(int, int) = delete;
389
390 ~Rational() = default;
391
397 template<unsigned long Digits = 50>
398 static
403
409 template<int Digits = 50>
410 static
412 {
413 return Rational(RandomRat<Digits>(),0);
414 }
415
416 void print(std::ostream & target) const override;
417
418 // real-valued rationals print bare (no complex pair). the bare form is
419 // textually an expression: a leading '-' parenthesizes like a Negate, and
420 // 'p/q' contains a division, so it binds like a Mult (x/(1/3), not x/1/3).
421 // complex pairs self-delimit.
422 unsigned Precedence() const override
423 {
424 if (true_value_imag_ == 0)
425 {
426 if (true_value_real_ < 0)
427 return PrecNegate;
428 if (denominator(true_value_real_) != 1)
429 return PrecMult;
430 }
431 return PrecAtom;
432 }
433
438 {
439 return true_value_real_;
440 }
441
446 {
447 return true_value_imag_;
448 }
449
458 template<typename NumT>
459 NumT Value() const
460 {
461 if constexpr (std::is_same<NumT, complex_dbl>::value)
462 return complex_dbl(double(true_value_real_), double(true_value_imag_));
463 else
464 return NumT(boost::multiprecision::mpfr_float(true_value_real_, ThreadPrecision()),
465 boost::multiprecision::mpfr_float(true_value_imag_, ThreadPrecision()));
466 }
467
468 bool IsLiteralZero() const override
469 {
470 return true_value_real_ == 0 && true_value_imag_ == 0;
471 }
472
473 bool IsLiteralOne() const override
474 {
475 return true_value_real_ == 1 && true_value_imag_ == 0;
476 }
477
478 std::size_t HashImpl() const override
479 {
480 std::size_t h = typeid(Rational).hash_code();
481 HashCombine(h, std::hash<std::string>{}(true_value_real_.str()));
482 HashCombine(h, std::hash<std::string>{}(true_value_imag_.str()));
483 return h;
484 }
485 bool IsSame(Node const& other) const override
486 {
487 auto o = dynamic_cast<Rational const*>(&other);
488 return o && true_value_real_ == o->true_value_real_ && true_value_imag_ == o->true_value_imag_;
489 }
490
491
492
494 template<typename... Ts>
495 static
496 std::shared_ptr<Rational> Make(Ts&& ...ts){
497 return std::static_pointer_cast<Rational>(Intern(std::shared_ptr<Node>( new Rational(ts...) )));
498 }
499
500 private:
501
502 explicit
503 Rational(int val) : true_value_real_(val), true_value_imag_(0)
504 {}
505
506 explicit
507 Rational(int val_real_numerator, int val_real_denomenator,
508 int val_imag_numerator, int val_imag_denomenator)
509 :
510 true_value_real_(val_real_numerator,val_real_denomenator), true_value_imag_(val_imag_numerator,val_imag_denomenator)
511 {}
512
513 explicit
514 Rational(std::string val) : true_value_real_(val), true_value_imag_(0)
515 {}
516
517 explicit
518 Rational(std::string val_real, std::string val_imag) : true_value_real_(val_real), true_value_imag_(val_imag)
519 {}
520
521 explicit
522 Rational(mpq_rational const& val_real, mpq_rational const& val_imag = 0) : true_value_real_(val_real), true_value_imag_(val_imag)
523 {}
524
525
526
527
528 mpq_rational true_value_real_, true_value_imag_;
529 Rational() = default;
531
532 template <typename Archive>
533 void serialize(Archive& ar, const unsigned /*version*/) {
534 ar & boost::serialization::base_object<Number>(*this);
535 ar & const_cast<mpq_rational &>(true_value_real_);
536 ar & const_cast<mpq_rational &>(true_value_imag_);
537 }
538 };
539
540
541
542} // re: namespace node
543} // re: namespace bertini
544
545#endif
A complex-number literal node in an expression tree.
Definition number.hpp:254
static std::shared_ptr< Complex > Make(Ts &&...ts)
Construct (and intern) a Complex node.
Definition number.hpp:313
complex_mp const & GetValue() const
Get the literal value this node represents, at its stored (highest) precision.
Definition number.hpp:280
bool IsLiteralZero() const override
Is this node the literal constant 0?
Definition number.hpp:285
bool IsSame(Node const &other) const override
Order-sensitive structural equality, shallow given interned children.
Definition number.hpp:302
void print(std::ostream &target) const override
Virtual method for printing Nodes to arbitrary output streams.
unsigned Precedence() const override
The printing precedence of this node, deciding parenthesization.
Definition number.hpp:270
bool IsLiteralOne() const override
Is this node the literal constant 1?
Definition number.hpp:290
friend class boost::serialization::access
Definition number.hpp:359
std::size_t HashImpl() const override
Compute this node's structural hash.
Definition number.hpp:295
static std::shared_ptr< Integer > Make(Ts &&...ts)
Construct (and intern) a Integer node.
Definition number.hpp:198
std::size_t HashImpl() const override
Compute this node's structural hash.
Definition number.hpp:183
mpz_int const & GetValue() const
Get the literal value this node represents.
Definition number.hpp:168
bool IsLiteralOne() const override
Is this node the literal constant 1?
Definition number.hpp:178
unsigned Precedence() const override
The printing precedence of this node, deciding parenthesization.
Definition number.hpp:160
void print(std::ostream &target) const override
Virtual method for printing Nodes to arbitrary output streams.
friend class boost::serialization::access
Definition number.hpp:224
bool IsSame(Node const &other) const override
Order-sensitive structural equality, shallow given interned children.
Definition number.hpp:189
Integer(Integer const &)=default
Defaulted copy constructor.
bool IsLiteralZero() const override
Is this node the literal constant 0?
Definition number.hpp:173
An interface for all nodes in a function tree, and for a function object as well.
Definition node.hpp:114
static void HashCombine(std::size_t &seed, std::size_t value)
Combine an extra value into a running hash (boost::hash_combine recipe).
Definition node.hpp:384
Abstract Number type from which other Numbers derive.
Definition number.hpp:50
int Degree(VariableGroup const &) const override
Get the degree of this node.
Definition number.hpp:81
bool IsHomogeneous(VariableGroup const &) const override
Check for homogeneity, with respect to a variable group.
Definition number.hpp:112
bool IsHomogeneous(std::shared_ptr< Variable > const &=nullptr) const override
Is this node homogeneous?
Definition number.hpp:104
int Degree(std::shared_ptr< Variable > const &=nullptr) const override
Get the degree of this node.
Definition number.hpp:70
std::vector< int > MultiDegreeImpl(VariableGroup const &vars) const override
Get the multidegree of this node.
Definition number.hpp:93
virtual ~Number()=default
friend class boost::serialization::access
Definition number.hpp:126
std::shared_ptr< Node > Differentiate(std::shared_ptr< Variable > const &v=nullptr) const override
Differentiate a number.
void print(std::ostream &target) const override
Virtual method for printing Nodes to arbitrary output streams.
Rational(int, int)=delete
unsigned Precedence() const override
The printing precedence of this node, deciding parenthesization.
Definition number.hpp:422
bool IsLiteralZero() const override
Is this node the literal constant 0?
Definition number.hpp:468
bool IsSame(Node const &other) const override
Order-sensitive structural equality, shallow given interned children.
Definition number.hpp:485
static std::shared_ptr< Rational > Make(Ts &&...ts)
Construct (and intern) a Rational node.
Definition number.hpp:496
std::size_t HashImpl() const override
Compute this node's structural hash.
Definition number.hpp:478
bool IsLiteralOne() const override
Is this node the literal constant 1?
Definition number.hpp:473
friend class boost::serialization::access
Definition number.hpp:530
static Rational Rand()
Get a random complex rational node.
Definition number.hpp:399
mpq_rational const & GetValueReal() const
Get the real part of the literal value this node represents.
Definition number.hpp:437
mpq_rational const & GetValueImag() const
Get the imaginary part of the literal value this node represents.
Definition number.hpp:445
static Rational RandReal()
Get a random real rational node.
Definition number.hpp:411
NumT Value() const
Get this exact constant as a number of type NumT, independent of the evaluation engine.
Definition number.hpp:459
bertini::mpq_rational mpq_rational
The exact rational type this node stores.
Definition number.hpp:383
Abstract symbol class.
Definition symbol.hpp:47
Definition canonical.hpp:56
std::shared_ptr< Node > Intern(std::shared_ptr< Node > const &candidate)
Hash-cons a freshly-built node: return an existing structurally-equal node if one is live,...
@ PrecAtom
Definition node.hpp:101
@ PrecNegate
Definition node.hpp:98
@ PrecMult
Definition node.hpp:99
Definition algorithm_builder.hpp:36
std::complex< double > complex_dbl
The double-precision complex number type.
Definition double_extensions.hpp:47
boost::multiprecision::number< boost::multiprecision::backends::gmp_int, boost::multiprecision::et_on > mpz_int
The arbitrary-precision integer type.
Definition mpfr_extensions.hpp:54
std::vector< std::shared_ptr< node::Variable > > VariableGroup
An ordered group of variables (the unit of homogenization / variable grouping).
Definition node.hpp:69
bmp::number< mpc_complex_backend< 0 >, bmp::et_on > complex_mp
The arbitrary-precision complex number type.
Definition mpfr_complex.hpp:58
boost::multiprecision::number< boost::multiprecision::mpfr_float_backend< 0 >, boost::multiprecision::et_on > real_mp
The arbitrary-precision real number type.
Definition mpfr_extensions.hpp:53
unsigned ThreadPrecision()
Get the current thread's precision (digits).
Definition mpfr_complex.hpp:183
mpq_rational RandomRat()
Generate a random rational number with numerator and denomenator between -10^digits and 10^digits.
Definition random.hpp:141
Defines the abstract Symbol and NamedSymbol classes,.
#define BERTINI_DEFAULT_VISITABLE()
macro for classes which want default Accept implementation, having nothing fancy to do when accepting...
Definition visitable.hpp:121