simplify_expr.hpp 21.2 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
79
80
81
82
83
84
85
86
    /// -(n) -> (-n)
    template<class T>
    struct Simplify< Negative<RValue<T> > >
    {
      typedef RValue<T> type;

      static type eval(Negative<RValue<T> > const& t)
      { return RValue<T>(-t.term.value); }
    };

87
88
    /// -(N) -> (-N)
    template<int N>
89
90
91
92
    struct Simplify< Negative<CValue<N> > >
    {
      typedef CValue<-N> type;

93
94
95
      static type eval(Negative<CValue<N> > const& t)
      { return CValue<-N>(); }
    };
96

97
98
    /// -0 -> 0
    template<>
99
100
    struct Simplify< Negative<CValue<0> > >
    {
101
      typedef CValue<0> type;
102
103

      static type eval(Negative<CValue<0> > const& t)
104
105
      { return CValue<0>(); }
    };
106

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

      static type eval(Add<CValue<N>, CValue<M> > const& t)
114
115
      { return CValue<N+M>(); }
    };
116

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

      static type eval(Subtract<CValue<N>, CValue<M> > const& t)
124
125
      { return CValue<N-M>(); }
    };
126

127
128
    /// (N) * (M) -> (N*M)
    template<int N, int M >
129
130
    struct Simplify< Mult<CValue<N>, CValue<M> > >
    {
131
      typedef CValue<N*M> type;
132
133

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

137
138
    /// (M) ^ N -> (M^N)
    template<int N, int M >
139
140
    struct Simplify< Pow<N, CValue<M> > >
    {
141
      typedef CValue<meta::pow<M,N>::value> type;
142
143

      static type eval(Pow<N, CValue<M> > const& t)
144
145
      { return type(); }
    };
146

147
148
  } // end namespace expressions

149
  namespace expressions
