1 /*
2     Copyright (C) 2013 Tom Bachmann
3 
4     This file is part of FLINT.
5 
6     FLINT is free software: you can redistribute it and/or modify it under
7     the terms of the GNU Lesser General Public License (LGPL) as published
8     by the Free Software Foundation; either version 2.1 of the License, or
9     (at your option) any later version.  See <http://www.gnu.org/licenses/>.
10 */
11 
12 #ifndef CXX_TEST_MYINT_H
13 #define CXX_TEST_MYINT_H CXX_TEST_MYINT_H
14 
15 #include <sstream>
16 #include <string>
17 
18 #include "flintxx/expression.h"
19 
20 namespace flint {
21 template<class Operation, class Data>
22 class my_expression
23     : public expression<derived_wrapper<my_expression>, Operation, Data>
24 {
25 public:
my_expression()26     my_expression() {};
27     template<class T>
my_expression(const T & t)28     explicit my_expression(const T& t)
29         : expression<derived_wrapper< ::flint::my_expression>,
30               Operation, Data>(t) {}
31 
32     template<class T>
33     my_expression& operator=(const T& t)
34     {
35         this->set(t);
36         return *this;
37     }
38 
39 protected:
my_expression(const Data & d)40     explicit my_expression(const Data& d)
41         : expression<derived_wrapper< ::flint::my_expression>,
42               Operation, Data>(d) {}
43 
44     template<class D, class O, class Da>
45     friend class flint::expression;
46 };
47 
48 struct data
49 {
50     int payload;
51     bool* destroyed;
52     int extra;
53 
datadata54     data() : payload(-1), destroyed(0), extra(42) {}
55 
~datadata56     ~data()
57     {
58         if(destroyed)
59             *destroyed = true;
60     }
61 
datadata62     data(const data& d)
63         : payload(d.payload), destroyed(0), extra(1) {}
datadata64     data(int i)
65         : payload(i), destroyed(0), extra(2) {}
datadata66     data(char i)
67         : payload(i), destroyed(0), extra(3) {}
68 };
69 
70 typedef my_expression<operations::immediate, data> myint;
71 
72 template<class Operation, class Data>
73 class my_expression2
74     : public expression<derived_wrapper<my_expression2>, Operation, Data>
75 {
76 public:
77     // cannot have a default constructor
78 
79     typedef expression<derived_wrapper< ::flint::my_expression2>,
80               Operation, Data> base_t;
81     typedef typename base_t::evaluated_t evaluated_t;
82 
83     template<class T>
my_expression2(const T & t)84     explicit my_expression2(const T& t)
85         : base_t(t) {}
86 
87     template<class T>
my_expression2(T & t)88     explicit my_expression2(T& t)
89         : base_t(t) {}
90 
91     template<class T>
92     my_expression2& operator=(const T& t)
93     {
94         this->set(t);
95         return *this;
96     }
97 
create_temporary()98     evaluated_t create_temporary() const
99     {
100         return evaluated_t(WORD(0));
101     }
102 
103 protected:
my_expression2(const Data & d)104     explicit my_expression2(const Data& d)
105         : base_t(d) {}
106 
107     template<class D, class O, class Da>
108     friend class flint::expression;
109 };
110 
111 struct longref_data;
112 struct longcref_data;
113 struct long_data;
114 typedef my_expression2<operations::immediate, long_data> mylong;
115 typedef my_expression2<operations::immediate, longref_data> mylong_ref;
116 typedef my_expression2<operations::immediate, longcref_data> mylong_cref;
117 
118 namespace traits {
119 template<> struct can_evaluate_into<mylong_ref, mylong> : mp::true_ { };
120 }
121 
122 struct long_data
123 {
124     slong payload;
125     // no default constructor
126     long_data(slong d) : payload(d) {}
127     long_data(const myint& m) : payload(m._data().payload) {}
128 
129     long_data(const mylong_ref&);
130     long_data(const mylong_cref&);
131 };
132 
133 struct longref_data
134 {
135     slong& payload;
136 
137     longref_data(mylong& l) : payload(l._data().payload) {}
138 };
139 
140 struct longcref_data
141 {
142     const slong& payload;
143 
144     longcref_data(const mylong& l) : payload(l._data().payload) {}
145     longcref_data(mylong_ref lr) : payload(lr._data().payload) {}
146 };
147 
148 inline long_data::long_data(const mylong_ref& mlr) : payload(mlr._data().payload) {}
149 inline long_data::long_data(const mylong_cref& mlr) : payload(mlr._data().payload) {}
150 
151 namespace mylong_traits {
152 template<class T> struct is_source : mp::false_ { };
153 template<class T> struct is_target : mp::false_ { };
154 
155 template<> struct is_source<mylong> : mp::true_ { };
156 template<> struct is_source<mylong_ref> : mp::true_ { };
157 template<> struct is_source<mylong_cref> : mp::true_ { };
158 template<> struct is_target<mylong> : mp::true_ { };
159 template<> struct is_target<mylong_ref> : mp::true_ { };
160 }
161 
162 
163 FLINT_DEFINE_FOURARY(fourary_test)
164 FLINT_DEFINE_FIVEARY(fiveary_test)
165 FLINT_DEFINE_SIXARY(sixary_test)
166 FLINT_DEFINE_SEVENARY(sevenary_test)
167 
168 namespace rules {
169 FLINT_DEFINE_FOURARY_EXPR_COND4(fourary_test_op, myint,
170         traits::is_integer, traits::is_integer, traits::is_integer, traits::is_integer,
171         to._data().payload = e1 + e2 + e3 + e4)
172 FLINT_DEFINE_FIVEARY_EXPR_COND5(fiveary_test_op, myint,
173         traits::is_integer, traits::is_integer, traits::is_integer,
174         traits::is_integer, traits::is_integer,
175         to._data().payload = e1 + e2 + e3 + e4 + e5)
176 FLINT_DEFINE_SIXARY_EXPR_COND6(sixary_test_op, myint,
177         traits::is_integer, traits::is_integer, traits::is_integer,
178         traits::is_integer, traits::is_integer, traits::is_integer,
179         to._data().payload = e1 + e2 + e3 + e4 + e5 + e6)
180 FLINT_DEFINE_SEVENARY_EXPR_COND7(sevenary_test_op, myint,
181         traits::is_integer, traits::is_integer, traits::is_integer,
182         traits::is_integer, traits::is_integer, traits::is_integer,
183         traits::is_integer,
184         to._data().payload = e1 + e2 + e3 + e4 + e5 + e6 + e7)
185 
186 template<>
187 struct print<myint>
188 {
189     static void doit(const myint& v, std::ostream& o)
190     {
191         o << v._data().payload;
192     }
193 };
194 
195 template<>
196 struct assignment<myint, myint>
197 {
198     static void doit(myint& to, const myint& from)
199     {
200         to._data().payload = from._data().payload;
201         to._data().extra = 4;
202     }
203 };
204 
205 template<>
206 struct assignment<myint, slong>
207 {
208     static void doit(myint& to, slong from)
209     {
210         to._data().payload = from;
211         to._data().extra = 5;
212     }
213 };
214 
215 template<>
216 struct to_string<myint>
217 {
218     static std::string get(const myint& i, int base /* ignored */)
219     {
220         std::ostringstream oss;
221         oss << i;
222         return oss.str();
223     }
224 };
225 
226 template<>
227 struct equals<myint, myint>
228 {
229     static bool get(const myint& i1, const myint& i2)
230     {
231         return i1._data().payload == i2._data().payload;
232     }
233 };
234 
235 template<>
236 struct equals<myint, int>
237 {
238     static bool get(const myint& i1, int i2)
239     {
240         return i1._data().payload == i2;
241     }
242 };
243 
244 template<>
245 struct conversion<int, myint>
246 {
247     static int get(const myint& from)
248     {
249         return from._data().payload;
250     }
251 };
252 
253 template<>
254 struct swap<myint, myint>
255 {
256     static void doit(myint& e1, myint& e2)
257     {
258         int tmp;
259         tmp = e1._data().payload;
260         e1._data().payload = e2._data().payload;
261         e2._data().payload = tmp;
262         e1._data().extra = 1234;
263         e2._data().extra = 1234;
264     }
265 };
266 
267 template<>
268 struct commutative_binary_expression<myint, operations::plus, myint>
269 {
270     typedef myint return_t;
271     static void doit(myint& to, const myint& a1, const myint& a2)
272     {
273         to._data().payload = a1._data().payload + a2._data().payload;
274     }
275 };
276 
277 template<class T>
278 struct commutative_binary_expression<myint,
279     typename mp::enable_if<traits::is_integer<T>, operations::plus>::type,
280     T>
281 {
282     typedef myint return_t;
283     static void doit(myint& to, const myint& a1, T a2)
284     {
285         to._data().payload = a1._data().payload + a2;
286     }
287 };
288 
289 template<>
290 struct commutative_binary_expression<myint, operations::times, myint>
291 {
292     typedef myint return_t;
293     static void doit(myint& to, const myint& a1, const myint& a2)
294     {
295         to._data().payload = a1._data().payload * a2._data().payload;
296     }
297 };
298 
299 template<>
300 struct binary_expression<myint, operations::minus, myint>
301 {
302     typedef myint return_t;
303     static void doit(myint& to, const myint& a1, const myint& a2)
304     {
305         to._data().payload = a1._data().payload - a2._data().payload;
306     }
307 };
308 
309 template<>
310 struct binary_expression<myint, operations::divided_by, myint>
311 {
312     typedef myint return_t;
313     static void doit(myint& to, const myint& a1, const myint& a2)
314     {
315         to._data().payload = a1._data().payload / a2._data().payload;
316     }
317 };
318 
319 template<>
320 struct binary_expression<myint, operations::modulo, myint>
321 {
322     typedef myint return_t;
323     static void doit(myint& to, const myint& a1, const myint& a2)
324     {
325         to._data().payload = a1._data().payload % a2._data().payload;
326     }
327 };
328 
329 template<>
330 struct binary_expression<myint, operations::shift, int>
331 {
332     typedef myint return_t;
333     static void doit(myint& to, const myint& a1, int a2)
334     {
335         if (a2 >= 0)
336             to._data().payload = a1._data().payload << a2;
337         else
338             to._data().payload = a1._data().payload >> (-a2);
339     }
340 };
341 
342 template<>
343 struct unary_expression<operations::negate, myint>
344 {
345     typedef myint return_t;
346     static void doit(myint& to, const myint& from)
347     {
348         to._data().payload = - from._data().payload;
349     }
350 };
351 
352 
353 /////////////////////////////////////////////////////////////////////////////
354 // Minimal rules for mylong
355 /////////////////////////////////////////////////////////////////////////////
356 
357 template<class T, class U>
358 struct equals<T, U, typename mp::enable_if<mp::and_<
359     mylong_traits::is_source<T>, mylong_traits::is_source<U> > >::type>
360 {
361     static bool get(const T& i1, const U& i2)
362     {
363         return i1._data().payload == i2._data().payload;
364     }
365 };
366 
367 template<class T>
368 struct equals<T, slong,
369     typename mp::enable_if<mylong_traits::is_source<T> >::type>
370 {
371     static bool get(const T& i1, slong i2)
372     {
373         return i1._data().payload == i2;
374     }
375 };
376 
377 template<class T, class U>
378 struct commutative_binary_expression<T, typename mp::enable_if<mp::and_<
379         mylong_traits::is_source<T>,
380         mylong_traits::is_source<U> >,
381     operations::plus>::type, U>
382 {
383     typedef mylong return_t;
384 
385     template<class V>
386     static void doit(V& to, const T& a1, const U& a2)
387     {
388         to._data().payload = a1._data().payload + a2._data().payload;
389     }
390 };
391 
392 template<class U>
393 struct commutative_binary_expression<typename mp::enable_if<
394     mylong_traits::is_source<U>, myint>::type, operations::plus, U>
395 {
396     typedef mylong return_t;
397 
398     template<class V>
399     static void doit(V& to, const myint& a1, const U& a2)
400     {
401         to._data().payload = a1._data().payload + a2._data().payload;
402     }
403 };
404 
405 template<class T, class U>
406 struct assignment<T, U, typename mp::enable_if<mp::and_<
407     mylong_traits::is_target<T>, mylong_traits::is_source<U> > >::type>
408 {
409     static void doit(T& to, const U& from)
410     {
411         to._data().payload = from._data().payload;
412     }
413 };
414 
415 template<class T>
416 struct assignment<T, slong,
417     typename mp::enable_if<mylong_traits::is_target<T> >::type>
418 {
419     static void doit(T& to, slong from)
420     {
421         to._data().payload = from;
422     }
423 };
424 
425 template<class T>
426 struct assignment<T, myint,
427     typename mp::enable_if<mylong_traits::is_target<T> >::type>
428 {
429     static void doit(T& to, const myint& from)
430     {
431         to._data().payload = from._data().payload;
432     }
433 };
434 
435 FLINT_DEFINE_READ_COND(mylong_traits::is_target,
436         flint_fscanf(from, "%wd", &to._data().payload))
437 FLINT_DEFINE_PRINT_COND(mylong_traits::is_source,
438         flint_fprintf(to, "%wd", from._data().payload))
439 FLINT_DEFINE_PRINT_PRETTY_COND(mylong_traits::is_source,
440         flint_fprintf(to, "<%wd>", from._data().payload))
441 } // rules
442 } // flint
443 
444 #endif
445