459 lines
12 KiB
C++
459 lines
12 KiB
C++
/*=============================================================================
|
|
|
|
This file is part of FLINT.
|
|
|
|
FLINT is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
FLINT is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with FLINT; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
=============================================================================*/
|
|
/******************************************************************************
|
|
|
|
Copyright (C) 2013 Tom Bachmann
|
|
|
|
******************************************************************************/
|
|
|
|
#ifndef CXX_TEST_MYINT_H
|
|
#define CXX_TEST_MYINT_H CXX_TEST_MYINT_H
|
|
|
|
#include <sstream>
|
|
#include <string>
|
|
|
|
#include "flintxx/expression.h"
|
|
|
|
namespace flint {
|
|
template<class Operation, class Data>
|
|
class my_expression
|
|
: public expression<derived_wrapper<my_expression>, Operation, Data>
|
|
{
|
|
public:
|
|
my_expression() {};
|
|
template<class T>
|
|
explicit my_expression(const T& t)
|
|
: expression<derived_wrapper< ::flint::my_expression>,
|
|
Operation, Data>(t) {}
|
|
|
|
template<class T>
|
|
my_expression& operator=(const T& t)
|
|
{
|
|
this->set(t);
|
|
return *this;
|
|
}
|
|
|
|
protected:
|
|
explicit my_expression(const Data& d)
|
|
: expression<derived_wrapper< ::flint::my_expression>,
|
|
Operation, Data>(d) {}
|
|
|
|
template<class D, class O, class Da>
|
|
friend class flint::expression;
|
|
};
|
|
|
|
struct data
|
|
{
|
|
int payload;
|
|
bool* destroyed;
|
|
int extra;
|
|
|
|
data() : payload(-1), destroyed(0), extra(42) {}
|
|
|
|
~data()
|
|
{
|
|
if(destroyed)
|
|
*destroyed = true;
|
|
}
|
|
|
|
data(const data& d)
|
|
: payload(d.payload), destroyed(0), extra(1) {}
|
|
data(int i)
|
|
: payload(i), destroyed(0), extra(2) {}
|
|
data(char i)
|
|
: payload(i), destroyed(0), extra(3) {}
|
|
};
|
|
|
|
typedef my_expression<operations::immediate, data> myint;
|
|
|
|
template<class Operation, class Data>
|
|
class my_expression2
|
|
: public expression<derived_wrapper<my_expression2>, Operation, Data>
|
|
{
|
|
public:
|
|
// cannot have a default constructor
|
|
|
|
typedef expression<derived_wrapper< ::flint::my_expression2>,
|
|
Operation, Data> base_t;
|
|
typedef typename base_t::evaluated_t evaluated_t;
|
|
|
|
template<class T>
|
|
explicit my_expression2(const T& t)
|
|
: base_t(t) {}
|
|
|
|
template<class T>
|
|
explicit my_expression2(T& t)
|
|
: base_t(t) {}
|
|
|
|
template<class T>
|
|
my_expression2& operator=(const T& t)
|
|
{
|
|
this->set(t);
|
|
return *this;
|
|
}
|
|
|
|
evaluated_t create_temporary() const
|
|
{
|
|
return evaluated_t(WORD(0));
|
|
}
|
|
|
|
protected:
|
|
explicit my_expression2(const Data& d)
|
|
: base_t(d) {}
|
|
|
|
template<class D, class O, class Da>
|
|
friend class flint::expression;
|
|
};
|
|
|
|
struct longref_data;
|
|
struct longcref_data;
|
|
struct long_data;
|
|
typedef my_expression2<operations::immediate, long_data> mylong;
|
|
typedef my_expression2<operations::immediate, longref_data> mylong_ref;
|
|
typedef my_expression2<operations::immediate, longcref_data> mylong_cref;
|
|
|
|
namespace traits {
|
|
template<> struct can_evaluate_into<mylong_ref, mylong> : mp::true_ { };
|
|
}
|
|
|
|
struct long_data
|
|
{
|
|
slong payload;
|
|
// no default constructor
|
|
long_data(slong d) : payload(d) {}
|
|
long_data(const myint& m) : payload(m._data().payload) {}
|
|
|
|
long_data(const mylong_ref&);
|
|
long_data(const mylong_cref&);
|
|
};
|
|
|
|
struct longref_data
|
|
{
|
|
slong& payload;
|
|
|
|
longref_data(mylong& l) : payload(l._data().payload) {}
|
|
};
|
|
|
|
struct longcref_data
|
|
{
|
|
const slong& payload;
|
|
|
|
longcref_data(const mylong& l) : payload(l._data().payload) {}
|
|
longcref_data(mylong_ref lr) : payload(lr._data().payload) {}
|
|
};
|
|
|
|
inline long_data::long_data(const mylong_ref& mlr) : payload(mlr._data().payload) {}
|
|
inline long_data::long_data(const mylong_cref& mlr) : payload(mlr._data().payload) {}
|
|
|
|
namespace mylong_traits {
|
|
template<class T> struct is_source : mp::false_ { };
|
|
template<class T> struct is_target : mp::false_ { };
|
|
|
|
template<> struct is_source<mylong> : mp::true_ { };
|
|
template<> struct is_source<mylong_ref> : mp::true_ { };
|
|
template<> struct is_source<mylong_cref> : mp::true_ { };
|
|
template<> struct is_target<mylong> : mp::true_ { };
|
|
template<> struct is_target<mylong_ref> : mp::true_ { };
|
|
}
|
|
|
|
|
|
FLINT_DEFINE_FOURARY(fourary_test)
|
|
FLINT_DEFINE_FIVEARY(fiveary_test)
|
|
FLINT_DEFINE_SIXARY(sixary_test)
|
|
FLINT_DEFINE_SEVENARY(sevenary_test)
|
|
|
|
namespace rules {
|
|
FLINT_DEFINE_FOURARY_EXPR_COND4(fourary_test_op, myint,
|
|
traits::is_integer, traits::is_integer, traits::is_integer, traits::is_integer,
|
|
to._data().payload = e1 + e2 + e3 + e4)
|
|
FLINT_DEFINE_FIVEARY_EXPR_COND5(fiveary_test_op, myint,
|
|
traits::is_integer, traits::is_integer, traits::is_integer,
|
|
traits::is_integer, traits::is_integer,
|
|
to._data().payload = e1 + e2 + e3 + e4 + e5)
|
|
FLINT_DEFINE_SIXARY_EXPR_COND6(sixary_test_op, myint,
|
|
traits::is_integer, traits::is_integer, traits::is_integer,
|
|
traits::is_integer, traits::is_integer, traits::is_integer,
|
|
to._data().payload = e1 + e2 + e3 + e4 + e5 + e6)
|
|
FLINT_DEFINE_SEVENARY_EXPR_COND7(sevenary_test_op, myint,
|
|
traits::is_integer, traits::is_integer, traits::is_integer,
|
|
traits::is_integer, traits::is_integer, traits::is_integer,
|
|
traits::is_integer,
|
|
to._data().payload = e1 + e2 + e3 + e4 + e5 + e6 + e7)
|
|
|
|
template<>
|
|
struct print<myint>
|
|
{
|
|
static void doit(const myint& v, std::ostream& o)
|
|
{
|
|
o << v._data().payload;
|
|
}
|
|
};
|
|
|
|
template<>
|
|
struct assignment<myint, myint>
|
|
{
|
|
static void doit(myint& to, const myint& from)
|
|
{
|
|
to._data().payload = from._data().payload;
|
|
to._data().extra = 4;
|
|
}
|
|
};
|
|
|
|
template<>
|
|
struct assignment<myint, slong>
|
|
{
|
|
static void doit(myint& to, slong from)
|
|
{
|
|
to._data().payload = from;
|
|
to._data().extra = 5;
|
|
}
|
|
};
|
|
|
|
template<>
|
|
struct to_string<myint>
|
|
{
|
|
static std::string get(const myint& i, int base /* ignored */)
|
|
{
|
|
std::ostringstream oss;
|
|
oss << i;
|
|
return oss.str();
|
|
}
|
|
};
|
|
|
|
template<>
|
|
struct equals<myint, myint>
|
|
{
|
|
static bool get(const myint& i1, const myint& i2)
|
|
{
|
|
return i1._data().payload == i2._data().payload;
|
|
}
|
|
};
|
|
|
|
template<>
|
|
struct equals<myint, int>
|
|
{
|
|
static bool get(const myint& i1, int i2)
|
|
{
|
|
return i1._data().payload == i2;
|
|
}
|
|
};
|
|
|
|
template<>
|
|
struct conversion<int, myint>
|
|
{
|
|
static int get(const myint& from)
|
|
{
|
|
return from._data().payload;
|
|
}
|
|
};
|
|
|
|
template<>
|
|
struct swap<myint, myint>
|
|
{
|
|
static void doit(myint& e1, myint& e2)
|
|
{
|
|
int tmp;
|
|
tmp = e1._data().payload;
|
|
e1._data().payload = e2._data().payload;
|
|
e2._data().payload = tmp;
|
|
e1._data().extra = 1234;
|
|
e2._data().extra = 1234;
|
|
}
|
|
};
|
|
|
|
template<>
|
|
struct commutative_binary_expression<myint, operations::plus, myint>
|
|
{
|
|
typedef myint return_t;
|
|
static void doit(myint& to, const myint& a1, const myint& a2)
|
|
{
|
|
to._data().payload = a1._data().payload + a2._data().payload;
|
|
}
|
|
};
|
|
|
|
template<class T>
|
|
struct commutative_binary_expression<myint,
|
|
typename mp::enable_if<traits::is_integer<T>, operations::plus>::type,
|
|
T>
|
|
{
|
|
typedef myint return_t;
|
|
static void doit(myint& to, const myint& a1, T a2)
|
|
{
|
|
to._data().payload = a1._data().payload + a2;
|
|
}
|
|
};
|
|
|
|
template<>
|
|
struct commutative_binary_expression<myint, operations::times, myint>
|
|
{
|
|
typedef myint return_t;
|
|
static void doit(myint& to, const myint& a1, const myint& a2)
|
|
{
|
|
to._data().payload = a1._data().payload * a2._data().payload;
|
|
}
|
|
};
|
|
|
|
template<>
|
|
struct binary_expression<myint, operations::minus, myint>
|
|
{
|
|
typedef myint return_t;
|
|
static void doit(myint& to, const myint& a1, const myint& a2)
|
|
{
|
|
to._data().payload = a1._data().payload - a2._data().payload;
|
|
}
|
|
};
|
|
|
|
template<>
|
|
struct binary_expression<myint, operations::divided_by, myint>
|
|
{
|
|
typedef myint return_t;
|
|
static void doit(myint& to, const myint& a1, const myint& a2)
|
|
{
|
|
to._data().payload = a1._data().payload / a2._data().payload;
|
|
}
|
|
};
|
|
|
|
template<>
|
|
struct binary_expression<myint, operations::modulo, myint>
|
|
{
|
|
typedef myint return_t;
|
|
static void doit(myint& to, const myint& a1, const myint& a2)
|
|
{
|
|
to._data().payload = a1._data().payload % a2._data().payload;
|
|
}
|
|
};
|
|
|
|
template<>
|
|
struct binary_expression<myint, operations::shift, int>
|
|
{
|
|
typedef myint return_t;
|
|
static void doit(myint& to, const myint& a1, int a2)
|
|
{
|
|
if (a2 >= 0)
|
|
to._data().payload = a1._data().payload << a2;
|
|
else
|
|
to._data().payload = a1._data().payload >> (-a2);
|
|
}
|
|
};
|
|
|
|
template<>
|
|
struct unary_expression<operations::negate, myint>
|
|
{
|
|
typedef myint return_t;
|
|
static void doit(myint& to, const myint& from)
|
|
{
|
|
to._data().payload = - from._data().payload;
|
|
}
|
|
};
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Minimal rules for mylong
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
template<class T, class U>
|
|
struct equals<T, U, typename mp::enable_if<mp::and_<
|
|
mylong_traits::is_source<T>, mylong_traits::is_source<U> > >::type>
|
|
{
|
|
static bool get(const T& i1, const U& i2)
|
|
{
|
|
return i1._data().payload == i2._data().payload;
|
|
}
|
|
};
|
|
|
|
template<class T>
|
|
struct equals<T, slong,
|
|
typename mp::enable_if<mylong_traits::is_source<T> >::type>
|
|
{
|
|
static bool get(const T& i1, slong i2)
|
|
{
|
|
return i1._data().payload == i2;
|
|
}
|
|
};
|
|
|
|
template<class T, class U>
|
|
struct commutative_binary_expression<T, typename mp::enable_if<mp::and_<
|
|
mylong_traits::is_source<T>,
|
|
mylong_traits::is_source<U> >,
|
|
operations::plus>::type, U>
|
|
{
|
|
typedef mylong return_t;
|
|
|
|
template<class V>
|
|
static void doit(V& to, const T& a1, const U& a2)
|
|
{
|
|
to._data().payload = a1._data().payload + a2._data().payload;
|
|
}
|
|
};
|
|
|
|
template<class U>
|
|
struct commutative_binary_expression<typename mp::enable_if<
|
|
mylong_traits::is_source<U>, myint>::type, operations::plus, U>
|
|
{
|
|
typedef mylong return_t;
|
|
|
|
template<class V>
|
|
static void doit(V& to, const myint& a1, const U& a2)
|
|
{
|
|
to._data().payload = a1._data().payload + a2._data().payload;
|
|
}
|
|
};
|
|
|
|
template<class T, class U>
|
|
struct assignment<T, U, typename mp::enable_if<mp::and_<
|
|
mylong_traits::is_target<T>, mylong_traits::is_source<U> > >::type>
|
|
{
|
|
static void doit(T& to, const U& from)
|
|
{
|
|
to._data().payload = from._data().payload;
|
|
}
|
|
};
|
|
|
|
template<class T>
|
|
struct assignment<T, slong,
|
|
typename mp::enable_if<mylong_traits::is_target<T> >::type>
|
|
{
|
|
static void doit(T& to, slong from)
|
|
{
|
|
to._data().payload = from;
|
|
}
|
|
};
|
|
|
|
template<class T>
|
|
struct assignment<T, myint,
|
|
typename mp::enable_if<mylong_traits::is_target<T> >::type>
|
|
{
|
|
static void doit(T& to, const myint& from)
|
|
{
|
|
to._data().payload = from._data().payload;
|
|
}
|
|
};
|
|
|
|
FLINT_DEFINE_READ_COND(mylong_traits::is_target,
|
|
flint_fscanf(from, "%wd", &to._data().payload))
|
|
FLINT_DEFINE_PRINT_COND(mylong_traits::is_source,
|
|
flint_fprintf(to, "%wd", from._data().payload))
|
|
FLINT_DEFINE_PRINT_PRETTY_COND(mylong_traits::is_source,
|
|
flint_fprintf(to, "<%wd>", from._data().payload))
|
|
} // rules
|
|
} // flint
|
|
|
|
#endif
|