Dropped pollution of std namespace.
[piranha:mainline.git] / src / core / base_classes / numerical_container.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_NUMERICAL_CONTAINER_H
22 #define PIRANHA_NUMERICAL_CONTAINER_H
23
24 #include <algorithm>
25 #include <cmath>
26 #include <complex>
27 #include <cstddef>
28 #include <iostream>
29 #include <string>
30 #include <vector>
31
32 #include "../config.h"
33 #include "../math.h"
34 #include "../mp.h"
35 #include "../null_type.h"
36 #include "../psym.h"
37 #include "../settings.h"
38 #include "../utils.h" // Lexical converter.
39 #include "numerical_container_complex_toolbox.h"
40
41 // Convenience macros.
42 #define derived_const_cast static_cast<Derived const *>(this)
43 #define derived_cast static_cast<Derived *>(this)
44
45 namespace piranha
46 {
47         template <class T>
48         struct numerical_container_eval_type_determiner
49         {
50                 typedef double type;
51         };
52
53         template <class T>
54         struct numerical_container_eval_type_determiner<std::complex<T> >
55         {
56                 typedef std::complex<double> type;
57         };
58
59         template <class T, class U>
60         struct in_place_transform {
61                 static const U &run(const U &u)
62                 {
63                         return u;
64                 }
65         };
66
67         /// Numerical container class.
68         /**
69          * This class can be used as a base class for coefficients that consist of a
70          * numerical entity (double, MP classes, etc.).
71          */
72         template <class T, class Derived>
73         class numerical_container
74         {
75                         friend class numerical_container_complex_toolbox<Derived>;
76                 public:
77                         /// Typedef for evaluation type.
78                         typedef typename numerical_container_eval_type_determiner<T>::type eval_type;
79                         /// Alias for internal type.
80                         typedef T numerical_type;
81                         /// Numerical coefficient is a terminator for echelon recursion.
82                         typedef null_type next_echelon_type;
83                         template <class, class SubCachesCons, class>
84                         struct sub_cache_selector {
85                                 typedef SubCachesCons type;
86                         };
87                         template <class, class SubCachesCons, class>
88                         struct ei_sub_cache_selector {
89                                 typedef SubCachesCons type;
90                         };
91                         /// Default constructor, initialises internal value to 0.
92                         explicit numerical_container(): m_value(0) {}
93                         /// Constructor from string.
94                         /**
95                          * Will call boost::lexical_converter internally.
96                          */
97                         template <class ArgsTuple>
98                         explicit numerical_container(const std::string &s, const ArgsTuple &):
99                                 m_value(utils::lexical_converter<T>(s)) {}
100                         /// Constructor from double.
101                         template <class ArgsTuple>
102                         explicit numerical_container(const double &x, const ArgsTuple &): m_value(x) {}
103                         /// Constructor from piranha::mp_rational.
104                         template <class ArgsTuple>
105                         explicit numerical_container(const mp_rational &q, const ArgsTuple &): m_value(q) {}
106                         /// Constructor from piranha::mp_integer.
107                         template <class ArgsTuple>
108                         explicit numerical_container(const mp_integer &z, const ArgsTuple &): m_value(z) {}
109                         /// Ctor from psym.
110                         /**
111                          * Sets internal value to one.
112                          */
113                         template <class ArgsTuple>
114                         explicit numerical_container(const psym &, const int &, const ArgsTuple &): m_value(1) {}
115                         /// Print in plain mode.
116                         template <class ArgsTuple>
117                         void print_plain(std::ostream &out_stream, const ArgsTuple &) const {
118                                 out_stream << m_value;
119                         }
120                         /// Print in pretty mode. Equivalent to print_plain.
121                         template <class ArgsTuple>
122                         void print_pretty(std::ostream &out_stream, const ArgsTuple &args_tuple) const {
123                                 print_plain(out_stream,args_tuple);
124                         }
125                         /// Print in Tex mode.
126                         template <class ArgsTuple>
127                         void print_tex(std::ostream &out_stream, const ArgsTuple &) const {
128                                 out_stream << ' ' << m_value << ' ';
129                         }
130                         /// Swap content using std::swap.
131                         Derived &swap(Derived &dc) {
132                                 std::swap(m_value, dc.m_value);
133                                 return *derived_cast;
134                         }
135                         /// Pad right.
136                         template <class ArgsTuple>
137                         void pad_right(const ArgsTuple &) {}
138                         /// Apply layout.
139                         template <class Layout, class ArgsTuple>
140                         void apply_layout(const Layout &, const ArgsTuple &) {}
141                         /// Test if trimming is possible.
142                         template <class TrimFlags>
143                         void trim_test(TrimFlags &) const {}
144                         /// Trim.
145                         template <class TrimFlags, class ArgsTuple>
146                         Derived trim(const TrimFlags &, const ArgsTuple &) const {
147                                 return *derived_const_cast;
148                         }
149                         /// Split.
150                         template <class Series, class ArgsTuple>
151                         void split(std::vector<std::vector<Series> > &, const int &, const ArgsTuple &) const
152                         {
153                                 piranha_assert(false);
154                         }
155                         /// Number of atoms. Returns 1.
156                         std::size_t atoms() const {
157                                 return 1;
158                         }
159                         /// Norm. Returns std::abs of internal value.
160                         template <class ArgsTuple>
161                         double norm(const ArgsTuple &) const {
162                                 return std::abs(m_value);
163                         }
164                         /// Test for ignorability.
165                         /**
166                          * Returns true if norm() is less than settings::get_numerical_zero().
167                          */
168                         template <class ArgsTuple>
169                         bool is_ignorable(const ArgsTuple &a) const {
170                                 return (derived_const_cast->norm(a) < settings::get_numerical_zero());
171                         }
172                         /// Insertability test. Returns true.
173                         template <class ArgsTuple>
174                         bool is_insertable(const ArgsTuple &) const {
175                                 return true;
176                         }
177                         /// Padding test. Returns false.
178                         template <class ArgsTuple>
179                         bool needs_padding(const ArgsTuple &) const {
180                                 return false;
181                         }
182                         template <class ArgsTuple>
183                         const T &eval(const double &, const ArgsTuple &) const {
184                                 return m_value;
185                         }
186                         bool operator==(const Derived &other) const {
187                                 return (m_value == other.m_value);
188                         }
189                         bool operator==(const double &x) const {
190                                 return (m_value == x);
191                         }
192                         bool operator==(const mp_rational &q) const {
193                                 return (m_value == q);
194                         }
195                         bool operator==(const mp_integer &z) const {
196                                 return (m_value == z);
197                         }
198                         // Maths.
199                         template <class ArgsTuple>
200                         void invert_sign(const ArgsTuple &) {
201                                 m_value *= -1;
202                         }
203                         template <class ArgsTuple>
204                         Derived &add(const Derived &val2, const ArgsTuple &) {
205                                 return add_generic(val2.value());
206                         }
207                         template <class ArgsTuple>
208                         Derived &subtract(const Derived &val2, const ArgsTuple &) {
209                                 return subtract_generic(val2.value());
210                         }
211                         template <class ArgsTuple>
212                         Derived &mult_by(const double &x, const ArgsTuple &) {
213                                 return mult_by_generic(x);
214                         }
215                         template <class ArgsTuple>
216                         Derived &mult_by(const mp_rational &q, const ArgsTuple &) {
217                                 return mult_by_generic(q);
218                         }
219                         template <class ArgsTuple>
220                         Derived &mult_by(const mp_integer &z, const ArgsTuple &) {
221                                 return mult_by_generic(z);
222                         }
223                         template <class ArgsTuple>
224                         Derived &mult_by(const Derived &x, const ArgsTuple &) {
225                                 return mult_by_generic(x.value());
226                         }
227                         template <class ArgsTuple>
228                         Derived &divide_by(const double &x, const ArgsTuple &) {
229                                 return divide_by_generic(x);
230                         }
231                         template <class ArgsTuple>
232                         Derived &divide_by(const mp_rational &q, const ArgsTuple &) {
233                                 return divide_by_generic(q);
234                         }
235                         template <class ArgsTuple>
236                         Derived &divide_by(const mp_integer &z, const ArgsTuple &) {
237                                 return divide_by_generic(z);
238                         }
239                         // Multiply and add.
240                         template <class Derived2, class ArgsTuple>
241                         void addmul(const Derived &x1, const Derived2 &x2, const ArgsTuple &) {
242                                 multiply_accumulate(m_value,x1.m_value,x2.value());
243                         }
244                         template <class Series, class PosTuple, class ArgsTuple>
245                         Series partial(const PosTuple &, const ArgsTuple &) const {
246                                 return Series();
247                         }
248                         template <class ArgsTuple>
249                         Derived pow(const double &x, const ArgsTuple &args_tuple) const {
250                                 return generic_pow(x,args_tuple);
251                         }
252                         template <class ArgsTuple>
253                         Derived pow(const mp_rational &q, const ArgsTuple &args_tuple) const {
254                                 return generic_pow(q,args_tuple);
255                         }
256                         template <class ArgsTuple>
257                         Derived besselJ(const int &, const ArgsTuple &) const {
258                                 piranha_throw(not_implemented_error,
259                                         "besselJ is not implemented for this coefficient type");
260                         }
261                         template <class RetSeries, class PosTuple, class SubCaches, class ArgsTuple>
262                         RetSeries sub(const PosTuple &, SubCaches &, const ArgsTuple &args_tuple) const {
263                                 return RetSeries::base_series_from_cf(*derived_const_cast, args_tuple);
264                         }
265                         template <class RetSeries, class PosTuple, class SubCaches, class ArgsTuple>
266                         RetSeries ei_sub(const PosTuple &p, SubCaches &s, const ArgsTuple &a) const {
267                                 return sub<RetSeries>(p,s,a);
268                         }
269                         /// Get value.
270                         const T &value() const {
271                                 return m_value;
272                         }
273                         /// Set value.
274                         T &value() {
275                                 return m_value;
276                         }
277                 protected:
278                         template <class U>
279                         Derived &assign_self(const U &x) {
280                                 m_value = x.value();
281                                 return *derived_cast;
282                         }
283                         template <class U>
284                         Derived &add_generic(const U &x) {
285                                 m_value += in_place_transform<T,U>::run(x);
286                                 return *derived_cast;
287                         }
288                         template <class U>
289                         Derived &subtract_generic(const U &x) {
290                                 m_value -= in_place_transform<T,U>::run(x);
291                                 return *derived_cast;
292                         }
293                         template <class U>
294                         Derived &mult_by_generic(const U &x) {
295                                 m_value *= in_place_transform<T,U>::run(x);
296                                 return *derived_cast;
297                         }
298                         template <class U>
299                         Derived &divide_by_generic(const U &x) {
300                                 m_value /= in_place_transform<T,U>::run(x);
301                                 return *derived_cast;
302                         }
303                         template <class Number, class ArgsTuple>
304                         Derived generic_pow(const Number &n, const ArgsTuple &) const {
305                                 // COMPILER BUG: usual stuff with ubuntu's 4.1.3 compiler :(
306                                 Derived retval;
307                                 const numerical_type tmp(std::pow(m_value,n));
308                                 retval.m_value = tmp;
309                                 return retval;
310                         }
311                 protected:
312                         T m_value;
313         };
314
315         #define NUMERICAL_CONTAINER_CTORS(derived,...) \
316         explicit derived(): ancestor() {} \
317         template <class ArgsTuple> \
318         explicit derived(const std::string &s, const ArgsTuple &a): ancestor(s, a) {} \
319         template <class ArgsTuple> \
320         explicit derived(const double &val, const ArgsTuple &a): ancestor(val, a) {} \
321         template <class ArgsTuple> \
322         explicit derived(const piranha::mp_rational &val, const ArgsTuple &a): ancestor(val __VA_ARGS__ , a) {} \
323         template <class ArgsTuple> \
324         explicit derived(const piranha::mp_integer &val, const ArgsTuple &a): ancestor(val __VA_ARGS__ , a) {} \
325         template <class ArgsTuple> \
326         explicit derived(const piranha::psym &p, const int &n, const ArgsTuple &a): ancestor(p, n, a) {}
327
328         // Overloads for I/O operators.
329         template <class T, class Derived>
330         inline std::istream &operator>>(std::istream &is, numerical_container<T, Derived> &nc)
331         {
332                 std::string tmp;
333                 std::getline(is, tmp);
334                 nc = numerical_container<T, Derived>(utils::lexical_converter<T>(tmp));
335                 return is;
336         }
337
338         template <class T, class Derived>
339         inline std::ostream &operator<<(std::ostream &os, const numerical_container<T, Derived> &nc)
340         {
341                 os << nc.value();
342                 return os;
343         }
344 }
345
346 #undef derived_const_cast
347 #undef derived_cast
348
349 #endif