Move term erase methods into private.
[piranha:mainline.git] / src / core / base_classes / base_series_def.h
1 /***************************************************************************
2  *   Copyright (C) 2007, 2008 by Francesco Biscani   *
3  *   bluescarni@gmail.com   *
4  *                                                                         *
5  *   This program is free software; you can redistribute it and/or modify  *
6  *   it under the terms of the GNU General Public License as published by  *
7  *   the Free Software Foundation; either version 2 of the License, or     *
8  *   (at your option) any later version.                                   *
9  *                                                                         *
10  *   This program is distributed in the hope that it will be useful,       *
11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
13  *   GNU General Public License for more details.                          *
14  *                                                                         *
15  *   You should have received a copy of the GNU General Public License     *
16  *   along with this program; if not, write to the                         *
17  *   Free Software Foundation, Inc.,                                       *
18  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
19  ***************************************************************************/
20
21 #ifndef PIRANHA_BASE_SERIES_DEF_H
22 #define PIRANHA_BASE_SERIES_DEF_H
23
24 #include <boost/functional/hash.hpp>
25 #include <boost/unordered_set.hpp>
26 #include <cstddef>
27 #include <functional>
28 #include <iostream>
29 #include <memory>
30 #include <vector>
31
32 #include "../config.h"
33 #include "../exceptions.h"
34 #include "../memory.h"
35 #include "../mp.h"
36 #include "../null_type.h"
37 #include "../psym.h"
38 #include "../type_traits.h"
39 #include "toolbox.h"
40
41 // Template parameters list for piranha::base_series (declaration form).
42 #define __PIRANHA_BASE_SERIES_TP_DECL class Term, char Separator, class Allocator, class Derived
43 // Template parameters list for piranha::base_series (implementation form).
44 #define __PIRANHA_BASE_SERIES_TP Term,Separator,Allocator,Derived
45
46 namespace piranha
47 {
48         template <class EchelonType, int N = 0>
49         struct echelon_level_impl
50         {
51                 static const int value = echelon_level_impl<typename EchelonType::next_echelon_type,N + 1>::value;
52         };
53
54         template <int N>
55         struct echelon_level_impl<null_type,N>
56         {
57                 // Offset is 1 because we went one past.
58                 static const int value = N - 1;
59         };
60
61         // Struct to define the container used in series - like a template typedef.
62         template <class Term>
63         struct series_container
64         {
65                 typedef boost::unordered_set<Term,boost::hash<Term>,std::equal_to<Term>,counting_allocator<Term,std::allocator<char> > > type;
66         };
67
68         // These accessors are used in generic code that must work on both plain series (i.e., iterators) and sorted representations
69         // of series as returned by get_sorted_series (i.e., pointers to pointers of terms).
70         template <class Iterator>
71         struct it_getter
72         {
73                 static const Iterator &get(const Iterator &it)
74                 {
75                         return it;
76                 }
77         };
78
79         template <class TermPointer>
80         struct it_getter<TermPointer *>
81         {
82                 static const TermPointer get(const TermPointer *p)
83                 {
84                         return *p;
85                 }
86         };
87
88         template <__PIRANHA_BASE_SERIES_TP_DECL>
89         struct base_series {};
90
91         /// Base series class.
92         /**
93          * This class provides the basic representation of a series as a collection of terms stored into a hash set. The class is intended
94          * to be inherited together with (at least) either piranha::named_series (for a top-level series) or piranha::cf_series (for a coefficient series).
95          *
96          * The methods in this class provide the lowest level of series manipulation, and allow to operate directly on the individual terms of the
97          * series.
98          *
99          * @author Francesco Biscani (bluescarni@gmail.com)
100          */
101         template <__PIRANHA_BASE_SERIES_TP_DECL>
102         class toolbox<base_series<__PIRANHA_BASE_SERIES_TP> >
103         {
104                 public:
105                         /// Alias for term type.
106                         typedef Term term_type;
107                         /// Term container.
108                         /**
109                          * The underlying term container is a plain boost::unordered set. Term types must specialise the boost::hash class, which
110                          * will be used to provide the hash values for terms.
111                          */
112                         typedef typename series_container<term_type>::type container_type;
113                         /// Next echelon type (term's coefficient).
114                         typedef typename term_type::cf_type next_echelon_type;
115                         /// Echelon level.
116                         static const int echelon_level = echelon_level_impl<next_echelon_type>::value;
117                         /// Type resulting from series evaluation.
118                         /**
119                          * Determined automatically at compile time. Will be double in case of series with scalar coefficients,
120                          * std::complex<double> in case of series with complex coefficients.
121                          */
122                         typedef typename term_eval_type_determiner<Term>::type eval_type;
123                         /// Const iterator over the series' terms.
124                         typedef typename container_type::const_iterator const_iterator;
125                         /// Size type.
126                         typedef typename container_type::size_type size_type;
127                         size_type length() const;
128                         bool empty() const;
129                         bool is_single_cf() const;
130                         size_type atoms() const;
131                 protected:
132                         template <class ArgsTuple>
133                         void term_erase(const const_iterator &, const ArgsTuple &);
134                         void clear_terms();
135                         template <bool, bool, class Term2, class ArgsTuple>
136                         void insert(const Term2 &, const ArgsTuple &);
137                         template <class Term2, class ArgsTuple>
138                         void insert(const Term2 &, const ArgsTuple &);
139                         template <class Iterator, class ArgsTuple>
140                         void insert_range(const Iterator &, const Iterator &, const ArgsTuple &);
141                         const_iterator begin() const;
142                         const_iterator end() const;
143                         template <class Key, class ArgsTuple>
144                         static Derived base_series_from_key(const Key &, const ArgsTuple &);
145                         template <class Cf, class ArgsTuple>
146                         static Derived base_series_from_cf(const Cf &, const ArgsTuple &);
147                         const_iterator find_term(const term_type &) const;
148                         bool base_equal_to(const Derived &) const;
149                         bool base_equal_to(const double &) const;
150                         bool base_equal_to(const mp_rational &) const;
151                         bool base_equal_to(const mp_integer &) const;
152                         template <class ArgsTuple>
153                         double base_norm(const ArgsTuple &) const;
154                         template <class ArgsTuple>
155                         eval_type base_eval(const double &, const ArgsTuple &) const;
156                         template <class ArgsTuple>
157                         Derived &base_add(const Derived &, const ArgsTuple &);
158                         template <class ArgsTuple>
159                         Derived &base_add(const double &, const ArgsTuple &);
160                         template <class ArgsTuple>
161                         Derived &base_add(const mp_rational &, const ArgsTuple &);
162                         template <class ArgsTuple>
163                         Derived &base_add(const mp_integer &, const ArgsTuple &);
164                         template <class ArgsTuple>
165                         Derived &base_subtract(const double &, const ArgsTuple &);
166                         template <class ArgsTuple>
167                         Derived &base_subtract(const mp_rational &, const ArgsTuple &);
168                         template <class ArgsTuple>
169                         Derived &base_subtract(const mp_integer &, const ArgsTuple &);
170                         template <class ArgsTuple>
171                         Derived &base_subtract(const Derived &, const ArgsTuple &);
172                         template <class ArgsTuple>
173                         Derived &base_mult_by(const double &, const ArgsTuple &);
174                         template <class ArgsTuple>
175                         Derived &base_mult_by(const mp_rational &, const ArgsTuple &);
176                         template <class ArgsTuple>
177                         Derived &base_mult_by(const mp_integer &, const ArgsTuple &);
178                         template <class ArgsTuple>
179                         Derived &base_mult_by(const Derived &, const ArgsTuple &);
180                         template <class ArgsTuple>
181                         Derived &base_divide_by(const double &, const ArgsTuple &);
182                         template <class ArgsTuple>
183                         Derived &base_divide_by(const mp_rational &, const ArgsTuple &);
184                         template <class ArgsTuple>
185                         Derived &base_divide_by(const mp_integer &, const ArgsTuple &);
186                         template <class ArgsTuple>
187                         Derived base_inv(const ArgsTuple &) const;
188                         template <class ArgsTuple>
189                         Derived base_pow(const double &, const ArgsTuple &) const;
190                         template <class ArgsTuple>
191                         Derived base_pow(const mp_rational &, const ArgsTuple &) const;
192                         template <class ArgsTuple>
193                         Derived base_root(const int &, const ArgsTuple &) const;
194                         template <class PosTuple, class ArgsTuple>
195                         Derived base_partial(int, const PosTuple &, const ArgsTuple &) const;
196                         template <class PosTuple, class ArgsTuple>
197                         Derived base_partial(const PosTuple &, const ArgsTuple &) const;
198                         // Standard substitution functor. Will call sub() on coefficients and keys.
199                         struct sub_functor {
200                                 template <class RetSeries, class Element, class PosTuple, class SubCaches,
201                                         class ArgsTuple>
202                                 static RetSeries run(const Element &e, const PosTuple &pos_tuple,
203                                         SubCaches &sub_caches, const ArgsTuple &args_tuple) {
204                                         return e.template sub<RetSeries>(pos_tuple, sub_caches, args_tuple);
205                                 }
206                         };
207                         static const char separator = Separator;
208                         // Check that the separators do not conflict.
209                         p_static_check(separator != term_type::separator, "");
210                         template <class Number, class ArgsTuple>
211                         void construct_from_number(const Number &, const ArgsTuple &);
212                         template <class ArgsTuple>
213                         void base_construct_from_psym(const psym &, const int &, const ArgsTuple &);
214                         template <class ArgsTuple>
215                         void print_terms_plain(std::ostream &, const ArgsTuple &) const;
216                         template <class ArgsTuple>
217                         void print_terms_tex(std::ostream &, const ArgsTuple &) const;
218                         template <class ArgsTuple>
219                         void print_terms_pretty(std::ostream &, const ArgsTuple &) const;
220                         void base_swap(Derived &);
221                         template <class Number>
222                         bool generic_numerical_comparison(const Number &) const;
223                         template <class Layout, class ArgsTuple>
224                         void apply_layout_to_terms(const Layout &, Derived &, const ArgsTuple &) const;
225                         template <bool, class Derived2, class ArgsTuple>
226                         Derived &merge_terms(const Derived2 &, const ArgsTuple &);
227                         template <class TrimFlags>
228                         void trim_test_terms(TrimFlags &) const;
229                         template <class TrimFlags, class ArgsTuple>
230                         void trim_terms(const TrimFlags &, Derived &, const ArgsTuple &) const;
231                         template <class T, class ArgsTuple>
232                         void multiply_coefficients_by(const T &, const ArgsTuple &);
233                         template <class T, class ArgsTuple>
234                         void divide_coefficients_by(const T &, const ArgsTuple &);
235                         template <bool, class Number, class ArgsTuple>
236                         Derived &merge_with_number(const Number &, const ArgsTuple &);
237                         template <class ArgsTuple>
238                         Derived natural_power(const std::size_t &, const ArgsTuple &) const;
239                         template <class ArgsTuple>
240                         Derived negative_integer_power(const int &, const ArgsTuple &) const;
241                         template <class ArgsTuple>
242                         Derived real_power(const double &, const ArgsTuple &) const;
243                         template <class ArgsTuple>
244                         Derived rational_power(const mp_rational &, const ArgsTuple &) const;
245                         template <class RetSeries, class SubFunctor, class PosTuple, class SubCaches, class ArgsTuple>
246                         RetSeries base_sub(const PosTuple &, SubCaches &, const ArgsTuple &) const;
247                         template <class Series, class PosTuple, class ArgsTuple>
248                         static void ll_partial(const Derived &, Series &, const PosTuple &, const ArgsTuple &);
249                         template <class Series, class ArgsTuple>
250                         void base_split(std::vector<std::vector<Series> > &, const int &n, const ArgsTuple &) const;
251                         template <class ArgsTuple>
252                         std::vector<term_type> flatten_terms(const ArgsTuple &) const;
253                 private:
254                         template <class Iterator, class ArgsTuple>
255                         void generic_print_terms_pretty(std::ostream &, const Iterator &, const Iterator &, const ArgsTuple &) const;
256                         template <class Iterator, class ArgsTuple>
257                         void generic_print_terms_tex(std::ostream &, const Iterator &, const Iterator &, const ArgsTuple &) const;
258                         template <class Iterator, class Series, class ArgsTuple>
259                         void generic_base_split(std::vector<std::vector<Series> > &, const Iterator &, const Iterator &, const ArgsTuple &) const;
260                         template <bool, class ArgsTuple>
261                         void ll_insert(const term_type &, const ArgsTuple &);
262                         template <bool, class ArgsTuple>
263                         void term_insert_new(const term_type &, const ArgsTuple &);
264                         template <int, class T, class ArgsTuple>
265                         void mult_div_coefficients_by(const T &, const ArgsTuple &);
266                         template <class Number, class ArgsTuple>
267                         Derived &multiply_by_number(const Number &, const ArgsTuple &);
268                         template <class Number, class ArgsTuple>
269                         Derived &divide_by_number(const Number &, const ArgsTuple &);
270                         template <class Number, class ArgsTuple>
271                         bool common_pow_handler(const Number &, Derived &retval, const ArgsTuple &) const;
272                 private:
273                         container_type m_container;
274         };
275
276 #define E0_SERIES_TP_DECL class Cf, class Key, class Multiplier, class Truncator, class Allocator
277 #define E0_SERIES_TP Cf,Key,Multiplier,Truncator,Allocator
278 #define E0_SERIES_TERM(term_name) term_name<Cf,Key,'|',Allocator>
279 #define E0_SERIES(series_name) series_name<E0_SERIES_TP>
280 #define E0_SERIES_BASE_ANCESTOR(term_name,series_name) piranha::toolbox<piranha::base_series<E0_SERIES_TERM(term_name),'\n', \
281         Allocator,E0_SERIES(series_name) > >
282
283 #define E1_SERIES_TP_DECL class Cf, class Key0, class Key1, \
284                                                 class Mult0, class Mult1, class Trunc0, class Trunc1, class Allocator
285 #define E1_SERIES_TP Cf,Key0,Key1,Mult0,Mult1,Trunc0,Trunc1,Allocator
286 #define E1_SERIES_COEFFICIENT(cf_name) cf_name<Cf,Key0,Mult0,Trunc0,Allocator>
287 #define E1_SERIES(series_name) series_name<E1_SERIES_TP>
288 #define E1_SERIES_TERM(term_name,cf_name) term_name< cf_name, Key1, '|', Allocator >
289 #define E1_SERIES_BASE_ANCESTOR(term_name,cf_name,series_name) piranha::toolbox<piranha::base_series<term_name< \
290         cf_name,Key1,'|',Allocator>, \
291         '\n',Allocator,series_name > >
292 }
293
294 #endif