File: Storage.hh

package info (click to toggle)
cadabra2 2.4.3.2-2
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 78,732 kB
  • sloc: ansic: 133,450; cpp: 92,064; python: 1,530; javascript: 203; sh: 184; xml: 182; objc: 53; makefile: 51
file content (315 lines) | stat: -rw-r--r-- 12,149 bytes parent folder | download | duplicates (2)
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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
/*

Cadabra: a field-theory motivated computer algebra system.
Copyright (C) 2001-2014  Kasper Peeters <kasper.peeters@phi-sci.com>

This program is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.

This program 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
General Public License for more details.

You should have received a copy of the GNU General Public License
	along with this program.  If not, see <http://www.gnu.org/licenses/>.

*/

#pragma once

#include <cstddef>
#include <iostream>
#include <gmpxx.h>
#include <string>
#include <vector>
#include <set>
#include <map>
#include <stdint.h>
#include <assert.h>
#include <initializer_list>

#include "tree.hh"

namespace cadabra {

	typedef mpq_class               multiplier_t;
	typedef std::set<std::string>   nset_t;
	typedef std::set<multiplier_t>  rset_t;
	typedef uintptr_t               hashval_t;

	long        to_long(multiplier_t);
	double      to_double(multiplier_t);
	std::string to_string(long);

	extern nset_t name_set;
	extern rset_t rat_set;

	/// \ingroup core
	///
	/// Elementary building block for a mathematical expression. Contains information about the
	/// way in which the node is related to the parent node, and iterators into the global
	/// list of names and rationals.

	class str_node { // size: 9 bytes (32 bit arch), can be reduced to 5 bytes.
		public:
			enum bracket_t     { b_round=0, b_square=1, b_curly=2, b_pointy=3, b_none=4, b_no=5, b_invalid=6 };

			/// Child nodes are related to their parent node by a so-called parent relation, which can
			/// be one of these values.
			enum parent_rel_t  { p_sub=0, p_super=1, p_none=2, p_property=3, p_exponent=4, p_components=5, p_invalid=7 };

			str_node(void);
			str_node(nset_t::iterator name, bracket_t btype=b_none, parent_rel_t ptype=p_none);
			str_node(const std::string& name, bracket_t btype=b_none, parent_rel_t ptype=p_none);
			str_node(const std::u32string& name, bracket_t btype=b_none, parent_rel_t ptype=p_none);

			bool operator==(const str_node&) const;
			bool operator<(const str_node&) const;

			nset_t::iterator name;
			rset_t::iterator multiplier;

#ifdef _WIN32
			struct flag_t {
				bool            keep_after_eval ;
				bracket_t       bracket         ;
				parent_rel_t    parent_rel      ;
				bool            line_per_node   ;
				};
#else
			struct flag_t { // kept inside 8 bits for speed and size
				bool            keep_after_eval : 1;
				bracket_t       bracket         : 3;
				parent_rel_t    parent_rel      : 3;
				bool            line_per_node   : 1;
				};
#endif

			flag_t fl;

			/// Change the parent relation from sub to super and vice versa (throws error
			/// when this is not an index).
			void flip_parent_rel();

			bool is_zero() const;
			bool is_identity() const;
			bool is_rational() const;
			bool is_unsimplified_rational() const;
			bool is_integer() const;
			bool is_unsimplified_integer() const;
			bool is_index() const;            // _ or ^ parent_rel (does not query properties)
			bool is_quoted_string() const;
			bool is_command() const;
			bool is_inert_command() const;
			bool is_name_wildcard() const;    //  ?
			bool is_object_wildcard() const;  //  ??
			bool is_range_wildcard() const;   //  #{..}
			bool is_siblings_wildcard() const; // a...
			bool is_autodeclare_wildcard() const; // m#
			bool is_indexstar_wildcard() const; // ?* in sub/super
			bool is_indexplus_wildcard() const; // ?+ in sub/super
			bool is_numbered_symbol() const;  //  [a-zA-Z]+[0-9]+

