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