150
151
152
  {
    /// X + 0 -> X
    template<typename Term>
153
    struct Simplify< Add<Term, CValue<0> > >
154
155
156
157
    {
      typedef typename Simplify<Term>::type type;

      static type eval(Add<Term, CValue<0> > const& t)
158
159
      { return simplify(t.term1); }
    };
160

161
162
163
    /// (N) + 0 -> X
    template<int N>
    struct Simplify< Add<CValue<N>, CValue<0> > >
164
165
166
167
    {
      typedef CValue<N> type;

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

Praetorius, Simon's avatar
Praetorius, Simon committed
171
172
    /// X - 0 -> X
    template<typename Term>
173
    struct Simplify< Subtract<Term, CValue<0> > >
174
175
176
177
    {
      typedef typename Simplify<Term>::type type;

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

181
182
183
    /// (N) - 0 -> (N)
    template<int N>
    struct Simplify< Subtract<CValue<N>, CValue<0> > >
184
185
186
187
    {
      typedef CValue<N> type;

      static type eval(Subtract<CValue<N>, CValue<0> > const&)
188
189
      { return CValue<N>(); }
    };
190

191
192
193
    /// 0 + X -> X
    template<typename Term>
    struct Simplify< Add<CValue<0>, Term> >
194
195
196
197
    {
      typedef typename Simplify<Term>::type type;

      static type eval(Add<CValue<0>, Term> const& t)
198
199
      { return simplify(t.term2); }
    };
200

201
202
203
    /// 0 + (N) -> (N)
    template<int N>
    struct Simplify< Add<CValue<0>, CValue<N> > >
204
205
206
207
    {
      typedef CValue<N> type;

      static type eval(Add<CValue<0>, CValue<N> > const&)
208
209
      { return CValue<N>(); }
    };
210

Praetorius, Simon's avatar
Praetorius, Simon committed
211
212
    /// 0 - X -> -X
    template<typename Term>
213
    struct Simplify< Subtract<CValue<0>, Term> >
214
215
216
217
    {
      typedef Negative<typename Simplify<Term>::type> type;

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

221
222
223
    /// 0 - (N) -> (-N)
    template<int N>
    struct Simplify< Subtract<CValue<0>, CValue<N> > >
224
225
226
227
    {
      typedef CValue<-N> type;

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

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

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

241
242
243
    /// 0 + 0 -> 0
    template<>
    struct Simplify< Add<CValue<0>, CValue<0> > >
244
245
246
247
    {
      typedef CValue<0> type;

      static type eval(Add<CValue<0>, CValue<0> > const&)
248
249
      { return type(); }
    };
250

251
252
    /// X * 0 -> 0
    template<typename Term>
253
254
255
256
257
    struct Simplify< Mult<Term, CValue<0> > >
    {
      typedef CValue<0> type;

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

261
262
    /// (N) * 0 -> 0
    template<int N>
263
264
265
266
267
    struct Simplify< Mult<CValue<N>, CValue<0> > >
    {
      typedef CValue<0> type;

      static type eval(Mult<CValue<N>, CValue<0> > const&)
268
269
      { return CValue<0>(); }
    };
270

271
272
    /// 0 * X -> 0
    template<typename Term>
273
274
275
276
277
    struct Simplify< Mult<CValue<0>, Term> >
    {
      typedef CValue<0> type;

      static type eval(Mult<CValue<0>, Term> const& t)
278
279
      { return CValue<0>(); }
    };
280

281
282
    /// 0 * (N) -> 0
    template<int N>
283
284
285
286
287
    struct Simplify< Mult<CValue<0>, CValue<N> > >
    {
      typedef CValue<0> type;

      static type eval(Mult<CValue<0>, CValue<N> > const&)
288
289
      { return CValue<0>(); }
    };
290

291
292
    /// X * 1 -> X
    template<typename Term>
293
294
295
296
297
    struct Simplify< Mult<Term, CValue<1> > >
    {
      typedef typename Simplify<Term>::type type;

      static type eval(Mult<Term, CValue<1> > const& t)
298
299
      { return simplify(t.term1); }
    };
300

301
302
    /// (N) * 1 -> (N)
    template<int N>
303
304
305
306
307
    struct Simplify< Mult<CValue<N>, CValue<1> > >
    {
      typedef CValue<N> type;

      static type eval(Mult<CValue<N>, CValue<1> > const&)
308
309
      { return CValue<N>(); }
    };
310

311
312
    /// 1 * X -> X
    template<typename Term>
313
314
315
316
317
    struct Simplify< Mult<CValue<1>, Term> >
    {
      typedef typename Simplify<Term>::type type;

      static type eval(Mult<CValue<1>, Term> const& t)
318
319
      { return simplify(t.term2); }
    };
320

321
322
    /// 1 * (N) -> (N)
    template<int N>
323
324
325
326
327
    struct Simplify< Mult<CValue<1>, CValue<N> > >
    {
      typedef CValue<N> type;

      static type eval(Mult<CValue<1>, CValue<N> > const&)
328
329
      { return CValue<N>(); }
    };
330

331
332
    /// X * -1 -> -X
    template<typename Term>
333
334
335
336
337
    struct Simplify< Mult<Term, CValue<-1> > >
    {
      typedef Negative<typename Simplify<Term>::type> type;

      static type eval(Mult<Term, CValue<-1> > const& t)
338
339
      { return -simplify(t.term1); }
    };
340

341
342
    /// (N) * -1 -> (-N)
    template<int N>
343
344
345
346
347
    struct Simplify< Mult<CValue<N>, CValue<-1> > >
    {
      typedef CValue<-N> type;

      static type eval(Mult<CValue<N>, CValue<-1> > const&)
348
349
      { return CValue<-N>(); }
    };
350

351
352
    /// -1 * X -> -X
    template<typename Term>
353
354
355
356
357
    struct Simplify< Mult<CValue<-1>, Term> >
    {
      typedef Negative<typename Simplify<Term>::type> type;

      static type eval(Mult<CValue<-1>, Term> const& t)
358
359
      { return -simplify(t.term2); }
    };
360

361
362
    /// -1 * (N) -> (-N)
    template<int N>
363
364
365
366
367
    struct Simplify< Mult<CValue<-1>, CValue<N> > >
    {
      typedef CValue<-N> type;

      static type eval(Mult<CValue<-1>, CValue<N> > const&)
368
369
      { return type(); }
    };
370
371


372
373
374
375
376
#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(); } \
  };
377

378
379
380
381
382
383
384
385
386
387
    // 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)
388

389
390
  } // end namespace expressions

391

392
393
394
395
396
  namespace expressions
  {
    // move constants to the beginning of the expression
//     /// X * N -> N * X
//     template<int N, typename Term>
397
398
399
400
401
//     struct Simplify< Mult<Term, CValue<N> > >
//     {
//       typedef Mult<CValue<N>, Term> type;
//
//       static type eval(Mult<Term, CValue<N> > const& t)
402
403
//       { return CValue<N>() * t.term1; }
//     };
404

405
  } // end namespace expressions
406
407

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

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

419
420
    /// X / X -> 1
    template<typename Term>
421
422
    struct Simplify< Mult<MultInverse<Term>, Term> >
    {
423
      typedef CValue<1> type;
424
425

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

429
430
    /// -(-X) -> X
    template<typename Term>
431
432
    struct Simplify< Negative<Negative<Term> > >
    {
433
      typedef Term type;
434
435

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

439
440
    /// (X^(-1))^(-1) -> X
    template<typename Term>
441
442
    struct Simplify< MultInverse<MultInverse<Term> > >
    {
443
      typedef Term type;
444
445

      static type eval(MultInverse<MultInverse<Term> > const& t)
446
447
      { return t.term.term; }
    };
448

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

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

459
460
461
462
463
464
465
466
467
    template<typename Y>
    struct Simplify< Add<CValue<0>, Negative<Y> > >
    {
      typedef Negative<Y> type;

      static type eval(Add<CValue<0>, Negative<Y> > const& t)
      { return t.term2; }
    };

468
469
    /// -(X - Y) -> Y - X
    template<typename X, typename Y>
470
471
    struct Simplify< Negative<Subtract<X, Y> > >
    {
472
      typedef Subtract<Y, X> type;
473
474

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

478
  } // end namespace expressions
479
480
481


  namespace expressions
482
483
484
  {
    /// X^1 -> X
    template<typename Term>
485
    struct Simplify< Pow<1, Term> >
486
487
488
    {
      typedef Term type;

489
490
      static type eval(Pow<1,Term> const& t) { return t.term; }
    };
491

492
493
    /// X^0 -> 1
    template<typename Term>
494
    struct Simplify< Pow<0, Term> >
495
    {
496
      typedef CValue<1> type;
497

498
499
500
501
      static type eval(Pow<0,Term> const& t) { return CValue<1>(); }
    };

  } // end namespace expressions
502
503
504


  namespace expressions
505
506
507
  {
    /// (XY) / (XZ) -> Y/Z
    template<typename X, typename Y, typename Z>
508
509
510
511
    struct Simplify< Mult<Mult<X,Y>, MultInverse<Mult<X,Z> > > >
    {
      typedef Mult<Y, MultInverse<Z> > type;

512
      // Y = t.term1.term2, Z = t.term2.term.term2
513
514
      static type eval(Mult<Mult<X,Y>, MultInverse<Mult<X,Z> > > const& t)
      { return t.term1.term2 / t.term2.term.term2; }
515
    };
516

517
518
    /// (XY) / X -> Y
    template<typename X, typename Y>
519
520
    struct Simplify< Mult<Mult<X,Y>, MultInverse<X> > >
    {
521
      typedef Y type;
522

523
      // Y = t.term1.term2
524
      static type eval(Mult<Mult<X,Y>, MultInverse<X> > const& t)
525
526
      { return t.term1.term2; }
    };
527

528
529
    /// X / (XY) -> 1/Y
    template<typename X, typename Y>
530
531
    struct Simplify< Mult<X, MultInverse<Mult<X,Y> > > >
    {
532
      typedef MultInverse<Y> type;
533

534
      // Y = t.term2.term.term2
535
      static type eval(Mult<Mult<X,Y>, MultInverse<X> > const& t)
536
537
      { return MultInverse<Y>(t.term2.term.term2); }
    };
538

539
540
    /// N*(M*X) -> (N*M) * X
    template<int N, int M, typename X>
541
542
    struct Simplify< Mult<CValue<N>, Mult<CValue<M>, X> > >
    {
543
      typedef Mult<CValue<N*M>, X> type;
544

545
      // X = t.term2.term2
546
547
      static type eval(Mult<CValue<N>, Mult<CValue<M>, X> > const& t)
      { return CValue<N*M>() * (t.term2.term2); }
548
    };
549

550
551
    /// 0*(M*X) -> 0
    template<int M, typename X>
552
553
    struct Simplify< Mult<CValue<0>, Mult<CValue<M>, X> > >
    {
554
      typedef CValue<0> type;
555

556
      // X = t.term2.term2
557
558
      static type eval(Mult<CValue<0>, Mult<CValue<M>, X> > const& t)
      { return type(); }
559
    };
560

561
562
    /// 1*(M*X) -> M * X
    template<int M, typename X>
563
564
    struct Simplify< Mult<CValue<1>, Mult<CValue<M>, X> > >
    {
565
      typedef Mult<CValue<M>, X> type;
566

567
      // X = t.term2.term2
568
569
      static type eval(Mult<CValue<1>, Mult<CValue<M>, X> > const& t)
      { return CValue<M>() * (t.term2.term2); }
570
    };
571

572
573
    /// -1*(M*X) -> (-M) * X
    template<int M, typename X>
574
575
    struct Simplify< Mult<CValue<-1>, Mult<CValue<M>, X> > >
    {
576
      typedef Mult<CValue<-M>, X> type;
577

578
      // X = t.term2.term2
579
580
      static type eval(Mult<CValue<-1>, Mult<CValue<M>, X> > const& t)
      { return CValue<-M>() * (t.term2.term2); }
581
    };
582
583


584
585
    /// N*(X*M) -> (N*M) * X
    template<int N, int M, typename X>
586
587
588
589
    struct Simplify< Mult<CValue<N>, Mult<X, CValue<M> > > >
    {
      typedef Mult<CValue<N*M>, X> type;

590
      // X = t.term2.term1
591
592
      static type eval(Mult<CValue<N>, Mult<X, CValue<M> > > const& t)
      { return CValue<N*M>() * (t.term2.term1); }
593
    };
594

595
596
    /// 0*(X*M) -> 0
    template<int M, typename X>
597
598
599
600
    struct Simplify< Mult<CValue<0>, Mult<X, CValue<M> > > >
    {
      typedef CValue<0> type;

601
      // X = t.term2.term1
602
603
      static type eval(Mult<CValue<0>, Mult<X, CValue<M> > > const& t)
      { return type(); }
604
    };
605

606
607
    /// 1*(X*M) -> M * X
    template<int M, typename X>
608
609
610
611
    struct Simplify< Mult<CValue<1>, Mult<X, CValue<M> > > >
    {
      typedef Mult<CValue<M>, X> type;

612
      // X = t.term2.term1
613
614
      static type eval(Mult<CValue<1>, Mult<X, CValue<M> > > const& t)
      { return CValue<M>() * (t.term2.term1); }
615
    };
616

617
618
    /// -1*(X*M) -> (-M) * X
    template<int M, typename X>
619
620
621
622
    struct Simplify< Mult<CValue<-1>, Mult<X, CValue<M> > > >
    {
      typedef Mult<CValue<-M>, X> type;

623
      // X = t.term2.term1
624
625
      static type eval(Mult<CValue<-1>, Mult<X, CValue<M> > > const& t)
      { return CValue<-M>() * (t.term2.term1); }
626
    };
627
628


629
630
    /// (M*X)*N -> (N*M) * X
    template<int N, int M, typename X>
631
632
633
634
    struct Simplify< Mult<Mult<CValue<M>, X>, CValue<N> > >
    {
      typedef Mult<CValue<N*M>, X> type;

635
      // X = t.term1.term2
636
      static type eval(Mult<Mult<CValue<M>, X>, CValue<N> > const& t)
637
      { return CValue<N*M>() * (t.term1.term2); }
638
639
    };

640
641
    /// (M*X)*0 -> 0
    template<int M, typename X>
642
643
644
645
    struct Simplify< Mult<Mult<CValue<M>, X>, CValue<0> > >
    {
      typedef CValue<0> type;

646
      // X = t.term1.term2
647
      static type eval(Mult<Mult<CValue<M>, X>, CValue<0> > const& t)
648
649
      { return type(); }
    };
650

651
652
    /// (M*X)*1 -> M * X
    template<int M, typename X>
653
654
655
656
    struct Simplify< Mult<Mult<CValue<M>, X>, CValue<1> > >
    {
      typedef Mult<CValue<M>, X> type;

657
      // X = t.term1.term2
658
      static type eval(Mult<Mult<CValue<M>, X>, CValue<1> > const& t)
659
      { return CValue<M>() * (t.term1.term2); }
660
661
    };

662
663
    /// (M*X)*-1 -> (-M) * X
    template<int M, typename X>
664
665
666
667
    struct Simplify< Mult<Mult<CValue<M>, X>, CValue<-1> > >
    {
      typedef Mult<CValue<-M>, X> type;

668
      // X = t.term1.term2
669
      static type eval(Mult<Mult<CValue<M>, X>, CValue<-1> > const& t)
670
      { return CValue<-M>() * (t.term1.term2); }
671
    };
672
673


674
675
    /// (X*M)*N -> (N*M) * X
    template<int N, int M, typename X>
676
677
678
679
    struct Simplify< Mult<Mult<X, CValue<M> >, CValue<N> > >
    {
      typedef Mult<CValue<N*M>, X> type;

680
      // X = t.term1.term1
681
      static type eval(Mult<Mult<X, CValue<M> >, CValue<N> > const& t)
682
      { return CValue<N*M>() * (t.term1.term1); }
683
684
    };

685
686
    /// (X*M)*0 -> 0
    template<int M, typename X>
687
688
689
690
    struct Simplify< Mult<Mult<X, CValue<M> >, CValue<0> > >
    {
      typedef CValue<0> type;

691
      // X = t.term1.term1
692
      static type eval(Mult<Mult<X, CValue<M> >, CValue<0> > const& t)
693
694
      { return type(); }
    };
695

696
697
    /// (X*M)*1 -> M * X
    template<int M, typename X>
698
699
700
701
    struct Simplify< Mult<Mult<X, CValue<M> >, CValue<1> > >
    {
      typedef Mult<CValue<M>, X> type;

702
      // X = t.term1.term1
703
      static type eval(Mult<Mult<X, CValue<M> >, CValue<1> > const& t)
704
      { return CValue<M>() * (t.term1.term1); }
705
706
    };

707
708
    /// (X*M)*-1 -> (-M) * X
    template<int M, typename X>
709
710
711
712
    struct Simplify< Mult<Mult<X, CValue<M> >, CValue<-1> > >
    {
      typedef Mult<CValue<-M>, X> type;

713
      // X = t.term1.term1
714
      static type eval(Mult<Mult<X, CValue<M> >, CValue<-1> > const& t)
715
      { return CValue<-M>() * (t.term1.term1); }
716
717
718
    };


719
720
    /// X * (N * Y) -> N * (X * Y)
    template<typename X, int N, typename Y>
721
722
723
724
    struct Simplify< Mult<X, Mult<CValue<N>, Y> > >
    {
      typedef Mult<CValue<N>, Mult<X,Y> > type;

725
726
      // X = t.term1
      // Y = t.term2.term2
727
      static type eval(Mult<X, Mult<CValue<N>, Y> > const& t)
728
729
      { return CValue<N>() * (t.term1 * t.term2.term2); }
    };
730
731


732
733
    /// -(N*X) -> (-N) * X
    template<int N, typename X>
734
735
    struct Simplify< Negative<Mult<CValue<N>,X> > >
    {
736
      typedef Mult<CValue<-N>, typename Simplify<X>::type> type;
737

738
      // X = t.term.term2
739
      static type eval(Negative<Mult<CValue<N>,X> > const& t)
740
      { return CValue<-N>() * simplify(t.term.term2); }
741
742
743
744
745
    };

  } // end namespace expressions


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

755
756
    public:
      typedef Add<S1, S2> type;
757
758

      static type eval(Add<Term1, Term2> const& t)
759
760
761
762
      {
	return simplify(t.term1) + simplify(t.term2);
      }
    };
763

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

771
772
    public:
      typedef Subtract<S1, S2> type;
773
774

      static type eval(Subtract<Term1, Term2> const& t)
775
776
777
778
      {
	return simplify(t.term1) - simplify(t.term2);
      }
    };
779

780
781
    /// A * B -> simplify(A) * simplify(B)
    template<typename Term1, typename Term2>
782
783
    class Simplify< Mult<Term1, Term2> >
    {
784
785
      typedef typename Simplify<Term1>::type S1;
      typedef typename Simplify<Term2>::type S2;
786

787
788
    public:
      typedef Mult<S1, S2> type;
789
790

      static type eval(Mult<Term1, Term2> const& t)
791
792
793
794
      {
	return simplify(t.term1) * simplify(t.term2);
      }
    };
795

796
797
    /// X(A) -> X(simplify(A))
    template<template<class> class Outer, class Inner>
798
799
    class Simplify< Outer<Inner> >
    {
800
      typedef typename Simplify<Inner>::type S;
801

802
803
    public:
      typedef Outer<S> type;
804
805

      static type eval(Outer<Inner> const& t)
806
807
808
809
810
811
812
813
814
815
816
      {
	return type(simplify(t.term));
      }
    };

  } // end namespace expressions


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

817
818
  namespace expressions
  {
819
    template<int N, typename Term, typename Enabled = void>
820
821
    struct SimplifyRecursive
    {
822
823
      typedef typename Simplify< typename SimplifyRecursive<N-1, Term>::type >::type type;
    };
824

825
826
    template<typename Term>
    struct SimplifyRecursive<1, Term>
827
    {
828
829
      typedef typename Simplify< Term >::type type;
    };
830

831
832
    template<int N, typename Term >
    struct SimplifyRecursive<N, Term, typename boost::enable_if_c<(N <= 0)>::type>
833
    {
834
835
      typedef Term type;
    };
836

837
838
  } // end namespace expressions

839
840

  template<int N, typename Term>
841
842
843
  inline typename expressions::SimplifyRecursive<N, Term>::type
  simplify(const Term& t);

844
  template<int N, typename Term>
845
846
847
  inline typename expressions::SimplifyRecursive<N, Term>::type
  simplify(const Term& t, boost::mpl::int_<N>) { return simplify(simplify<N-1>(t)); }

848
  template<typename Term>
849
850
851
  inline typename expressions::SimplifyRecursive<1, Term>::type
  simplify(const Term& t, boost::mpl::int_<1>) { return simplify(t); }

852
  template<typename Term>