Minor.
[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/type_traits/is_base_of.hpp>
26 #include <boost/unordered_set.hpp>
27 #include <boost/utility/enable_if.hpp>
28 #include <cstddef>
29 #include <functional>
30 #include <iostream>
31 #include <memory>
32 #include <vector>
33
34 #include "../config.h"
35 #include "../exceptions.h"
36 #include "../memory.h"
37 #include "../mp.h"
38 #include "../psym.h"
39 #include "../type_traits.h"
40 #include "base_series_mp.h"
41 #include "base_series_tag.h"
42
43 // Template parameters list for piranha::base_series (declaration form).
44 #define __PIRANHA_BASE_SERIES_TP_DECL class Term, char Separator, class Allocator, class Derived
45 // Template parameters list for piranha::base_series (implementation form).
46 #define __PIRANHA_BASE_SERIES_TP Term,Separator,Allocator,Derived
47
48 namespace piranha
49 {
50         // Implementation of echelon level determination.
51         template <class CfSeries, class Enable = void>
52         struct echelon_level_impl
53         {
54                 static const int value = echelon_level_impl<typename CfSeries::term_type::cf_type>::value + 1;
55         };
56
57         template <class FinalCf>
58         struct echelon_level_impl<FinalCf, typename boost::enable_if_c<!boost::is_base_of<base_series_tag,FinalCf>::value>::type>
59         {
60                 static const int value = 0;
61         };
62
63         // Struct to define the container used in series - like a template typedef.
64         template <class Term>
65         struct series_container
66         {
67                 typedef boost::unordered_set<Term,boost::hash<Term>,std::equal_to<Term>,counting_allocator<Term,std::allocator<char> > > type;
68         };
69
70         // These accessors are used in generic code that must work on both plain series (i.e., iterators) and sorted representations
71         // of series as returned by get_sorted_series (i.e., pointers to pointers of terms).
72         template <class Iterator>
73         struct it_getter
74         {
75                 static const Iterator &get(const Iterator &it)
76                 {
77                         return it;
78                 }
79         };
80
81         template <class TermPointer>
82         struct it_getter<TermPointer *>
83         {
84                 static const TermPointer get(const TermPointer *p)
85                 {
86                         return *p;
87                 }
88         };
89
90         /// Base series class.
91         /**
92          * This class provides the basic representation of a series as a collection of terms stored into a hash set. The class is intended
93          * to be inherited together with (at least) either piranha::named_series (for a top-level series) or piranha::cf_series (for a coefficient series).
94          *
95          * The methods in this class provide the lowest level of series manipulation, and allow to operate directly on the individual terms of the
96          * series.
97          *
98          * @author Francesco Biscani (bluescarni@gmail.com)
99          */
100         template <__PIRANHA_BASE_SERIES_TP_DECL>
101         class base_series: base_series_tag
102         {
103                         // Befriend meta-programming classes.
104                         template <class RequestedCf, class SeriesCf>
105                         friend struct series_from_cf_impl;
106                         template <class RequestedKey, class SeriesKey>
107                         friend struct series_from_key_impl;
108                         template <int N>
109                         friend class series_flattener;
110                 public:
111                         /// Alias for term type.
112                         typedef Term term_type;
113                         /// Term container.
114                         /**
115                          * The underlying term container is a plain boost::unordered set. Term types must specialise the boost::hash class, which
116                          * will be used to provide the hash values for terms.
117                          */
118                         typedef typename series_container<term_type>::type container_type;
119                         /// Echelon level.
120                         static const int echelon_level = echelon_level_impl<typename term_type::cf_type>::value;
121                         /// Type resulting from series evaluation.
122                         /**
123                          * Determined automatically at compile time. Will be double in case of series with scalar coefficients,
124                          * std::complex<double> in case of series with complex coefficients.
125                          */
126                         typedef typename term_eval_type_determiner<Term>::type eval_type;
127                         /// Term separator in textual series representation.
128                         static const char separator = Separator;
129                         /// Const iterator over the series' terms.
130                         typedef typename container_type::const_iterator const_iterator;
131                         /// Size type.
132                         typedef typename container_type::size_type size_type;
133                         /** @name Series properties. */
134                         //@{
135                         size_type length() const;
136                         bool empty() const;
137                         bool is_single_cf() const;
138                         size_type atoms() const;
139                         //@}
140                 //protected:
141                         /** @name Construction/destruction. */
142                         //@{
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                         template <class Number, class ArgsTuple>
148                         static Derived base_series_from_number(const Number &, const ArgsTuple &);
149                         template <class ArgsTuple>
150                         void base_construct_from_psym(const psym &, const int &, const ArgsTuple &);
151                         ~base_series();
152                         //@}
153                         /** @name Series manipulation. */
154                         //@{
155                         void erase_term(const const_iterator &);
156                         void clear_terms();
157                         template <bool, bool, class Term2, class ArgsTuple>
158                         void insert(const Term2 &, const ArgsTuple &);
159                         template <class Term2, class ArgsTuple>
160                         void insert(const Term2 &, const ArgsTuple &);
161                         template <class Iterator, class ArgsTuple>
162                         void insert_range(const Iterator &, const Iterator &, const ArgsTuple &);
163                         void base_swap(Derived &);
164                         template <class Series, class ArgsTuple>
165                         void base_split(std::vector<std::vector<Series> > &, const int &n, const ArgsTuple &) const;
166                         template <class ArgsTuple>
167                         std::vector<term_type> flatten_terms(const ArgsTuple &) const;
168                         template <class Layout, class ArgsTuple>
169                         void apply_layout_to_terms(const Layout &, Derived &, const ArgsTuple &) const;
170                         template <bool, class Derived2, class ArgsTuple>
171                         Derived &merge_terms(const Derived2 &, const ArgsTuple &);
172                         template <class TrimFlags>
173                         void trim_test_terms(TrimFlags &) const;
174                         template <class TrimFlags, class ArgsTuple>
175                         void trim_terms(const TrimFlags &, Derived &, const ArgsTuple &) const;
176                         template <class RetSeries, class SubFunctor, class PosTuple, class SubCaches, class ArgsTuple>
177                         RetSeries base_sub(const PosTuple &, SubCaches &, const ArgsTuple &) const;
178                         template <bool, class Number, class ArgsTuple>
179                         Derived &merge_with_number(const Number &, const ArgsTuple &);
180                         //@}
181                         /** @name Terms accessors. */
182                         //@{
183                         const_iterator find_term(const term_type &) const;
184                         const_iterator begin() const;
185                         const_iterator end() const;
186                         //@}
187                         /** @name Base comparison methods. */
188                         //@{
189                         bool base_equal_to(const Derived &) const;
190                         bool base_equal_to(const double &) const;
191                         bool base_equal_to(const mp_rational &) const;
192                         bool base_equal_to(const mp_integer &) const;
193                         template <class Number>
194                         bool generic_numerical_comparison(const Number &) const;
195                         //@}
196                         /** @name Base maths. */
197                         //@{
198                         template <class T, class ArgsTuple>
199                         void multiply_coefficients_by(const T &, const ArgsTuple &);
200                         template <class T, class ArgsTuple>
201                         void divide_coefficients_by(const T &, const ArgsTuple &);
202                         template <class ArgsTuple>
203                         double base_norm(const ArgsTuple &) const;
204                         template <class ArgsTuple>
205                         eval_type base_eval(const double &, const ArgsTuple &) const;
206                         template <class ArgsTuple>
207                         Derived &base_add(const Derived &, const ArgsTuple &);
208                         template <class ArgsTuple>
209                         Derived &base_add(const double &, const ArgsTuple &);
210                         template <class ArgsTuple>
211                         Derived &base_add(const mp_rational &, const ArgsTuple &);
212                         template <class ArgsTuple>
213                         Derived &base_add(const mp_integer &, const ArgsTuple &);
214                         template <class ArgsTuple>
215                         Derived &base_subtract(const double &, const ArgsTuple &);
216                         template <class ArgsTuple>
217                         Derived &base_subtract(const mp_rational &, const ArgsTuple &);
218                         template <class ArgsTuple>
219                         Derived &base_subtract(const mp_integer &, const ArgsTuple &);
220                         template <class ArgsTuple>
221                         Derived &base_subtract(const Derived &, const ArgsTuple &);
222                         template <class ArgsTuple>
223                         Derived &base_mult_by(const double &, const ArgsTuple &);
224                         template <class ArgsTuple>
225                         Derived &base_mult_by(const mp_rational &, const ArgsTuple &);
226                         template <class ArgsTuple>
227                         Derived &base_mult_by(const mp_integer &, const ArgsTuple &);
228                         template <class ArgsTuple>
229                         Derived &base_mult_by(const Derived &, const ArgsTuple &);
230                         template <class ArgsTuple>
231                         Derived &base_divide_by(const double &, const ArgsTuple &);
232                         template <class ArgsTuple>
233                         Derived &base_divide_by(const mp_rational &, const ArgsTuple &);
234                         template <class ArgsTuple>
235                         Derived &base_divide_by(const mp_integer &, const ArgsTuple &);
236                         template <class ArgsTuple>
237                         Derived base_inv(const ArgsTuple &) const;
238                         template <class ArgsTuple>
239                         Derived base_pow(const double &, const ArgsTuple &) const;
240                         template <class ArgsTuple>
241                         Derived base_pow(const mp_rational &, const ArgsTuple &) const;
242                         template <class ArgsTuple>
243                         Derived natural_power(const std::size_t &, const ArgsTuple &) const;
244                         template <class ArgsTuple>
245                         Derived negative_integer_power(const int &, const ArgsTuple &) const;
246                         template <class ArgsTuple>
247                         Derived real_power(const double &, const ArgsTuple &) const;
248                         template <class ArgsTuple>
249                         Derived rational_power(const mp_rational &, const ArgsTuple &) const;
250                         template <class ArgsTuple>
251                         Derived base_root(const int &, const ArgsTuple &) const;
252                         template <class Series, class PosTuple, class ArgsTuple>
253                         static void base_partial(const Derived &, Series &, const PosTuple &, const ArgsTuple &);
254                         template <class PosTuple, class ArgsTuple>
255                         Derived base_partial(int, const PosTuple &, const ArgsTuple &) const;
256                         template <class PosTuple, class ArgsTuple>
257                         Derived base_partial(const PosTuple &, const ArgsTuple &) const;
258                         //@}
259                         /** @name Base output streaming methods. */
260                         //@{
261                         template <class ArgsTuple>
262                         void print_terms_plain(std::ostream &, const ArgsTuple &) const;
263                         template <class ArgsTuple>
264                         void print_terms_tex(std::ostream &, const ArgsTuple &) const;
265                         template <class ArgsTuple>
266                         void print_terms_pretty(std::ostream &, const ArgsTuple &) const;
267                         //@}
268                         // Standard substitution functor. Will call sub() on coefficients and keys.
269                         struct sub_functor {
270                                 template <class RetSeries, class Element, class PosTuple, class SubCaches, class ArgsTuple>
271                                 static RetSeries run(const Element &e, const PosTuple &pos_tuple,
272                                         SubCaches &sub_caches, const ArgsTuple &args_tuple)
273                                 {
274                                         return e.template sub<RetSeries>(pos_tuple, sub_caches, args_tuple);
275                                 }
276                         };
277                 private:
278                         template <class Iterator, class ArgsTuple>
279                         void generic_print_terms_pretty(std::ostream &, const Iterator &, const Iterator &, const ArgsTuple &) const;
280                         template <class Iterator, class ArgsTuple>
281                         void generic_print_terms_tex(std::ostream &, const Iterator &, const Iterator &, const ArgsTuple &) const;
282                         template <class Iterator, class Series, class ArgsTuple>
283                         void generic_base_split(std::vector<std::vector<Series> > &, const Iterator &, const Iterator &, const ArgsTuple &) const;
284                         template <bool, class ArgsTuple>
285                         void ll_insert(const term_type &, const ArgsTuple &);
286                         template <bool, class ArgsTuple>
287                         void term_insert_new(const term_type &, const ArgsTuple &);
288                         template <int, class T, class ArgsTuple>
289                         void mult_div_coefficients_by(const T &, const ArgsTuple &);
290                         template <class Number, class ArgsTuple>
291                         Derived &multiply_by_number(const Number &, const ArgsTuple &);
292                         template <class Number, class ArgsTuple>
293                         Derived &divide_by_number(const Number &, const ArgsTuple &);
294                         template <class Number, class ArgsTuple>
295                         bool common_pow_handler(const Number &, Derived &retval, const ArgsTuple &) const;
296                 private:
297                         container_type m_container;
298         };
299
300 #define E0_SERIES_TP_DECL class Cf, class Key, class Multiplier, class Truncator, class Allocator
301 #define E0_SERIES_TP Cf,Key,Multiplier,Truncator,Allocator
302 #define E0_SERIES_TERM(term_name) term_name<Cf,Key,'|',Allocator>
303 #define E0_SERIES(series_name) series_name<E0_SERIES_TP>
304 #define E0_SERIES_BASE_ANCESTOR(term_name,series_name) piranha::base_series<E0_SERIES_TERM(term_name),'\n', \
305         Allocator,E0_SERIES(series_name) >
306
307 #define E1_SERIES_TP_DECL class Cf, class Key0, class Key1, \
308                                                 class Mult0, class Mult1, class Trunc0, class Trunc1, class Allocator
309 #define E1_SERIES_TP Cf,Key0,Key1,Mult0,Mult1,Trunc0,Trunc1,Allocator
310 #define E1_SERIES_COEFFICIENT(cf_name) cf_name<Cf,Key0,Mult0,Trunc0,Allocator>
311 #define E1_SERIES(series_name) series_name<E1_SERIES_TP>
312 #define E1_SERIES_TERM(term_name,cf_name) term_name< cf_name, Key1, '|', Allocator >
313 #define E1_SERIES_BASE_ANCESTOR(term_name,cf_name,series_name) piranha::base_series<term_name< \
314         cf_name,Key1,'|',Allocator>, \
315         '\n',Allocator,series_name >
316 }
317
318 #endif