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