			nset_t::iterator name_only();

			static bool compare_names_only(const str_node&, const str_node&);
			static bool compare_name_brack_par(const str_node&, const str_node&);
			static bool compare_name_inverse_par(const str_node&, const str_node&);
		};

	/// \ingroup core
	///
	/// Helper functions for manipulation of multipliers.
	void     multiply(rset_t::iterator&, multiplier_t);
	void     add(rset_t::iterator&, multiplier_t);
	void     zero(rset_t::iterator&);
	void     one(rset_t::iterator&);
	void     flip_sign(rset_t::iterator&);
	void     half(rset_t::iterator&);

	/// \ingroup core
	///
	/// Basic storage class for symbolic mathemematical expressions. The
	/// full meaning of an expression typically requires knowledge about
	/// properties of patterns in it, which this class does _not_
	/// contain. All property dependent algorithms acting on Ex
	/// objects are in Algorithm.hh.

	class Ex : public std::enable_shared_from_this<Ex>, public tree<str_node> {
		public:
			Ex();
			//		Ex(const tree<str_node>&);
			Ex(tree<str_node>::iterator);
			Ex(const str_node&);
			Ex(const Ex&);
			/// Initialise with given string as head node (does not parse this string).
			Ex(const std::string&);
			Ex(int);

			/// Keeping track of what algorithms have done to this expression.
			/// After a reset_state (or at initialisation), the expression sits
			/// in the 'checkpointed' state. When an algorithm acts, it can then
			/// move to 'no_action' (unchanged), 'applied' (changed) or 'error'.
			/// Once it is in 'error', it will stay there until the next 'reset'.
			/// FIXME: the following should implement a stack of states,
			/// so that it can be used with nested functions.

			enum result_t { l_checkpointed, l_no_action, l_applied, l_applied_no_new_dummies, l_error };
			result_t state() const;
			void     update_state(result_t);
			void     reset_state();

			/// A status query method mainly to implement a simple method to
			/// apply algorithms until they converge. Returns true when the
			/// expression is in 'checkpointed' or 'applied' state. Will
			/// set the state to 'no_action'.
			bool     changed_state();

			/// Test if the expression is a rational number.
			/// FIXME: add tests for integers as well.
			bool          is_rational() const;
			multiplier_t  to_rational() const;
			bool          is_integer() const;
			long          to_integer() const;

			/// Display expression in Python/Cadabra input form. This is
			/// fairly straightforward so not handled with a separate
			/// DisplayBase derived class.
			static std::ostream& print_python(std::ostream& str, Ex::iterator it);

			/// Output helpers mainly for debugging purposes.
			std::ostream& print_entire_tree(std::ostream& str) const;
			static std::ostream& print_recursive_treeform(std::ostream& str, Ex::iterator it);
			static std::ostream& print_recursive_treeform(std::ostream& str, Ex::iterator it, unsigned int& number);

			/// Print a representation like Python's 'repr'.
			std::ostream& print_repr(std::ostream& str, Ex::iterator it) const;

			/// Step up until matching node is found (if current node matches, do nothing)
			iterator     named_parent(iterator it, const std::string&) const;
			iterator     erase_expression(iterator it);

			/// Calculate the hash value for the subtree starting at 'it'.
			hashval_t    calc_hash(iterator it) const;

			/// Quick access to arguments or argument lists for A(B)(C,D) type nodes.
			static sibling_iterator arg(iterator, unsigned int);
			static unsigned int     arg_size(sibling_iterator);

			multiplier_t     arg_to_num(sibling_iterator, unsigned int) const; // shorthand for numerical arguments

			// Like 'child', but using index iterators instead.
			//		sibling_iterator tensor_index(const iterator_base& position, unsigned int) const;

