simplify_expr.hpp 20.8 KB
Newer Older
1
2
3
4
5
6
7
/******************************************************************************
 *
 * AMDiS - Adaptive multidimensional simulations
 *
 * Copyright (C) 2013 Dresden University of Technology. All Rights Reserved.
 * Web: https://fusionforge.zih.tu-dresden.de/projects/amdis
 *
8
 * Authors:
9
10
11
12
13
14
15
16
17
 * Simon Vey, Thomas Witkowski, Andreas Naumann, Simon Praetorius, et al.
 *
 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 *
 *
 * This file is part of AMDiS
 *
 * See also license.opensource.txt in the distribution.
18
 *
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
 ******************************************************************************/



/** \file simplify_expr.hpp */

#ifndef AMDIS_SIMPLIFY_EXPRESSION_HPP
#define AMDIS_SIMPLIFY_EXPRESSION_HPP

#include "AMDiS_fwd.h"
#include "LazyOperatorTerm.h"
#include "value_expr.hpp"

#define SINGLE_ARG(...) __VA_ARGS__

34
namespace AMDiS
35
{
36
  namespace traits
37
38
39
  {
    template<typename T>
    struct is_ct_value : boost::mpl::false_ {};
40

41
42
    template<int I>
    struct is_ct_value< expressions::CValue<I> > : boost::mpl::true_ {};
43

44
  } // end namespace traits
45
46
47


  namespace expressions
48
  {
49
    template<typename Term>
50
51
52
53
    struct Simplify
    {
      typedef Term type;

54
55
      static type eval(Term const& t) { return t; }
    }; // by default do not simplify a term
56

57
  } // end namespace expressions
58

59
60

  // generator function for simplification
61
62
  template<typename Term>
  inline typename expressions::Simplify<Term>::type simplify(const Term& t)
63
64
65
  { return expressions::Simplify<Term>::eval(t); }


66
  namespace expressions
67
  {
Praetorius, Simon's avatar
Praetorius, Simon committed
68
69
70
71
72
73
74
75
76
    /// no simplification
    template<class T>
    struct Simplify< RValue<T> >
    {
      typedef RValue<T> type;

      static type eval(RValue<T> const& t) { return t; }
    };

77
78
    /// -(N) -> (-N)
    template<int N>
79
80
81
82
    struct Simplify< Negative<CValue<N> > >
    {
      typedef CValue<-N> type;

83
84
      static type eval(Negative<CValue<N> > const& t)
      { return CValue<-N>(); }
85

86
    };
87

88
89
    /// -0 -> 0
    template<>
90
91
    struct Simplify< Negative<CValue<0> > >
    {
92
      typedef CValue<0> type;
93
94

      static type eval(Negative<CValue<0> > const& t)
95
96
      { return CValue<0>(); }
    };
97

98
99
    /// (N) + (M) -> (N+M)
    template<int N, int M>
100
101
    struct Simplify< Add<CValue<N>, CValue<M> > >
    {
102
      typedef CValue<N+M> type;
103
104

      static type eval(Add<CValue<N>, CValue<M> > const& t)
105
106
      { return CValue<N+M>(); }
    };
107

108
109
    /// (N) - (M) -> (N-M)
    template<int N, int M>
110
111
    struct Simplify< Subtract<CValue<N>, CValue<M> > >
    {
112
      typedef CValue<N-M> type;
113
114

      static type eval(Subtract<CValue<N>, CValue<M> > const& t)
115
116
      { return CValue<N-M>(); }
    };
117

118
119
    /// (N) * (M) -> (N*M)
    template<int N, int M >
120
121
    struct Simplify< Mult<CValue<N>, CValue<M> > >
    {
122
      typedef CValue<N*M> type;
123
124

      static type eval(Mult<CValue<N>, CValue<M> > const& t)
125
126
      { return CValue<N*M>(); }
    };
127

128
129
    /// (M) ^ N -> (M^N)
    template<int N, int M >
130
131
    struct Simplify< Pow<N, CValue<M> > >
    {
132
      typedef CValue<meta::pow<M,N>::value> type;
133
134

      static type eval(Pow<N, CValue<M> > const& t)
135
136
      { return type(); }
    };
137

138
139
  } // end namespace expressions

140
  namespace expressions
141
142
143
  {
    /// X + 0 -> X
    template<typename Term>
144
    struct Simplify< Add<Term, CValue<0> > >
145
146
147
148
    {
      typedef typename Simplify<Term>::type type;

      static type eval(Add<Term, CValue<0> > const& t)
149
150
      { return simplify(t.term1); }
    };
151

152
153
154
    /// (N) + 0 -> X
    template<int N>
    struct Simplify< Add<CValue<N>, CValue<0> > >
155
156
157
158
    {
      typedef CValue<N> type;

      static type eval(Add<CValue<N>, CValue<0> > const&)
159
      { return CValue<N>(); }
Praetorius, Simon's avatar
Praetorius, Simon committed
160
    };
161

Praetorius, Simon's avatar
Praetorius, Simon committed
162
163
    /// X - 0 -> X
    template<typename Term>
164
    struct Simplify< Subtract<Term, CValue<0> > >
165
166
167
168
    {
      typedef typename Simplify<Term>::type type;

      static type eval(Subtract<Term, CValue<0> > const& t)
Praetorius, Simon's avatar
Praetorius, Simon committed
169
170
      { return simplify(t.term1); }
    };
171

172
173
174
    /// (N) - 0 -> (N)
    template<int N>
    struct Simplify< Subtract<CValue<N>, CValue<0> > >
175
176
177
178
    {
      typedef CValue<N> type;

      static type eval(Subtract<CValue<N>, CValue<0> > const&)
179
180
      { return CValue<N>(); }
    };
181

182
183
184
    /// 0 + X -> X
    template<typename Term>
    struct Simplify< Add<CValue<0>, Term> >
185
186
187
188
    {
      typedef typename Simplify<Term>::type type;

      static type eval(Add<CValue<0>, Term> const& t)
189
190
      { return simplify(t.term2); }
    };
191

192
193
194
    /// 0 + (N) -> (N)
    template<int N>
    struct Simplify< Add<CValue<0>, CValue<N> > >
195
196
197
198
    {
      typedef CValue<N> type;

      static type eval(Add<CValue<0>, CValue<N> > const&)
199
200
      { return CValue<N>(); }
    };
201

Praetorius, Simon's avatar
Praetorius, Simon committed
202
203
    /// 0 - X -> -X
    template<typename Term>
204
    struct Simplify< Subtract<CValue<0>, Term> >
205
206
207
208
    {
      typedef Negative<typename Simplify<Term>::type> type;

      static type eval(Subtract<CValue<0>, Term> const& t)
Praetorius, Simon's avatar
Praetorius, Simon committed
209
      { return -simplify(t.term2); }
210
    };
211

212
213
214
    /// 0 - (N) -> (-N)
    template<int N>
    struct Simplify< Subtract<CValue<0>, CValue<N> > >
215
216
217
218
    {
      typedef CValue<-N> type;

      static type eval(Subtract<CValue<0>, CValue<N> > const&)
219
220
      { return CValue<-N>(); }
    };
221

222
223
224
    /// 0 - 0 -> 0
    template<>
    struct Simplify< Subtract<CValue<0>, CValue<0> > >
225
226
227
228
    {
      typedef CValue<0> type;

      static type eval(Subtract<CValue<0>, CValue<0> > const&)
229
230
      { return type(); }
    };
231

232
233
234
    /// 0 + 0 -> 0
    template<>
    struct Simplify< Add<CValue<0>, CValue<0> > >
235
236
237
238
    {
      typedef CValue<0> type;

      static type eval(Add<CValue<0>, CValue<0> > const&)
239
240
      { return type(); }
    };
241

242
243
    /// X * 0 -> 0
    template<typename Term>
244
245
246
247
248
    struct Simplify< Mult<Term, CValue<0> > >
    {
      typedef CValue<0> type;

      static type eval(Mult<Term, CValue<0> > const&)
249
250
      { return CValue<0>(); }
    };
251

252
253
    /// (N) * 0 -> 0
    template<int N>
254
255
256
257
258
    struct Simplify< Mult<CValue<N>, CValue<0> > >
    {
      typedef CValue<0> type;

      static type eval(Mult<CValue<N>, CValue<0> > const&)
259
260
      { return CValue<0>(); }
    };
261

262
263
    /// 0 * X -> 0
    template<typename Term>
264
265
266
267
268
    struct Simplify< Mult<CValue<0>, Term> >
    {
      typedef CValue<0> type;

      static type eval(Mult<CValue<0>, Term> const& t)
269
270
      { return CValue<0>(); }
    };
271

272
273
    /// 0 * (N) -> 0
    template<int N>
274
275
276
277
278
    struct Simplify< Mult<CValue<0>, CValue<N> > >
    {
      typedef CValue<0> type;

      static type eval(Mult<CValue<0>, CValue<N> > const&)
279
280
      { return CValue<0>(); }
    };
281

282
283
    /// X * 1 -> X
    template<typename Term>
284
285
286
287
288
    struct Simplify< Mult<Term, CValue<1> > >
    {
      typedef typename Simplify<Term>::type type;

      static type eval(Mult<Term, CValue<1> > const& t)
289
290
      { return simplify(t.term1); }
    };
291

292
293
    /// (N) * 1 -> (N)
    template<int N>
294
295
296
297
298
    struct Simplify< Mult<CValue<N>, CValue<1> > >
    {
      typedef CValue<N> type;

      static type eval(Mult<CValue<N>, CValue<1> > const&)
299
300
      { return CValue<N>(); }
    };
301

302
303
    /// 1 * X -> X
    template<typename Term>
304
305
306
307
308
    struct Simplify< Mult<CValue<1>, Term> >
    {
      typedef typename Simplify<Term>::type type;

      static type eval(Mult<CValue<1>, Term> const& t)
309
310
      { return simplify(t.term2); }
    };
311

312
313
    /// 1 * (N) -> (N)
    template<int N>
314
315
316
317
318
    struct Simplify< Mult<CValue<1>, CValue<N> > >
    {
      typedef CValue<N> type;

      static type eval(Mult<CValue<1>, CValue<N> > const&)
319
320
      { return CValue<N>(); }
    };
321

322
323
    /// X * -1 -> -X
    template<typename Term>
324
325
326
327
328
    struct Simplify< Mult<Term, CValue<-1> > >
    {
      typedef Negative<typename Simplify<Term>::type> type;

      static type eval(Mult<Term, CValue<-1> > const& t)
329
330
      { return -simplify(t.term1); }
    };
331

332
333
    /// (N) * -1 -> (-N)
    template<int N>
334
335
336
337
338
    struct Simplify< Mult<CValue<N>, CValue<-1> > >
    {
      typedef CValue<-N> type;

      static type eval(Mult<CValue<N>, CValue<-1> > const&)
339
340
      { return CValue<-N>(); }
    };
341

342
343
    /// -1 * X -> -X
    template<typename Term>
344
345
346
347
348
    struct Simplify< Mult<CValue<-1>, Term> >
    {
      typedef Negative<typename Simplify<Term>::type> type;

      static type eval(Mult<CValue<-1>, Term> const& t)
349
350
      { return -simplify(t.term2); }
    };
351

352
353
    /// -1 * (N) -> (-N)
    template<int N>
354
355
356
357
358
    struct Simplify< Mult<CValue<-1>, CValue<N> > >
    {
      typedef CValue<-N> type;

      static type eval(Mult<CValue<-1>, CValue<N> > const&)
359
360
      { return type(); }
    };
361
362


363
364
365
366
367
#define MULT_CVALUE_IMPL(_A_,_B_) \
  template<> struct Simplify< Mult<CValue<_A_>, CValue<_B_> > > { \
    typedef CValue<_A_ * _B_> type; \
    static type eval(Mult<CValue<_A_>, CValue<_B_> > const&) { return type(); } \
  };
368

369
370
371
372
373
374
375
376
377
378
    // implement all specializations with special values
    MULT_CVALUE_IMPL(0,0)
    MULT_CVALUE_IMPL(0,1)
    MULT_CVALUE_IMPL(1,0)
    MULT_CVALUE_IMPL(1,1)
    MULT_CVALUE_IMPL(0,-1)
    MULT_CVALUE_IMPL(-1,0)
    MULT_CVALUE_IMPL(-1,-1)
    MULT_CVALUE_IMPL(1,-1)
    MULT_CVALUE_IMPL(-1,1)
379

380
381
  } // end namespace expressions

382

383
384
385
386
387
  namespace expressions
  {
    // move constants to the beginning of the expression
//     /// X * N -> N * X
//     template<int N, typename Term>
388
389
390
391
392
//     struct Simplify< Mult<Term, CValue<N> > >
//     {
//       typedef Mult<CValue<N>, Term> type;
//
//       static type eval(Mult<Term, CValue<N> > const& t)
393
394
//       { return CValue<N>() * t.term1; }
//     };
395

396
  } // end namespace expressions
397
398

  namespace expressions
399
400
401
  {
    /// X / X -> 1
    template<typename Term>
402
403
    struct Simplify< Mult<Term, MultInverse<Term> > >
    {
404
      typedef CValue<1> type;
405
406
407

      static type eval(Mult<Term, MultInverse<Term> > const& t)
      { return CValue<1>(); }
408
    };
409

410
411
    /// X / X -> 1
    template<typename Term>
412
413
    struct Simplify< Mult<MultInverse<Term>, Term> >
    {
414
      typedef CValue<1> type;
415
416

      static type eval(Mult<MultInverse<Term>, Term> const& t)
417
418
      { return CValue<1>(); }
    };
419

420
421
    /// -(-X) -> X
    template<typename Term>
422
423
    struct Simplify< Negative<Negative<Term> > >
    {
424
      typedef Term type;
425
426

      static type eval(Negative<Negative<Term> > const& t)
427
428
      { return t.term.term; }
    };
429

430
431
    /// (X^(-1))^(-1) -> X
    template<typename Term>
432
433
    struct Simplify< MultInverse<MultInverse<Term> > >
    {
434
      typedef Term type;
435
436

      static type eval(MultInverse<MultInverse<Term> > const& t)
437
438
      { return t.term.term; }
    };
439

440
    /// (X + (-Y)) -> X - Y
441
    template<typename X, typename Y>
442
443
    struct Simplify< Negative<Add<X, Negative<Y> > > >
    {
444
      typedef Subtract<X, Y> type;
445
446

      static type eval(Negative<Add<X, Negative<Y> > > const& t)
447
448
      { return t.term1 - t.term2.term; }
    };
449

450
451
    /// -(X - Y) -> Y - X
    template<typename X, typename Y>
452
453
    struct Simplify< Negative<Subtract<X, Y> > >
    {
454
      typedef Subtract<Y, X> type;
455
456

      static type eval(Negative<Subtract<X, Y> > const& t)
457
      { return t.term.term2 - t.term.term1; }
458
    };
459

460
  } // end namespace expressions
461
462
463


  namespace expressions
464
465
466
  {
    /// X^1 -> X
    template<typename Term>
467
    struct Simplify< Pow<1, Term> >
468
469
470
    {
      typedef Term type;

471
472
      static type eval(Pow<1,Term> const& t) { return t.term; }
    };
473

474
475
    /// X^0 -> 1
    template<typename Term>
476
    struct Simplify< Pow<0, Term> >
477
    {
478
      typedef CValue<1> type;
479

480
481
482
483
      static type eval(Pow<0,Term> const& t) { return CValue<1>(); }
    };

  } // end namespace expressions
484
485
486


  namespace expressions
487
488
489
  {
    /// (XY) / (XZ) -> Y/Z
    template<typename X, typename Y, typename Z>
490
491
492
493
    struct Simplify< Mult<Mult<X,Y>, MultInverse<Mult<X,Z> > > >
    {
      typedef Mult<Y, MultInverse<Z> > type;

494
      // Y = t.term1.term2, Z = t.term2.term.term2
495
496
      static type eval(Mult<Mult<X,Y>, MultInverse<Mult<X,Z> > > const& t)
      { return t.term1.term2 / t.term2.term.term2; }
497
    };
498

499
500
    /// (XY) / X -> Y
    template<typename X, typename Y>
501
502
    struct Simplify< Mult<Mult<X,Y>, MultInverse<X> > >
    {
503
      typedef Y type;
504

505
      // Y = t.term1.term2
506
      static type eval(Mult<Mult<X,Y>, MultInverse<X> > const& t)
507
508
      { return t.term1.term2; }
    };
509

510
511
    /// X / (XY) -> 1/Y
    template<typename X, typename Y>
512
513
    struct Simplify< Mult<X, MultInverse<Mult<X,Y> > > >
    {
514
      typedef MultInverse<Y> type;
515

516
      // Y = t.term2.term.term2
517
      static type eval(Mult<Mult<X,Y>, MultInverse<X> > const& t)
518
519
      { return MultInverse<Y>(t.term2.term.term2); }
    };
520

521
522
    /// N*(M*X) -> (N*M) * X
    template<int N, int M, typename X>
523
524
    struct Simplify< Mult<CValue<N>, Mult<CValue<M>, X> > >
    {
525
      typedef Mult<CValue<N*M>, X> type;
526

527
      // X = t.term2.term2
528
529
      static type eval(Mult<CValue<N>, Mult<CValue<M>, X> > const& t)
      { return CValue<N*M>() * (t.term2.term2); }
530
    };
531

532
533
    /// 0*(M*X) -> 0
    template<int M, typename X>
534
535
    struct Simplify< Mult<CValue<0>, Mult<CValue<M>, X> > >
    {
536
      typedef CValue<0> type;
537

538
      // X = t.term2.term2
539
540
      static type eval(Mult<CValue<0>, Mult<CValue<M>, X> > const& t)
      { return type(); }
541
    };
542

543
544
    /// 1*(M*X) -> M * X
    template<int M, typename X>
545
546
    struct Simplify< Mult<CValue<1>, Mult<CValue<M>, X> > >
    {
547
      typedef Mult<CValue<M>, X> type;
548

549
      // X = t.term2.term2
550
551
      static type eval(Mult<CValue<1>, Mult<CValue<M>, X> > const& t)
      { return CValue<M>() * (t.term2.term2); }
552
    };
553

554
555
    /// -1*(M*X) -> (-M) * X
    template<int M, typename X>
556
557
    struct Simplify< Mult<CValue<-1>, Mult<CValue<M>, X> > >
    {
558
      typedef Mult<CValue<-M>, X> type;
559

560
      // X = t.term2.term2
561
562
      static type eval(Mult<CValue<-1>, Mult<CValue<M>, X> > const& t)
      { return CValue<-M>() * (t.term2.term2); }
563
    };
564
565


566
567
    /// N*(X*M) -> (N*M) * X
    template<int N, int M, typename X>
568
569
570
571
    struct Simplify< Mult<CValue<N>, Mult<X, CValue<M> > > >
    {
      typedef Mult<CValue<N*M>, X> type;

572
      // X = t.term2.term1
573
574
      static type eval(Mult<CValue<N>, Mult<X, CValue<M> > > const& t)
      { return CValue<N*M>() * (t.term2.term1); }
575
    };
576

577
578
    /// 0*(X*M) -> 0
    template<int M, typename X>
579
580
581
582
    struct Simplify< Mult<CValue<0>, Mult<X, CValue<M> > > >
    {
      typedef CValue<0> type;

583
      // X = t.term2.term1
584
585
      static type eval(Mult<CValue<0>, Mult<X, CValue<M> > > const& t)
      { return type(); }
586
    };
587

588
589
    /// 1*(X*M) -> M * X
    template<int M, typename X>
590
591
592
593
    struct Simplify< Mult<CValue<1>, Mult<X, CValue<M> > > >
    {
      typedef Mult<CValue<M>, X> type;

594
      // X = t.term2.term1
595
596
      static type eval(Mult<CValue<1>, Mult<X, CValue<M> > > const& t)
      { return CValue<M>() * (t.term2.term1); }
597
    };
598

599
600
    /// -1*(X*M) -> (-M) * X
    template<int M, typename X>
601
602
603
604
    struct Simplify< Mult<CValue<-1>, Mult<X, CValue<M> > > >
    {
      typedef Mult<CValue<-M>, X> type;

605
      // X = t.term2.term1
606
607
      static type eval(Mult<CValue<-1>, Mult<X, CValue<M> > > const& t)
      { return CValue<-M>() * (t.term2.term1); }
608
    };
609
610


611
612
    /// (M*X)*N -> (N*M) * X
    template<int N, int M, typename X>
613
614
615
616
    struct Simplify< Mult<Mult<CValue<M>, X>, CValue<N> > >
    {
      typedef Mult<CValue<N*M>, X> type;

617
      // X = t.term1.term2
618
      static type eval(Mult<Mult<CValue<M>, X>, CValue<N> > const& t)
619
      { return CValue<N*M>() * (t.term1.term2); }
620
621
    };

622
623
    /// (M*X)*0 -> 0
    template<int M, typename X>
624
625
626
627
    struct Simplify< Mult<Mult<CValue<M>, X>, CValue<0> > >
    {
      typedef CValue<0> type;

628
      // X = t.term1.term2
629
      static type eval(Mult<Mult<CValue<M>, X>, CValue<0> > const& t)
630
631
      { return type(); }
    };
632

633
634
    /// (M*X)*1 -> M * X
    template<int M, typename X>
635
636
637
638
    struct Simplify< Mult<Mult<CValue<M>, X>, CValue<1> > >
    {
      typedef Mult<CValue<M>, X> type;

639
      // X = t.term1.term2
640
      static type eval(Mult<Mult<CValue<M>, X>, CValue<1> > const& t)
641
      { return CValue<M>() * (t.term1.term2); }
642
643
    };

644
645
    /// (M*X)*-1 -> (-M) * X
    template<int M, typename X>
646
647
648
649
    struct Simplify< Mult<Mult<CValue<M>, X>, CValue<-1> > >
    {
      typedef Mult<CValue<-M>, X> type;

650
      // X = t.term1.term2
651
      static type eval(Mult<Mult<CValue<M>, X>, CValue<-1> > const& t)
652
      { return CValue<-M>() * (t.term1.term2); }
653
    };
654
655


656
657
    /// (X*M)*N -> (N*M) * X
    template<int N, int M, typename X>
658
659
660
661
    struct Simplify< Mult<Mult<X, CValue<M> >, CValue<N> > >
    {
      typedef Mult<CValue<N*M>, X> type;

662
      // X = t.term1.term1
663
      static type eval(Mult<Mult<X, CValue<M> >, CValue<N> > const& t)
664
      { return CValue<N*M>() * (t.term1.term1); }
665
666
    };

667
668
    /// (X*M)*0 -> 0
    template<int M, typename X>
669
670
671
672
    struct Simplify< Mult<Mult<X, CValue<M> >, CValue<0> > >
    {
      typedef CValue<0> type;

673
      // X = t.term1.term1
674
      static type eval(Mult<Mult<X, CValue<M> >, CValue<0> > const& t)
675
676
      { return type(); }
    };
677

678
679
    /// (X*M)*1 -> M * X
    template<int M, typename X>
680
681
682
683
    struct Simplify< Mult<Mult<X, CValue<M> >, CValue<1> > >
    {
      typedef Mult<CValue<M>, X> type;

684
      // X = t.term1.term1
685
      static type eval(Mult<Mult<X, CValue<M> >, CValue<1> > const& t)
686
      { return CValue<M>() * (t.term1.term1); }
687
688
    };

689
690
    /// (X*M)*-1 -> (-M) * X
    template<int M, typename X>
691
692
693
694
    struct Simplify< Mult<Mult<X, CValue<M> >, CValue<-1> > >
    {
      typedef Mult<CValue<-M>, X> type;

695
      // X = t.term1.term1
696
      static type eval(Mult<Mult<X, CValue<M> >, CValue<-1> > const& t)
697
      { return CValue<-M>() * (t.term1.term1); }
698
699
700
    };


701
702
    /// X * (N * Y) -> N * (X * Y)
    template<typename X, int N, typename Y>
703
704
705
706
    struct Simplify< Mult<X, Mult<CValue<N>, Y> > >
    {
      typedef Mult<CValue<N>, Mult<X,Y> > type;

707
708
      // X = t.term1
      // Y = t.term2.term2
709
      static type eval(Mult<X, Mult<CValue<N>, Y> > const& t)
710
711
      { return CValue<N>() * (t.term1 * t.term2.term2); }
    };
712
713


714
715
    /// -(N*X) -> (-N) * X
    template<int N, typename X>
716
717
    struct Simplify< Negative<Mult<CValue<N>,X> > >
    {
718
      typedef Mult<CValue<-N>, typename Simplify<X>::type> type;
719

720
      // X = t.term.term2
721
      static type eval(Negative<Mult<CValue<N>,X> > const& t)
722
      { return CValue<-N>() * simplify(t.term.term2); }
723
724
725
726
727
    };

  } // end namespace expressions


728
  namespace expressions
729
730
731
  {
    /// A + B -> simplify(A) + simplify(B)
    template<typename Term1, typename Term2>
732
733
    class Simplify< Add<Term1, Term2> >
    {
734
735
      typedef typename Simplify<Term1>::type S1;
      typedef typename Simplify<Term2>::type S2;
736

737
738
    public:
      typedef Add<S1, S2> type;
739
740

      static type eval(Add<Term1, Term2> const& t)
741
742
743
744
      {
	return simplify(t.term1) + simplify(t.term2);
      }
    };
745

746
747
    /// A - B -> simplify(A) - simplify(B)
    template<typename Term1, typename Term2>
748
749
    class Simplify< Subtract<Term1, Term2> >
    {
750
751
      typedef typename Simplify<Term1>::type S1;
      typedef typename Simplify<Term2>::type S2;
752

753
754
    public:
      typedef Subtract<S1, S2> type;
755
756

      static type eval(Subtract<Term1, Term2> const& t)
757
758
759
760
      {
	return simplify(t.term1) - simplify(t.term2);
      }
    };
761

762
763
    /// A * B -> simplify(A) * simplify(B)
    template<typename Term1, typename Term2>
764
765
    class Simplify< Mult<Term1, Term2> >
    {
766
767
      typedef typename Simplify<Term1>::type S1;
      typedef typename Simplify<Term2>::type S2;
768

769
770
    public:
      typedef Mult<S1, S2> type;
771
772

      static type eval(Mult<Term1, Term2> const& t)
773
774
775
776
      {
	return simplify(t.term1) * simplify(t.term2);
      }
    };
777

778
779
    /// X(A) -> X(simplify(A))
    template<template<class> class Outer, class Inner>
780
781
    class Simplify< Outer<Inner> >
    {
782
      typedef typename Simplify<Inner>::type S;
783

784
785
    public:
      typedef Outer<S> type;
786
787

      static type eval(Outer<Inner> const& t)
788
789
790
791
792
793
794
795
796
797
798
      {
	return type(simplify(t.term));
      }
    };

  } // end namespace expressions


  // =============================================================================
  // multiple simplifications

799
800
  namespace expressions
  {
801
    template<int N, typename Term, typename Enabled = void>
802
803
    struct SimplifyRecursive
    {
804
805
      typedef typename Simplify< typename SimplifyRecursive<N-1, Term>::type >::type type;
    };
806

807
808
    template<typename Term>
    struct SimplifyRecursive<1, Term>
809
    {
810
811
      typedef typename Simplify< Term >::type type;
    };
812

813
814
    template<int N, typename Term >
    struct SimplifyRecursive<N, Term, typename boost::enable_if_c<(N <= 0)>::type>
815
    {
816
817
      typedef Term type;
    };
818

819
820
  } // end namespace expressions

821
822

  template<int N, typename Term>
823
824
825
  inline typename expressions::SimplifyRecursive<N, Term>::type
  simplify(const Term& t);

826
  template<int N, typename Term>
827
828
829
  inline typename expressions::SimplifyRecursive<N, Term>::type
  simplify(const Term& t, boost::mpl::int_<N>) { return simplify(simplify<N-1>(t)); }

830
  template<typename Term>
831
832
833
  inline typename expressions::SimplifyRecursive<1, Term>::type
  simplify(const Term& t, boost::mpl::int_<1>) { return simplify(t); }

834
  template<typename Term>
835
836
837
  inline typename expressions::SimplifyRecursive<0, Term>::type
  simplify(const Term& t, boost::mpl::int_<0>) { return t; }

838
  template<int N, typename Term>
839
840
841
842
843
844
  inline typename expressions::SimplifyRecursive<N, Term>::type
  simplify(const Term& t) { return simplify(t, boost::mpl::int_<N>()); }

} // end namespace AMDiS

#endif // AMDIS_SIMPLIFY_EXPRESSION_HPP