1 /* Copyright 2009-2016 Francesco Biscani (bluescarni@gmail.com)
2
3 This file is part of the Piranha library.
4
5 The Piranha library is free software; you can redistribute it and/or modify
6 it under the terms of either:
7
8 * the GNU Lesser General Public License as published by the Free
9 Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
11
12 or
13
14 * the GNU General Public License as published by the Free Software
15 Foundation; either version 3 of the License, or (at your option) any
16 later version.
17
18 or both in parallel, as here.
19
20 The Piranha library is distributed in the hope that it will be useful, but
21 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
22 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
23 for more details.
24
25 You should have received copies of the GNU General Public License and the
26 GNU Lesser General Public License along with the Piranha library. If not,
27 see https://www.gnu.org/licenses/. */
28
29 #include "../src/power_series.hpp"
30
31 #define BOOST_TEST_MODULE power_series_01_test
32 #include <boost/test/included/unit_test.hpp>
33
34 #include <boost/mpl/for_each.hpp>
35 #include <boost/mpl/vector.hpp>
36 #include <string>
37 #include <type_traits>
38 #include <vector>
39
40 #include "../src/init.hpp"
41 #include "../src/math.hpp"
42 #include "../src/monomial.hpp"
43 #include "../src/mp_integer.hpp"
44 #include "../src/mp_rational.hpp"
45 #include "../src/poisson_series.hpp"
46 #include "../src/polynomial.hpp"
47 #include "../src/real.hpp"
48 #include "../src/real_trigonometric_kronecker_monomial.hpp"
49 #include "../src/series.hpp"
50
51 using namespace piranha;
52
53 typedef boost::mpl::vector<double, integer> cf_types;
54 typedef boost::mpl::vector<int, integer> expo_types;
55
56 template <typename Cf, typename Expo>
57 class g_series_type : public power_series<series<Cf, monomial<Expo>, g_series_type<Cf, Expo>>, g_series_type<Cf, Expo>>
58 {
59 using base = power_series<series<Cf, monomial<Expo>, g_series_type<Cf, Expo>>, g_series_type<Cf, Expo>>;
60
61 public:
62 g_series_type() = default;
63 g_series_type(const g_series_type &) = default;
64 g_series_type(g_series_type &&) = default;
65 g_series_type &operator=(const g_series_type &) = default;
66 g_series_type &operator=(g_series_type &&) = default;
67 PIRANHA_FORWARDING_CTOR(g_series_type, base)
68 PIRANHA_FORWARDING_ASSIGNMENT(g_series_type, base)
69 };
70
71 template <typename Cf>
72 class g_series_type2 : public power_series<series<Cf, rtk_monomial, g_series_type2<Cf>>, g_series_type2<Cf>>
73 {
74 typedef power_series<series<Cf, rtk_monomial, g_series_type2<Cf>>, g_series_type2<Cf>> base;
75
76 public:
77 g_series_type2() = default;
78 g_series_type2(const g_series_type2 &) = default;
79 g_series_type2(g_series_type2 &&) = default;
80 g_series_type2 &operator=(const g_series_type2 &) = default;
81 g_series_type2 &operator=(g_series_type2 &&) = default;
82 PIRANHA_FORWARDING_CTOR(g_series_type2, base)
83 PIRANHA_FORWARDING_ASSIGNMENT(g_series_type2, base)
84 };
85
86 struct degree_tester {
87 template <typename Cf>
88 struct runner {
89 template <typename Expo>
operator ()degree_tester::runner90 void operator()(const Expo &)
91 {
92 typedef polynomial<Cf, monomial<Expo>> p_type1;
93 typedef polynomial<polynomial<Cf, monomial<Expo>>, monomial<Expo>> p_type11;
94 using deg_type = typename std::conditional<std::is_same<Expo, int>::value, int, integer>::type;
95 BOOST_CHECK((std::is_same<deg_type, decltype(math::degree(p_type1{}))>::value));
96 BOOST_CHECK((std::is_same<deg_type, decltype(math::degree(p_type1{}, std::vector<std::string>{}))>::value));
97 BOOST_CHECK((std::is_same<deg_type, decltype(math::ldegree(p_type1{}))>::value));
98 BOOST_CHECK(
99 (std::is_same<deg_type, decltype(math::ldegree(p_type1{}, std::vector<std::string>{}))>::value));
100 BOOST_CHECK(math::degree(p_type1{}) == 0);
101 BOOST_CHECK(math::degree(p_type1{}, std::vector<std::string>{}) == 0);
102 BOOST_CHECK(math::ldegree(p_type1{}) == 0);
103 BOOST_CHECK(math::ldegree(p_type1{}, std::vector<std::string>{}) == 0);
104 BOOST_CHECK(math::degree(p_type1{"x"}) == 1);
105 BOOST_CHECK(math::degree(p_type1{"x"}, {"x"}) == 1);
106 BOOST_CHECK(math::degree(p_type1{"x"}, {"y"}) == 0);
107 BOOST_CHECK(math::ldegree(p_type1{"x"}) == 1);
108 BOOST_CHECK(math::ldegree(p_type1{"x"}, {"x"}) == 1);
109 BOOST_CHECK(math::ldegree(p_type1{"x"}, {"y"}) == 0);
110 BOOST_CHECK(math::degree(p_type1{"x"} * p_type1{"x"}) == 2);
111 BOOST_CHECK(math::degree(p_type1{"x"} * p_type1{"x"}, {"x"}) == 2);
112 BOOST_CHECK(math::degree(p_type1{"x"} * p_type1{"y"}, {"y"}) == 1);
113 BOOST_CHECK(math::ldegree(p_type1{"x"} * p_type1{"x"}) == 2);
114 BOOST_CHECK(math::ldegree(p_type1{"x"} * p_type1{"x"}, {"x"}) == 2);
115 BOOST_CHECK(math::ldegree(p_type1{"x"} * p_type1{"y"}, {"y"}) == 1);
116 BOOST_CHECK(math::degree(p_type1{"x"} + p_type1{"y"} + p_type1{1}) == 1);
117 BOOST_CHECK(math::degree(p_type1{"x"} + p_type1{"y"} + p_type1{1}, {"x"}) == 1);
118 BOOST_CHECK(math::degree(p_type1{"x"} + p_type1{"y"} + p_type1{1}, {"x"}) == 1);
119 BOOST_CHECK(math::degree(p_type1{"x"} + p_type1{"y"} + p_type1{1}, {"y"}) == 1);
120 BOOST_CHECK(math::degree(p_type1{"x"} + p_type1{"y"} + p_type1{1}, {"y"}) == 1);
121 BOOST_CHECK(math::degree(p_type1{"x"} + p_type1{"y"} + p_type1{1}, {"z"}) == 0);
122 BOOST_CHECK(math::degree(p_type1{"x"} + p_type1{"y"} + p_type1{1}, {"z"}) == 0);
123 BOOST_CHECK(math::ldegree(p_type1{"x"} + p_type1{"y"} + p_type1{1}) == 0);
124 BOOST_CHECK(math::ldegree(p_type1{"x"} + p_type1{"y"} + p_type1{1}, {"x"}) == 0);
125 BOOST_CHECK(math::ldegree(p_type1{"x"} + p_type1{"y"} + p_type1{1}, {"x"}) == 0);
126 BOOST_CHECK(math::ldegree(p_type1{"x"} + p_type1{"y"} + p_type1{1}, {"y"}) == 0);
127 BOOST_CHECK(math::ldegree(p_type1{"x"} + p_type1{"y"} + p_type1{1}, {"y"}) == 0);
128 BOOST_CHECK(math::ldegree(p_type1{"x"} + p_type1{"y"} + p_type1{1}, {"z"}) == 0);
129 BOOST_CHECK(math::ldegree(p_type1{"x"} + p_type1{"y"} + p_type1{1}, {"z"}) == 0);
130 BOOST_CHECK(math::ldegree(p_type1{"x"} * p_type1{"x"} + p_type1{"y"} + p_type1{"x"}) == 1);
131 BOOST_CHECK(math::ldegree(p_type1{"x"} * p_type1{"x"} + p_type1{"y"} + p_type1{"x"}, {"x"}) == 0);
132 BOOST_CHECK(math::ldegree(p_type1{"x"} * p_type1{"x"} + p_type1{"y"} + p_type1{"x"}, {"x"}) == 0);
133 BOOST_CHECK(math::ldegree(p_type1{"x"} * p_type1{"x"} + 2 * p_type1{"x"}, {"x"}) == 1);
134 BOOST_CHECK(math::ldegree(p_type1{"x"} * p_type1{"y"} + 2 * p_type1{"x"}, {"x"}) == 1);
135 BOOST_CHECK(math::ldegree(p_type1{"x"} * p_type1{"y"} + 2 * p_type1{"x"}, {"y"}) == 0);
136 std::vector<std::string> empty_set;
137 BOOST_CHECK((std::is_same<decltype(math::degree(std::declval<const p_type11 &>())), deg_type>::value));
138 BOOST_CHECK(
139 (std::is_same<decltype(math::degree(std::declval<const p_type11 &>(), empty_set)), deg_type>::value));
140 BOOST_CHECK((std::is_same<decltype(math::ldegree(std::declval<const p_type11 &>())), deg_type>::value));
141 BOOST_CHECK(
142 (std::is_same<decltype(math::ldegree(std::declval<const p_type11 &>(), empty_set)), deg_type>::value));
143 BOOST_CHECK(math::degree(p_type11{"x"} * p_type1{"y"} + 2 * p_type1{"y"}) == 2);
144 BOOST_CHECK(math::degree(p_type11{"x"} * p_type1{"y"} + 2 * p_type1{"y"}, {"x"}) == 1);
145 BOOST_CHECK(math::degree(p_type11{"x"} * p_type1{"y"} + 2 * p_type1{"y"}, {"x"}) == 1);
146 BOOST_CHECK(math::degree(p_type11{"x"} * p_type1{"y"} + 2 * p_type1{"y"}, {"y"}) == 1);
147 BOOST_CHECK(math::ldegree(p_type11{"x"} * p_type1{"y"} + 2 * p_type1{"y"}) == 1);
148 BOOST_CHECK(math::ldegree(p_type11{"x"} * p_type1{"y"} + 2 * p_type1{"y"}, {"y"}) == 1);
149 BOOST_CHECK(math::ldegree(p_type11{"x"} * p_type1{"y"} + 2 * p_type1{"y"}, {"y"}) == 1);
150 BOOST_CHECK(math::ldegree(p_type11{"x"} * p_type1{"y"} + 2 * p_type1{"y"}, {"z"}) == 0);
151 BOOST_CHECK(math::ldegree(p_type11{"x"} * p_type1{"y"} + 2 * p_type1{"y"}, {"z"}) == 0);
152 BOOST_CHECK(math::ldegree(p_type11{"x"} * p_type1{"y"} + 2 * p_type1{"y"} + 1) == 0);
153 BOOST_CHECK(math::ldegree(p_type11{"x"} * p_type1{"y"} + 2 * p_type1{"y"} + 1, {"x"}) == 0);
154 BOOST_CHECK(math::ldegree(p_type11{"x"} * p_type1{"y"} + 2 * p_type1{"y"} + 1, {"y"}) == 0);
155 BOOST_CHECK(math::degree(p_type11{"x"} * p_type1{"y"} * p_type1{"y"} + 2 * p_type1{"y"} + 1) == 3);
156 BOOST_CHECK(math::degree(p_type11{"x"} * p_type1{"y"} * p_type1{"y"} + 2 * p_type1{"y"} + 1, {"x"}) == 1);
157 BOOST_CHECK(math::degree(p_type11{"x"} * p_type1{"y"} * p_type1{"y"} + 2 * p_type1{"y"} + 1, {"y"}) == 2);
158 BOOST_CHECK(math::degree(p_type11{"x"} * p_type1{"y"} * p_type1{"y"} + 2 * p_type1{"y"} + 1, {"y"}) == 2);
159 BOOST_CHECK(math::ldegree(p_type11{"x"} * p_type1{"y"} * p_type1{"y"} + 2 * p_type1{"y"} + 1) == 0);
160 BOOST_CHECK(math::ldegree(p_type11{"x"} * p_type1{"y"} * p_type1{"y"} + 2 * p_type1{"y"}, {"x"}) == 0);
161 BOOST_CHECK(math::ldegree(p_type11{"x"} * p_type1{"y"} * p_type1{"y"} + 2 * p_type1{"y"}, {"y"}) == 1);
162 BOOST_CHECK(math::ldegree(p_type11{"x"} * p_type1{"y"} * p_type1{"y"} + 2 * p_type1{"y"}, {"y"}) == 1);
163 // Test the type traits.
164 BOOST_CHECK(has_degree<p_type1>::value);
165 BOOST_CHECK(has_degree<p_type11>::value);
166 BOOST_CHECK(has_ldegree<p_type1>::value);
167 BOOST_CHECK(has_ldegree<p_type11>::value);
168 // Poisson series tests.
169 typedef poisson_series<p_type1> pstype1;
170 BOOST_CHECK(has_degree<pstype1>::value);
171 BOOST_CHECK(has_ldegree<pstype1>::value);
172 typedef poisson_series<Cf> pstype2;
173 BOOST_CHECK(!has_degree<pstype2>::value);
174 BOOST_CHECK(!has_ldegree<pstype2>::value);
175 BOOST_CHECK((std::is_same<deg_type, decltype(math::degree(pstype1{}))>::value));
176 BOOST_CHECK((std::is_same<deg_type, decltype(math::degree(pstype1{}, std::vector<std::string>{}))>::value));
177 BOOST_CHECK((std::is_same<deg_type, decltype(math::ldegree(pstype1{}))>::value));
178 BOOST_CHECK(
179 (std::is_same<deg_type, decltype(math::ldegree(pstype1{}, std::vector<std::string>{}))>::value));
180 // As usual, operations on Poisson series with (polynomial) integer coefficients are not gonna give
181 // meaningful mathematical results.
182 if (std::is_same<Cf, integer>::value) {
183 return;
184 }
185 BOOST_CHECK(math::degree(pstype1{}) == 0);
186 BOOST_CHECK(math::degree(pstype1{}, std::vector<std::string>{}) == 0);
187 BOOST_CHECK(math::ldegree(pstype1{}) == 0);
188 BOOST_CHECK(math::ldegree(pstype1{}, std::vector<std::string>{}) == 0);
189 BOOST_CHECK(math::degree(pstype1{"x"}) == 1);
190 BOOST_CHECK(math::degree(pstype1{"x"}, {"x"}) == 1);
191 BOOST_CHECK(math::degree(pstype1{"x"}, {"y"}) == 0);
192 BOOST_CHECK(math::ldegree(pstype1{"x"}) == 1);
193 BOOST_CHECK(math::ldegree(pstype1{"x"}, {"x"}) == 1);
194 BOOST_CHECK(math::ldegree(pstype1{"x"}, {"y"}) == 0);
195 BOOST_CHECK(math::degree(pstype1{"x"} * pstype1{"x"}) == 2);
196 BOOST_CHECK(math::degree(pstype1{"x"} * pstype1{"x"}, {"x"}) == 2);
197 BOOST_CHECK(math::degree(pstype1{"x"} * pstype1{"y"}, {"y"}) == 1);
198 BOOST_CHECK(math::ldegree(pstype1{"x"} * pstype1{"x"}) == 2);
199 BOOST_CHECK(math::ldegree(pstype1{"x"} * pstype1{"x"}, {"x"}) == 2);
200 BOOST_CHECK(math::ldegree(pstype1{"x"} * pstype1{"y"}, {"y"}) == 1);
201 BOOST_CHECK(math::degree(pstype1{"x"} + pstype1{"y"} + pstype1{1}) == 1);
202 BOOST_CHECK(math::degree(pstype1{"x"} + pstype1{"y"} + pstype1{1}, {"x"}) == 1);
203 BOOST_CHECK(math::degree(pstype1{"x"} + pstype1{"y"} + pstype1{1}, {"x"}) == 1);
204 BOOST_CHECK(math::degree(pstype1{"x"} + pstype1{"y"} + pstype1{1}, {"y"}) == 1);
205 BOOST_CHECK(math::degree(pstype1{"x"} + pstype1{"y"} + pstype1{1}, {"y"}) == 1);
206 BOOST_CHECK(math::degree(pstype1{"x"} + pstype1{"y"} + pstype1{1}, {"z"}) == 0);
207 BOOST_CHECK(math::degree(pstype1{"x"} + pstype1{"y"} + pstype1{1}, {"z"}) == 0);
208 BOOST_CHECK(math::ldegree(pstype1{"x"} + pstype1{"y"} + pstype1{1}) == 0);
209 BOOST_CHECK(math::ldegree(pstype1{"x"} + pstype1{"y"} + pstype1{1}, {"x"}) == 0);
210 BOOST_CHECK(math::ldegree(pstype1{"x"} + pstype1{"y"} + pstype1{1}, {"x"}) == 0);
211 BOOST_CHECK(math::ldegree(pstype1{"x"} + pstype1{"y"} + pstype1{1}, {"y"}) == 0);
212 BOOST_CHECK(math::ldegree(pstype1{"x"} + pstype1{"y"} + pstype1{1}, {"y"}) == 0);
213 BOOST_CHECK(math::ldegree(pstype1{"x"} + pstype1{"y"} + pstype1{1}, {"z"}) == 0);
214 BOOST_CHECK(math::ldegree(pstype1{"x"} + pstype1{"y"} + pstype1{1}, {"z"}) == 0);
215 BOOST_CHECK(math::ldegree(pstype1{"x"} * pstype1{"x"} + pstype1{"y"} + pstype1{"x"}) == 1);
216 BOOST_CHECK(math::ldegree(pstype1{"x"} * pstype1{"x"} + pstype1{"y"} + pstype1{"x"}, {"x"}) == 0);
217 BOOST_CHECK(math::ldegree(pstype1{"x"} * pstype1{"x"} + pstype1{"y"} + pstype1{"x"}, {"x"}) == 0);
218 BOOST_CHECK(math::ldegree(pstype1{"x"} * pstype1{"x"} + 2 * pstype1{"x"}, {"x"}) == 1);
219 BOOST_CHECK(math::ldegree(pstype1{"x"} * pstype1{"y"} + 2 * pstype1{"x"}, {"x"}) == 1);
220 BOOST_CHECK(math::ldegree(pstype1{"x"} * pstype1{"y"} + 2 * pstype1{"x"}, {"y"}) == 0);
221 }
222 };
223 template <typename Cf>
operator ()degree_tester224 void operator()(const Cf &)
225 {
226 boost::mpl::for_each<expo_types>(runner<Cf>());
227 }
228 };
229
BOOST_AUTO_TEST_CASE(power_series_test_01)230 BOOST_AUTO_TEST_CASE(power_series_test_01)
231 {
232 init();
233 boost::mpl::for_each<cf_types>(degree_tester());
234 }
235