			// Number of \\history nodes in an expression
			unsigned int     number_of_steps(iterator it) const;
			// Given an iterator pointing to any node in the tree, figure
			// out to which equation number it belongs.
			unsigned int     number_of_equations() const;
			unsigned int     equation_number(iterator it) const;
			nset_t::iterator equation_label(iterator it) const;
			iterator         equation_by_number(unsigned int i) const;
			iterator         equation_by_name(nset_t::iterator it) const;
			iterator         equation_by_name(nset_t::iterator it, unsigned int& ) const;
			iterator         equation_by_number_or_name(iterator it, unsigned int last_used_equation) const;
			iterator         equation_by_number_or_name(iterator it, unsigned int last_used_equation,
			      unsigned int&) const;
			std::string      equation_number_or_name(iterator it, unsigned int last_used_equation) const;
			iterator         procedure_by_name(nset_t::iterator it) const;

			// Determine whether a node has an '\ldots' parent (not necessarily direct).
			bool is_hidden(iterator) const;

			/// Replace the index-like object (originally intended to
			/// replace indices only, but now used also for e.g. normal
			/// function arguments, as in \f[ \partial_{z}{ A(z) } \f] with
			/// a replacement of z).
			///
			/// Note: this originally kept the bracket and parent_rel, but
			/// that is not a good idea, because it prevents us from
			/// changing those. If we want to use a _{z} pattern replacing a
			/// A(z) index, it is better to make a rule that matches (z) and
			/// at the time we find and match _{z}. So this should be
			/// handled by the replacement_map logic in Compare.cc.
			iterator         replace_index(iterator position, const iterator& from, bool keep_parent_rel=false);

			/// As in replace_index, but moves the index rather than making a copy (so that iterators
			/// pointing to the original remain valid).
			iterator         move_index(iterator position, const iterator& from);

			/// Make sure that the node pointed to is a \\comma object, i.e. wrap the node if not already
			/// inside such a \\comma.
			/// DEPRECATED: in favour of 'do_list' in Functional.hh.
			void             list_wrap_single_element(iterator&);
			void             list_unwrap_single_element(iterator&);

			/// Replace the node with the children of the node, useful for e.g.
			/// \\prod{A} -> A. This algorithm takes care of the multiplier of the
			/// top node, i.e. it does 2\\prod{A} -> 2 A. Returns an iterator
			/// to the new location of the first child of the original node.
			iterator         flatten_and_erase(iterator position);

			/// Compare two Ex objects for exact equality; no dummy equivalence or other
			/// things that require property information.

			bool operator==(const Ex& other) const;

			/// Push a copy of the current state of the expression onto the
			/// history stack.  Also pushes a set of paths to terms which
			/// will be kept in the next history step.
			/// DEPRECATED, only used by take_match/replace_match.
			void push_history(const std::vector<Ex::path_t>&);

			/// Pop the most recent state of the expression off the history stack; returns
			/// the set of paths that we are replacing.
			/// DEPRECATED, only used by take_match/replace_match.
			std::vector<Ex::path_t> pop_history();

			/// Return the size of the history; 0 means no history, just the current
			/// expression.
			int  history_size() const;

		private:
			result_t state_;

			std::vector<tree<str_node> > history;
			/// Patterns which describe how to get from one history step to the next.
			std::vector<std::vector<Ex::path_t> > terms;
		};


	/// \ingroup core
	///
	/// Compare two nset iterators by comparing the strings to which they point.

	class nset_it_less {
		public:
			bool operator()(nset_t::iterator first, nset_t::iterator second) const;
		};

	template <typename T>
	bool is_in(const T& val, const std::initializer_list<T>& list)
		{
		for (const auto& i : list) {
			if (val == i) {
				return true;
				}
			}
		return false;
		}

	}

/// \ingroup core
///
/// Bare output operator for Ex objects, mainly to provide a simple
/// way to generate debugging output. Does not do any fancy
/// formatting; just prints a nested list representation.  For more
/// fancy output, look at DisplayTeX, DisplaySympy and
/// DisplayTerminal.

std::ostream& operator<<(std::ostream&, const cadabra::Ex&);
std::ostream& operator<<(std::ostream&, cadabra::Ex::iterator);