G_do_hoelder: fix case with real x values which are not of type cl_R.
[ginac.git] / check / exam_hashmap.cpp
1 /** @file exam_hashmap.cpp
2  *
3  *  Regression tests for the exhashmap<> container. */
4
5 /*
6  *  GiNaC Copyright (C) 1999-2018 Johannes Gutenberg University Mainz, Germany
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 2 of the License, or
11  *  (at your option) any later version.
12  *
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program; if not, write to the Free Software
20  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
21  */
22
23 #include "ginac.h"
24 using namespace GiNaC;
25
26 #include <iostream>
27 using namespace std;
28
29 unsigned exam_hashmap()
30 {
31         unsigned result = 0;
32         unsigned N = 100;
33
34         cout << "examining hash maps" << flush;
35
36         // Create empty container
37         exhashmap<unsigned> M1;
38         if (M1.size() != 0) {
39                 clog << "Newly constructed container has size() != 0" << endl;
40                 ++result;
41         }
42         if (!M1.empty()) {
43                 clog << "Newly constructed container is not empty" << endl;
44                 ++result;
45         }
46
47         cout << '.' << flush;
48
49         // Insert elements
50         for (unsigned i = 0; i < N; ++i)
51                 M1.insert(make_pair(i, i));
52
53         if (M1.size() != N) {
54                 clog << "After " << N << " insertions, size() returns " << M1.size() << " instead of " << N << endl;
55                 ++result;
56         }
57
58         for (unsigned i = 0; i < N; ++i) {
59                 if (M1[i] != i) {
60                         clog << "Lookup of key " << i << " in M1 didn't return correct value" << endl;
61                         ++result;
62                         break;
63                 }
64         }
65
66         if (M1.size() != N) {
67                 clog << "After " << N << " lookups, size() returns " << M1.size() << " instead of " << N << endl;
68                 ++result;
69         }
70
71         cout << '.' << flush;
72
73         // Test constructor from two iterators and operator==
74         exhashmap<unsigned> M2(M1.begin(), M1.end());
75         if (M2.size() != M1.size()) {
76                 clog << "Constructor from two iterators: size of destination container (" << M2.size() << ") not equal to size of source (" << M1.size() << ")" << endl;
77                 ++result;
78         }
79
80         for (unsigned i = 0; i < N; ++i) {
81                 if (M2[i] != i) {
82                         clog << "Lookup of key " << i << " in M2 didn't return correct value" << endl;
83                         ++result;
84                         break;
85                 }
86         }
87
88         if (M2 != M1) {
89                 clog << "Copied container not equal to source" << endl;
90                 ++result;
91         }
92
93         cout << '.' << flush;
94
95         // Test assignment operator
96         exhashmap<unsigned> M3;
97         M3 = M1;
98         if (M3.size() != N) {
99                 clog << "Assignment operator: size of assigned container not equal to size of original" << endl;
100                 ++result;
101         }
102
103         for (unsigned i = 0; i < N; ++i) {
104                 if (M3[i] != i) {
105                         clog << "Lookup of key " << i << " in M3 didn't return correct value" << endl;
106                         ++result;
107                         break;
108                 }
109         }
110
111         cout << '.' << flush;
112
113         // Test insert(it, it)
114         exhashmap<unsigned> M4;
115         M4.insert(M1.begin(), M1.end());
116
117         if (M4.size() != M1.size()) {
118                 clog << "insert(it, it): size of destination container not equal to size of source" << endl;
119                 ++result;
120         }
121
122         for (unsigned i = 0; i < N; ++i) {
123                 if (M4[i] != i) {
124                         clog << "Lookup of key " << i << " in M4 didn't return correct value" << endl;
125                         ++result;
126                         break;
127                 }
128         }
129
130         cout << '.' << flush;
131
132         // Test insert()/find()
133         symbol x("x"), y("y");
134         exhashmap<unsigned> M5;
135         M5.insert(make_pair(x-2, 1));
136         M5.insert(make_pair(sin(x+y), 2));
137         M5.insert(make_pair(Pi, 3));
138         M5.insert(make_pair(0, 4));
139         M5.insert(make_pair(4*pow(x, y), 5));
140         if (M5.size() != 5) {
141                 clog << "After 5 insertions, size() returns " << M5.size() << " instead of 5" << endl;
142                 ++result;
143         }
144
145         exhashmap<unsigned>::const_iterator cit = M5.find(sin(x+y));
146         if (cit == M5.end()) {
147                 clog << "Lookup of sin(x+y) didn't find anything" << endl;
148                 ++result;
149         }
150         if (!cit->first.is_equal(sin(x+y))) {
151                 clog << "Lookup of sin(x+y) returned an incorrect iterator" << endl;
152                 ++result;
153         }
154         if (cit->second != 2) {
155                 clog << "Lookup of sin(x+y) returned wrong value" << endl;
156                 ++result;
157         }
158
159         cout << '.' << flush;
160
161         // Test re-inserting insert()
162         pair<exhashmap<unsigned>::iterator, bool> pit = M5.insert(make_pair(sin(x+y), 42));
163         if (pit.second) {
164                 clog << "Reinsertion of sin(x+y) inserted a new value" << endl;
165                 ++result;
166         }
167         if (!pit.first->first.is_equal(sin(x+y))) {
168                 clog << "Reinsertion of sin(x+y) returned an incorrect iterator" << endl;
169                 ++result;
170         }
171         if (pit.first->second != 2) {
172                 clog << "Reinsertion of sin(x+y) changed the value" << endl;
173                 ++result;
174         }
175
176         cout << '.' << flush;
177
178         // Test operator[]
179         unsigned v = M5[sin(x+y)];
180         if (M5.size() != 5) {
181                 clog << "operator[] with an existing key changed the container size" << endl;
182                 ++result;
183         }
184         if (v != 2) {
185                 clog << "operator[] with an existing key returned the wrong value" << endl;
186                 ++result;
187         }
188
189         v = M5[y+1];
190         if (M5.size() != 6) {
191                 clog << "operator[] with a new key didn't insert a new value" << endl;
192                 ++result;
193         }
194         if (v != 0) {
195                 clog << "operator[] with a new key returned the wrong value" << endl;
196                 ++result;
197         }
198
199         cout << '.' << flush;
200
201         // Test erase()
202         exhashmap<unsigned>::iterator it = M5.find(y+1);
203         if (it == M5.end()) {
204                 clog << "Key y+1 wasn't found" << endl;
205                 ++result;
206         }
207         if (!it->first.is_equal(y+1)) {
208                 clog << "find() returned an incorrect iterator" << endl;
209                 ++result;
210         }
211         if (it->second != 0) {
212                 clog << "find() returned an incorrect value" << endl;
213                 ++result;
214         }
215
216         M5.erase(it);
217         if (M5.size() != 5) {
218                 clog << "erase(it) didn't reduce the size of the container" << endl;
219                 ++result;
220         }
221
222         it = M5.find(y+1);
223         if (it != M5.end()) {
224                 clog << "Key was still found after erase()" << endl;
225                 ++result;
226         }
227
228         exhashmap<unsigned>::size_type n = M5.erase(Pi);
229         if (n != 1) {
230                 clog << "erase(Pi) returned " << n << " instead of 1" << endl;
231                 ++result;
232         }
233         if (M5.size() != 4) {
234                 clog << "erase(Pi) didn't reduce the size of the container" << endl;
235                 ++result;
236         }
237
238         n = M5.erase(42);
239         if (n != 0) {
240                 clog << "erase(42) returned " << n << " instead of 0" << endl;
241                 ++result;
242         }
243         if (M5.size() != 4) {
244                 clog << "erase(42) reduced the size of the container" << endl;
245                 ++result;
246         }
247
248         cout << '.' << flush;
249
250         // Test swap()
251         exhashmap<unsigned> M6;
252         M6.swap(M1);
253         if (M6.size() != N) {
254                 clog << "After swap, size() returns " << M6.size() << " instead of " << N << endl;
255                 ++result;
256         }
257         if (M1.size() != 0) {
258                 clog << "After swap with empty container, size() returns " << M1.size() << " instead of 0" << endl;
259                 ++result;
260         }
261
262         cout << '.' << flush;
263
264         // Test clear()
265         M2.clear();
266         if (M2.size() != 0) {
267                 clog << "Size of cleared container is " << M5.size() << " instead of 0" << endl;
268                 ++result;
269         }
270
271         cout << '.' << flush;
272
273         // Test count()
274         n = M5.count(Pi);
275         if (n != 0) {
276                 clog << "count(Pi) returns " << n << " instead of 0" << endl;
277                 ++result;
278         }
279
280         n = M5.count(4*pow(x, y));
281         if (n != 1) {
282                 clog << "count(4*x^y) returns " << n << " instead of 1" << endl;
283                 ++result;
284         }
285         cout << '.' << flush;
286
287         return result;
288 }
289
290 int main(int argc, char** argv)
291 {
292         return exam_hashmap();
293 }