1 #ifndef _COMMON_
2 #define _COMMON_
3 
4 template<class R, class A, class B> R Build(A a, B b) {
5     return R(a, b);
6 }
7 template<class RR, class AA = RR, class BB = AA>
8 struct BinaryOp : public binary_function<AA, BB, RR> {
fBinaryOp9     static RR f(Stack s, const AA& a, const BB& b) { return RR(s, a, b); }
10 };
11 template<class Op, char trans = 'N'>
12 class pwr {
13     public:
14         Op* A;
pwr(Op * B)15         pwr(Op* B) : A(B) { assert(A); }
16         const typename std::conditional<trans == 'T', std::string*, long>::type c;
17         static constexpr char tr = trans;
18         mutable bool conjugate;
pwr(Stack s,Op * const & d,const typename std::conditional<trans=='T',std::string *,long>::type e)19         pwr(Stack s, Op* const& d, const typename std::conditional<trans == 'T', std::string*, long>::type e) : A(d), c(e), conjugate(false) { }
operator Op*() const20         operator Op* () const { return A; }
21 };
22 template<class RR, class AA = RR, class BB = AA>
23 struct assign : public binary_function<AA, BB, RR> {
24 template<class V, class T>
checkassign25 static T check(T* t, typename std::enable_if<T::tr == 'H'>::type* = 0) {
26     t->conjugate = true;
27     if(t->c != -1)
28         CompileError("A'^p, the p must be a constant == -1, sorry");
29     return *t;
30 }
31 template<class V, class T>
checkassign32 static T check(T* t, typename std::enable_if<T::tr == 'N'>::type* = 0) {
33     if(t->c != -1)
34         CompileError("A^p, the p must be a constant == -1 or == \"-T\" or == \"-H\", sorry");
35     return *t;
36 }
37 template<class V, class T>
checkassign38 static T check(T* t, typename std::enable_if<T::tr == 'T'>::type* = 0) {
39     if(t->c->compare("-H") == 0)
40         t->conjugate = true;
41     if(t->c->compare("-T") != 0 && !t->conjugate)
42         CompileError("A^p, the p must be a constant == -1 or == \"-T\" or == \"-H\", sorry");
43     return *t;
44 }
fassign45 static RR f(Stack stack, const AA& a, const BB& b) {
46     ffassert(a);
47     check<BB>(&a);
48     RR p(a, b);
49     return p;
50 }
51 };
52 template<class Op>
53 class OpTrans {
54     public:
55         Op* A;
OpTrans(Op * B)56         OpTrans(Op* B) : A(B) { assert(A); }
operator Op&() const57         operator Op& () const { return *A; }
operator Op*() const58         operator Op* () const { return A; }
59 };
60 template<class Op, template<class, class, class, char> class Inv, class V, class K = double, char trans = 'N'>
addInv()61 void addInv() {
62     Dcl_Type<pwr<Op, trans>>();
63     Dcl_Type<Inv<pwr<Op, trans>, V*, K, trans>>();
64     if(trans == 'T') {
65         Dcl_Type<pwr<Op, 'H'>>();
66         Dcl_Type<Inv<pwr<Op, 'H'>, V*, K, 'T'>>();
67         TheOperators->Add("^", new OneBinaryOperator_st<BinaryOp<pwr<Op, 'H'>, OpTrans<Op>, typename std::conditional<'N' == 'N', long, std::string*>::type>>);
68         TheOperators->Add("*", new OneBinaryOperator_st<assign<Inv<pwr<Op, 'H'>, V*, K, 'T'>, pwr<Op, 'H'>, V*>>);
69         TheOperators->Add("=", new OneOperator2<V*, V*, Inv<pwr<Op, 'H'>, V*, K, 'T'>>(Inv<pwr<Op, 'H'>, V*, K, 'T'>::inv));
70         TheOperators->Add("<-", new OneOperator2<V*, V*, Inv<pwr<Op, 'H'>, V*, K, 'T'>>(Inv<pwr<Op, 'H'>, V*, K, 'T'>::init));
71     }
72     TheOperators->Add("^", new OneBinaryOperator_st<BinaryOp<pwr<Op, trans>, Op*, typename std::conditional<trans == 'N', long, std::string*>::type>>);
73     TheOperators->Add("*", new OneBinaryOperator_st<assign<Inv<pwr<Op, trans>, V*, K, trans>, pwr<Op, trans>, V*>>);
74     TheOperators->Add("=", new OneOperator2<V*, V*, Inv<pwr<Op, trans>, V*, K, trans>>(Inv<pwr<Op, trans>, V*, K, trans>::inv));
75     TheOperators->Add("<-", new OneOperator2<V*, V*, Inv<pwr<Op, trans>, V*, K, trans>>(Inv<pwr<Op, trans>, V*, K, trans>::init));
76 }
77 template<class Op, template<class, class, class, char> class Prod, class V, class K = double, char N = 'N'>
addProd()78 void addProd() {
79     Dcl_Type<Prod<Op*, V*, K, N>>();
80     if(N == 'T') {
81         Dcl_Type<OpTrans<Op>>();
82         TheOperators->Add("\'", new OneOperator1<OpTrans<Op>, Op*>(Build));
83         TheOperators->Add("*", new OneOperator2<Prod<Op*, V*, K, N>, OpTrans<Op>, V*>(Build));
84     }
85     else
86         TheOperators->Add("*", new OneOperator2<Prod<Op*, V*, K, N>, Op*, V*>(Build));
87     TheOperators->Add("=", new OneOperator2<V*, V*, Prod<Op*, V*, K, N>>(Prod<Op*, V*, K, N>::mv));
88     TheOperators->Add("<-", new OneOperator2<V*, V*, Prod<Op*, V*, K, N>>(Prod<Op*, V*, K, N>::init));
89 }
90 
91 #endif // _COMMON_
92